ng-include 指令下的控制器

在工作中遇到了一个需求 —— 使用angular在一个页面中,要求点击左侧菜单显示的页面需要以tab(选项卡)的形式展现到页面中,这样方便用户使用不同的功能能来回切换。与ext tab选项卡的效果一致。

 

 

 

由于前期选型,使用的是angular技术作为前端的框架,如果使用ui-router的方式,这样不满足需求,因为内容会被重置,不能保留之前用户的操作,所以必须考虑其他的解决办法。

最后,找到了 ng-include 指令,异步加载HTML代码,这样才能将用户的操作保留在浏览器中。

代码如下:

<ng-include src="'../template/common/orderList.html'" ng-controller="orderListController"></ng-include>
扫描二维码关注公众号,回复: 306503 查看本文章
/**
 * 创建了一个indexController
 */
angular.module("klwkOmsApp")
    .controller("orderListController", ["$scope", "$rootScope", "$state", "WAP_CONFIG",
        function ($scope, $rootScope, $state, WAP_CONFIG) {
            
            function init() {
                //加载下拉框
                $('#orderList').selectPlug();

                //点击高级搜索展开
                $('.advancedSearchBtn').click(function () {
                    $('#simpleSearch').hide();
                    $('#advancedSearch').slideDown(500);
                });
                //点击取消 高级搜索收起
                $('.advancedSearchCancelBtn').click(function () {
                    $('#simpleSearch').show();
                    $('#advancedSearch').slideUp(200);
                });
                //制单时间展开收起
                $('.timeSpreadBtn').click(function () {
                    if($(this).html()==='展开'){
                        $('.timeSpread').slideDown(100);
                        $(this).html('收起');
                        $('.hide1').hide();
                        $('.hide2').css('display','inline-block');
                    }else{
                        $('.timeSpread').slideUp(100);
                        $(this).html('展开');
                        $('.hide1').show();
                        $('.hide2').hide();
                    }
                })

            }

            init();


        }]);

1、src 是引入文件的地址,如果有单引号,表示是字符串,如果没有引号,表示是变量,

注意:路径是相对于文件本身,不是模板的路径。

2、ng-controller 表示引入的控制器的名字.

只需要在模块化中引入该控制器即可。

上面这种方式如果是第一次刷新加载就没有什么问题,但是,如果我是页面加载完之后异步加载HTML代码,页面就会报错,在是因为 compile会对HTML代码进行编译,将指令转为浏览器认识的HTML代码,但是代码转义完了之后还没有将代码放到DOM树种,然后controller会对DOM树做相关的事件绑定,例如绑定事件等,一旦找不相关的DOM节点,就有可能报错,导致controller执行不成功,无法完成双向绑定。

 下面这个例子是对上面问题解决办法:

/**
 * 创建了一个indexController
 * */
angular.module("klwkOmsApp")
.controller('publicController', ["$scope","$rootScope","$state","WAP_CONFIG","$compile",
	function($scope,$rootScope, $state, WAP_CONFIG,$compile) {

		var stateController = {
			'index.orderList':{
				url: '/orderList',
				templateUrl:'../template/orderManage/orderList.html',
				controller: "orderListController"
			},
			'index.allocationNoticeBill':{
				url: '/allocationNoticeBill',
				templateUrl:'../template/orderManage/allocationNoticeBill.html',
				controller: "allocationNoticeBillController"
			}
		};

		$scope.topTabs = {};
		// 添加 tab 面板
		$scope.addTabPanel = function(uiSref){
			// 添加 tab 导航
			if($scope.topTabs[uiSref] === undefined){
				$scope.topTabs[uiSref] = uiSref;

				var el=$compile('<ng-include id="'+uiSref+'_panel" src="\''+stateController[uiSref].templateUrl+'\'" onload="loadController(\''+uiSref+'\')" ></ng-include>')($scope);
				$("#topTabPanel").append(el);
				console.dir(el);
			}
		};

		// ng-include 代码加载完毕之后执行的代码
		$scope.loadController = function(uiSref){
			console.log("loadController : " + uiSref);
			$compile('<div ng-controller="allocationNoticeBillController">'+$("#"+uiSref+"_panel").contents()+'</div>')($scope.$new());
		}


	}
]);

 代码说明:

1、使用ng-clude 先引用 src文件,页面加载进来之后,执行onload方法

2、onload 方法将编译之后的 html包裹在 一个有ng-controller指令的div中,代码如下

 <div ng-controller="allocationNoticeBillController">include编译之后的代码</div>

 上面这种方式非常的繁琐,逻辑也复杂,不便于理解,最后和同事讨论,找到了一个简单的解决办法

在ng-include的目标页面中最外层添加一个div,这个div 中有ng-controller标签

<!doctype html>
<html ng-app="HelloAngular">
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <div ng-controller="helloNgCtrl">
            <p>{{greeting.text}},Angular</p>
            <button ng-click="addFile()">动态添加文件</button>

            <div id="newFileContent">
                <div ng-include="'file1.html'"></div>
            </div>
        </div>

    </body>
    <script src="js/angular-1.3.0.js"></script>
    <script src="NgModule1.js"></script>
</html>
var helloModule=angular.module('HelloAngular', []);
helloModule.controller('helloNgCtrl', ['$scope', function($scope){
    $scope.greeting = {
        text: 'Hello'
    };

    $scope.addFile = function(){

    }
}]);

helloModule.controller('newFile', ['$scope', function($scope){
    $scope.username = "huangbiao";
    $scope.newFunc = function(){
      alert(this.username);
    };

}]);

 备注:html不能有body标签,否则controller执行不成功,原因还没有深入了解,现象如此。

了解angular的双向绑定的步骤:

1、先用$compile服务 将HTML编译成目标HTML

2、然后执行指令的 link函数,将目标HTML 与 $scope对象关联起来,最终实现双向绑定。 

猜你喜欢

转载自hbiao68.iteye.com/blog/2363620