AngularJS - 在带有重复和动态 html 控件的指令中使用 ng-model

AngularJS - using ng-model inside a directive with repeats and dynamic html controls

本文关键字:指令 控件 ng-model html 动态 AngularJS      更新时间:2023-09-26

我为网格编写了一个指令,我希望能够传入一个列定义,该列定义可能是带有ng-model和ng-click指令的html控件。 我不断收到"错误:[$rootScope:infdig] 达到 10 次 $digest() 次迭代。中止!"并且 ng 模型不具有约束力。 我在这里整理了一个简单的 plunker:https://plnkr.co/edit/ue1lQqvrUE0M5zZXsg8a?p=preview 作为一个例子。

// Code goes here
var myApp = angular.module('myApp', ['ngSanitize']);
myApp.controller('MyCtrl', function($scope) {
  $scope.myGridConfig = {};
  $scope.myGridConfig.columnDefs = [{
    field: 'facility',
    headerName: 'Facility'
  }, {
    field: 'code',
    headerName: 'Code'
  }, {
    field: 'cost',
    headerName: 'Cost'
  }, {
    field: 'conditionRating',
    headerName: 'Conditional Rating'
  }, {
    field: 'extent',
    headerName: 'Extent'
  }, {
    field: 'planYear',
    headerName: 'Plan Year',
    cellRenderer: function(row, de) {
      return '<input type="checkbox" ng-model="row.selected" />';
    }
  }];
  $scope.myGridConfig.rowCollection = [{
    facility: "Atlanta",
    code: "C-RD34",
    cost: 540000,
    conditionRating: 52,
    extent: 100,
    planYear: 2014
  }, {
    facility: "Seattle",
    code: "CRDm-4",
    cost: 23000,
    conditionRating: 40,
    extent: 88,
    planYear: 2014
  }, {
    facility: "Austin",
    code: "GR-5",
    cost: 1200000,
    conditionRating: 92,
    extent: 90,
    planYear: 2014
  }];
});
myApp.directive('cellRender', function($compile) {
  var directive = {};
  directive.restrict = 'A';
  directive.scope = {
    cellRender: "="
  }
  directive.replace = true;
  //directive.template = "<div>{{renderThis(cellRender.row, cellRender.def)}}</div>";
  directive.template = "<div>{{renderThis()}}</div>";
  directive.link = function(scope, ele, attrs) {
    scope.renderThis = function() {
      if (scope.cellRender.def.cellRenderer) {
        ele.html(scope.cellRender.def.cellRenderer(scope.cellRender.row, scope.cellRender.def));
        $compile(ele.contents())(scope);
      }
      return scope.cellRender.row[scope.cellRender.def.field];
    };
    /*scope.renderThis = function(r, d) {
			if (d.cellRenderer)
			{
				ele.html(d.cellRenderer(r,d));
				$compile(ele.contents())(scope);
			}
			return r[d.field];
		};*/
  };
  return directive;
});
myApp.directive('grid', function($compile) {
  var directive = {};
  directive.restrict = 'EA';
  directive.scope = {
    gridConfig: "="
  }
  directive.template = "<table style='border: 1px solid black;'>'n" +
    "<thead>'n" +
    "<tr>'n" +
    "<th ng-repeat='"def in gridConfig.columnDefs'" >{{def.headerName}}</th>'n" +
    "</tr>'n" +
    "</thead>'n" +
    "<tbody>'n" +
    "<tr ng-repeat='"row in gridConfig.rowCollection'">'n" +
    "<td ng-repeat='"def in gridConfig.columnDefs'" ><div cell-render='"{'row': row, 'def' :def}'"></div></td>'n" +
    "</tr>'n" +
    "</tbody>'n" +
    "</table>";
  directive.link = function(scope, ele, attrs) {
    angular.forEach(scope.gridConfig.rowCollection, function(rr) {
      rr.selected = true;
    });
  };
  return directive;
});
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Test dynamic ngModel</title>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.29/angular.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.29/angular-sanitize.js"></script>
  <script type="text/javascript" src="script.js"></script>
</head>
<body ng-app="myApp">
  <div ng-controller="MyCtrl">
    <div grid="" grid-config="myGridConfig"></div>
    <div>Row 2 selected: {{myGridConfig.rowCollection[1].selected}}</div>
  </div>
</body>
</html>

我想出了一个解决方案,这是 plunker。 http://plnkr.co/edit/6boouR50HiCh2BPuHEp1?p=preview

如果有更好或更清洁的方法,欢迎提出建议。

var myApp = angular.module('myApp',['ngSanitize']);
myApp.controller('MyCtrl', function($scope) {
        $scope.myGridConfig = {};
        $scope.myGridConfig.columnDefs = [{field: 'facility', headerName: 'Facility'},
        {field: 'code', headerName: 'Code'},
        {field: 'cost', headerName: 'Cost'},
        {field: 'conditionRating', headerName: 'Conditional Rating'},
        {field: 'extent', headerName: 'Extent'},
        {field: 'planYear', headerName: 'Plan Year', cellTemplate: '<input type='"checkbox'" ng-model='"row.selected'" ng-click='"clickMe()'"></input>'}];
        $scope.myGridConfig.rowCollection = [{
          facility: "Atlanta",
          code: "C-RD34",
          cost: 540000,
          conditionRating: 52,
          extent: 100,
          planYear: 2014
        }, {
          facility: "Seattle",
          code: "CRDm-4",
          cost: 23000,
          conditionRating: 40,
          extent: 88,
          planYear: 2014
        }, {
          facility: "Austin",
          code: "GR-5",
          cost: 1200000,
          conditionRating: 92,
          extent: 90,
          planYear: 2014
        }];
		
		angular.forEach($scope.myGridConfig.rowCollection, function(rr) {
                        rr.selected = true;
                });
});
myApp.directive('customCellTemplate', function($compile, $sce, $parse) {
        var directive = {};
        directive.restrict = 'A';
        directive.scope = {
                def : "=",
				row: "="				
        };
        directive.replace = true;
        directive.link = function(scope, ele, attrs) {
				ele.html(scope.def.cellTemplate);
				$compile(ele.contents())(scope);
				
				
				scope.clickMe = function() {
					alert(scope.row.cost);
				};
        };
        return directive;
});
myApp.directive('grid', function($compile, $sce, $parse) {
        var directive = {};
        directive.restrict = 'EA';
		directive.replace=true;
        directive.scope = {
                gridConfig : "="
        }
        directive.template = "<table style='border: 2px solid black;'>'n" +
                "<thead>'n" +
                        "<tr>'n" +
                                "<th ng-repeat='"def in gridConfig.columnDefs'" >{{def.headerName}}</th>'n" +
                        "</tr>'n" +
                "</thead>'n" +
                "<tbody>'n" +
                        "<tr ng-repeat='"row in gridConfig.rowCollection'">'n" +
                                "<td ng-repeat='"def in gridConfig.columnDefs'" >'n" +
									"<div custom-cell-template='"'" ng-if='"def['cellTemplate']'" row='"row'" def='"def'"></div><div ng-if='"!def['cellTemplate']'">{{row[def.field]}}</div>'n" +
								"</div></td>'n" +
                        "</tr>'n" +
                "</tbody>'n" +
        "</table>";
        return directive;
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Angular-scrollable-table directive demo</title>
    <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css"
        rel="stylesheet" type="text/css">
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.29/angular.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.29/angular-sanitize.js"></script>
    <script type="text/javascript" src="script.js"></script>
  </head>
  <body ng-app="myApp">
    <div ng-controller="MyCtrl">
      <div grid="" grid-config="myGridConfig"></div>
          2{{myGridConfig.rowCollection[1].selected}}
    </div>
  </body>
</html>