AngularJS:如何根据任意分层数据创建DOM并绑定到一个模型 [英] AngularJS : how to create DOM and bind to a model based on arbitrary hierarchical data

查看:136
本文介绍了AngularJS:如何根据任意分层数据创建DOM并绑定到一个模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Angularjs:在NG-重复复杂的指令,如何绑定ngModel或ngChecked的指令,并使其发挥作用?
给出的数组:

Angularjs: complex directive in ng-repeat, how to bind the ngModel or ngChecked in directive and make it work? given the array:

+----+-----------+----------+----------+-------+
| id |   name    | parentid | haschild | value |
+----+-----------+----------+----------+-------+
|  1 | parent    | null     | false    | true  |
|  2 | id1 child | 1        | true     | true  |
|  3 | id2 child | 2        | true     | true  |
|  4 | id3 child | 3        | false    | true  |
|  5 | id1 child | 1        | true     | true  |
|  6 | id5 child | 5        | false    | true  |
+----+-----------+----------+----------+-------+
$scope.permission = [
   {"id":1,"name":"parent","value":true,"parentid":"","haschild":false}, 
   {"id":2,"name":"id-1 child","value":true,"parentid":1,"haschild":true},
   {"id":3,"name":"id-2 child","value":true,"parentid":2,"haschild":true},
   {"id":4,"name":"id-3 child","value":true,"parentid":3,"haschild":false},
   {"id":5,"name":"id-1 child","value":true,"parentid":1,"haschild":true},
   {"id":6,"name":"id-5 child","value":true,"parentid":5,"haschild":false}
];

所以在HTML

so in html

<div ng-repeat="x in permission" ng-if="x.parentid == undefined"  has-child="{{x}}"></div>

和指令

myApp.directive('hasChild', function($compile) {
    return function(scope, element, attrs) {
        var j = JSON.parse(attrs.hasChild);
        function generatePermissionDom(thisElement,thisParent)
        {
            angular.forEach(scope.permission,function(o,i){
                if(thisParent.id==o.parentid) 
                {
                    var e = $('<div><input type="checkbox" ng-model="o.value"/>'+o.name+'</div>');
                    generatePermissionDom(e,o);
                    $(thisElement).append(e);
                }
            });
        }

        if(j.haschild)
            angular.forEach(scope.permission,function(o,i){
                if(o.parentid==j.id) 
                {   
                    var e = $('<div><input type="checkbox" ng-model="o.value"/>'+o.name+'</div>');
                    if(o.haschild)
                        generatePermissionDom(e,o);
                    $(element).append(e);
                }
            });

        var p = $(element);
        $compile(element.contents())(scope);
    }
});

那么如何在指令中的模型值绑定?
这里是plunker
http://plnkr.co/edit/QYqfEVaQF8WmUvB1aHB6?p=$p$pview

更多信息:

在haschild重新present的父有子元素

the haschild represent the the parent has child element

例如:

1.people一个拥有多个公司,所以人有子

1.people A own multiple company, so the people A has child

2.然后一体的公司有多个员工,那么该公司拥有孩子。
所以在我的指令,如果这个元素(假设这是元素A)有子再生成子元素和输入绑定到ngModel。

2.then one of the company has multiple employee, then that company has child. so in my directive, if this element(assume this is element A) has child then generate the child element and input and bind to the ngModel.

我的答案:这是我的想法和简单的方式实现
http://plnkr.co/edit/olKb5oBoxv0utlNcBQPg?p=$p$pview

My Answer: this is how i think and simple way to achieve http://plnkr.co/edit/olKb5oBoxv0utlNcBQPg?p=preview

var app = angular.module('plunk', []);
app.directive('generatePermissions', function($compile) {
  return {
    restrict : "E",
    scope : true,
    require : 'ngModel',
    link:function(scope,element,attrs,ngModel)
    {
      function generatePermissionDom(parent,parentElement)
      {

          angular.forEach(scope.list,function(o,i){
              if(parent.id==o.parentid) 
              {
                  var e = angular.element('<div style="border:1px solid red"><input type="checkbox" ng-model="list['+i+'].value"/></div>');
                  if(o.haschild)
                    generatePermissionDom(o,e);
                  parentElement.append(e);
              }
          });
      }
      angular.forEach(scope.list,function(o,i){

        if(o.parentid == null)
        {
          var e = angular.element('<div style="border:1px solid red"><input type="checkbox" ng-model="list['+i+'].value"/></div>');
          if(o.haschild)
            generatePermissionDom(o,e);
          element.append(e);
        }
      });
      var p = $(element);
      $compile(p.contents())(scope);
    }
  }
});


app.controller('MainCtrl', function($scope) {

  $scope.list = [{"id":1,"name":"parent","value":true,"parentid":null,"haschild":true},{"id":2,"name":"id-1 child","value":false,"parentid":1,"haschild":true},{"id":3,"name":"id-2 child","value":false,"parentid":2,"haschild":true},{"id":4,"name":"id-3 child","value":false,"parentid":3,"haschild":false},{"id":5,"name":"id-1 child","value":false,"parentid":1,"haschild":true},{"id":6,"name":"id-5 child","value":false,"parentid":5,"haschild":false}];
  $scope.checkValue = function()
  {
    angular.forEach($scope.list,function(o,i){
      console.log("id:"+o.id+"  name:"+o.name+"  value:"+o.value);
    });
  }
});

HTML

  <body ng-controller="MainCtrl">
    <generate-permissions ng-model="list"></generate-permissions>
    <button ng-click="checkValue()">check</button>
  </body>

不过,我觉得 @ NewDev的答案是正确的答案!

however, i think @NewDev's answer is the correct answer!

推荐答案

基本上,你所追求的是创造一个任意层次的DOM结构,并将其绑定到一些平等的分层数据结构(或视图模型)。

Basically, what you are looking for is to create an arbitrary hierarchical DOM structure and bind it to some equal hierarchical data structure (or ViewModel).

您如何重新present层次结构 - 我会离开它给你。这不是问题的关键。

How you represent your hierarchy - I'll leave it up to you. It's not essential for the question.

为了简单起见,假设我们的层次结构为树形结构模型:

For simplicity, suppose we model the hierarchy as a tree structure:

$scope.tree = {n: "root", v: false, 
      c: [
        {n: "L11", v: false, c: []},
        {n: "L12", v: false, c: [
          {n: "L21", v: true, c: [
            {n: "L31", v: false, c:[]}
            ]}
          ]}
        ]};

您则需要遍历这棵树,并创建一个绑定到某个对象的DOM元素 0 (多多包涵):

You then need to traverse this tree and create DOM elements bound to some object o (bear with me):

<div><input ng-model="o.v">{{o.n}}</div>

然后,这需要对一个范围编译。但由于结构是任意的,你可以为每个节点创建一个新的子范围。

Then, this needs to be compiled against a scope. But since the structure is arbitrary, you could create a new child scope for each node.

那么,什么是 0 0 将是我们对树的每个节点创建每个子范围创建对象。

So, what is o? o will be the object we will create on each child scope created for each node of the tree.

因此​​,假设你有一个递归函数 traverseTree ,即1)创建DOM元素,2)编制针对此范围内,以及3)为每个子作用域儿童。它可能看起来像的东西如下:

So, suppose you have a recursive function traverseTree, that 1) creates the DOM element, 2) compiles against this scope, and 3) creates a child scope for each child. It could look like something as follows:

function traverseTree(n, scope, parent){
  var me = angular.element("<div><input type='checkbox' ng-model='o.v'>{{o.n}}</div>");
  $compile(me)(scope);
  parent.append(me);

  for (var i = 0; i < n.c.length; i++) {
    var c = n.c[i];
    var childScope = scope.$new(true);
    childScope.o = c; // set object "o" on the scope

    traverseTree(c, childScope, me);
  }
}

该指令的链接功能揭开序幕树遍历:

The directive's link function kicks off the tree traversal:

app.directive("tree", function($compile){

  function traverseTree(n, scope, parent){
     // as above
  }

  return {
    restrict: "A",
    scope: {
      root: "=tree"
    },
    link: function(scope, element, attrs){
      var childScope = scope.$new(true);
      childScope.o = scope.root;

      traverseTree(scope.root, childScope, element);
    }
  };

});

的用法是:

<div tree="tree"></div>

下面是一个 plunker

这篇关于AngularJS:如何根据任意分层数据创建DOM并绑定到一个模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆