Angular动态嵌套指令,将新范围传递给每个子节点?

时间:2014-03-21 21:42:46

标签: javascript angularjs angularjs-directive angularjs-scope angularjs-ng-repeat

我正在尝试在angular中创建一个嵌套指令,该指令由一个可能深度嵌套的大型配置对象指定。我无法弄清楚如何将正确的范围扩展到正确的指令。

我的示例plunkr在这里:http://plnkr.co/edit/AJVaSk2GSxIJvZx3B6UX?p=preview

我认为我可以将当​​前的子配置复制到每个子节点的属性中,并通过指令定义的scope属性获取它,但这看起来有点疯狂 - 它可能很大,可能需要转义。

有没有更好的方法来做到这一点,或者其他我完全错过的东西? (或另一个回答这个问题的SO问题,我错过了......)

非常有责任。

根据评论进行修改以澄清

我正在尝试让每个指令为每个子对象设置范围(或者甚至只是范围上的变量?)。因此'theform'指令获取顶级对象,每个'theforma'指令获取创建它的子节点。也就是说,我有一个'theforma'指令,对象包含'type':'form_a_child_1',另一个指针包含'type':'form_a_child_2'。所以他们是“自足的”,只是真正了解他们创造的对象。

最后,我想要一个提交按钮,以及从动态表单元素中收集所有信息的方法......但那是另一个问题。

1 个答案:

答案 0 :(得分:0)

昨天被电子游戏分散注意力希望解决这个问题并不是非常迫切,但我现在在这里发布了答案。这可能不是您想要做的,但应该了解隔离范围。

http://plnkr.co/edit/FmpixQrBmvWJlB2wBRXW?p=preview

JS

// Code goes here

var app = angular.module('formtest', []);

app.controller("MyCtrl", function($scope){
  $scope.form_config = { 
      // first level children are the tabs
      children    : [ 
          {   
              type : 'form_a',
              label : 'Form A',
              children : [ 
                  {   
                      type : 'form_a_child_1',
                      label : 'Form A Child 1',
                  },  
                  {   
                      type : 'form_a_child_2',
                      label : 'Form A Child 2',
                  },  
              ]   
          },  
          {   
              type : 'form_b',
              label : 'Form B',
              children : [ 
                  {   
                      type : 'form_b_child_1',
                      label : 'Form B Child 1',
                  },  
                  {   
                      type : 'form_b_child_2',
                      label : 'Form B Child 2',
                  },  
              ]   
          },  
      ]   
  };  
})




/**
 * Should display the top level form info.
 * Form A and Form B
 */
app.directive('theform', function() {
    return {
        restrict : 'E',
        scope:{formConfig:"="},
        template : '<div>'+
                      '<div>'+
                          '<div><theforma form-a="formAData"></div>'+
                          '<div><theformb form-b="formBData"></div>'+
                      '</div>'+
                    '</div>',
        replace  : true,
        link     : function(scope, $el, $attrs) {
            //$scope.form_config = form_config;
            scope.formAData = [];
            scope.formBData = [];
            scope.$watch("formConfig", function(newVal){
              if(newVal)
              {
                for(var i=0; i<scope.formConfig.children.length; i++)
                {
                  var curElement = scope.formConfig.children[i];
                  console.log(curElement);
                  if(curElement.type == "form_a")
                    scope.formAData = curElement;
                  else
                    scope.formBData = curElement;
                }
              }
              console.log(scope.formAData);
            })

        }   
    };  
});

/**
 * I want to display the children of Form A
 */
app.directive('theforma', function() {
    return {
        restrict : 'E',
        scope : {formA : "="},
        template : '<div>'+
                        '<div ng-repeat="child in formA.children">'+
                            'Form A: {{child.label}}'+
                        '</div>' +
                   '</div>',
        replace  : true,
        link     : function(scope, $el, $attrs) {
            //console.log(scope.formA)
        }   
    };  
});

/**
 * I want to display the children of Form B
 */
app.directive('theformb', function() {
    return {
        restrict : 'E',
        scope : {formB : "="},
        template : '<div>'+
                            '<div ng-repeat="child in formB.children">'+
                                'Form B: {{child.label}}'+
                            '</div>' +
                        '</div>',
        replace  : true,
        link     : function(scope, $el, $attrs) {
            scope.children = scope.formB;
        }   
    };  
});

HTML

<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@*" data-semver="1.2.14" src="http://code.angularjs.org/1.2.14/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app='formtest' ng-controller="MyCtrl">
    <div>
      <theform form-config="form_config"></theform>
    </div>
  </body>

</html>

当指出指令的范围时,您可以在属性名称(=,&amp;或@)之后的引号中放置三个选项。 =使属性双向绑定,因此如果传入Javascript对象,则对该对象进行更改,@将从您传入的表达式中获取字符串结果并传递该字符串,&amp;允许您传递对要在原始范围(控制器或使用它的另一个指令)上执行的函数的引用。