Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/444.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript AngularJS:使隔离作用域指令模板绑定到父作用域_Javascript_Angularjs_Angularjs Directive_Ng Repeat_Isolate Scope - Fatal编程技术网

Javascript AngularJS:使隔离作用域指令模板绑定到父作用域

Javascript AngularJS:使隔离作用域指令模板绑定到父作用域,javascript,angularjs,angularjs-directive,ng-repeat,isolate-scope,Javascript,Angularjs,Angularjs Directive,Ng Repeat,Isolate Scope,我已经和Angular的隔离镜斗争了24个多小时了。下面是我的场景:我有一个ng repeat迭代对象数组,我想从中使用自定义指令,根据当前迭代对象的字段类型属性生成或。这意味着我必须在指令的post-link函数中生成模板和$compile,因为我无法访问模板函数中的迭代对象 除了生成的模板实际绑定到我的外部作用域中的控制器(vm)之外,一切都按预期工作。我认为我的方法(将其添加到模板字符串中:ng model=“vm.prodAttribs.+attr.attribute_code+”)可能

我已经和Angular的隔离镜斗争了24个多小时了。下面是我的场景:我有一个
ng repeat
迭代对象数组,我想从中使用自定义指令,根据当前迭代对象的
字段类型
属性生成
。这意味着我必须在指令的post-link函数中生成模板和
$compile
,因为我无法访问模板函数中的迭代对象

除了生成的模板实际绑定到我的外部作用域中的控制器(vm)之外,一切都按预期工作。我认为我的方法(将其添加到模板字符串中:
ng model=“vm.prodAttribs.+attr.attribute_code+”
)可能是错误的,并且希望指针指向正确的方向。谢谢

请参见下面的示例代码:

指令:

directives.directive('productAttributeWrapper', ['$compile',  function($compile){
    //this directive exists solely to provide 'productAttribute' directive access to the parent scope
    return {
        restrict: 'A',
        scope: false,
        controller: function($scope, $element, $attrs){
            this.compile = function (element) {
                $compile(element)($scope);
                console.log('$scope.prodAttribs in directive: ', $scope.prodAttribs);
            };
        }
    }
}]);

directives.directive('productAttribute', ['$compile',  function($compile){
    return {
        restrict: 'A',
        require: '^productAttributeWrapper', //use the wrapper's controller
        scope: {
            attribModel: '=',
            prodAttribute: '=productAttribute', //binding to the model being iterated by ng-repeat
        },
        link: function(scope, element, attrs, ctrl){
            var template = '';
            var attr = scope.prodAttribute;
            if(!attr) return;

            switch(attr.attribute_field_type.toLowerCase()){
                case 'textfield':
                    template = 
                        '<input type="text" id="'+attr.attribute_code+'" ng-model="vm.prodAttribs.' + attr.attribute_code +'">';
                    break;
                case 'dropdown':
                    template = [
                        '<select class="cvl" id="'+attr.attribute_code+'" ng-model="vm.prodAttribs.' + attr.attribute_code +'">',
                            '#cvl_option_values',
                        '\n</select>'
                    ].join('');
                    var options = '\n<option value="">Select One</option>';
                    for(var i=0; i<attr.cvl_option_values.length; i++) {
                        var optionVal = attr.cvl_option_values[i].value;
                        options += '\n<option value="'+optionVal+'">' + attr.cvl_option_values[i].value + '</option>';
                    }
                    template = template.replace('#cvl_option_values', options);
                    break;
            }
            element.html(template);
            ctrl.compile(element.html());  //try to bind template to outer scope
        }
    }
}]);
<div ng-controller="ProductController as vm">
    <div product-attribute="attrib" ng-repeat="attrib in vm.all_attribs"></div>
</div>
app.controller('ProductDetailsController', function(){
    var vm = this;
    //also added the property to $scope to see if i could access it there
    $scope.prodAttribs = vm.prodAttribs = {
            name: '',
            description: '',
            price: [0.0],
            condition: null
    }
    vm.all_attributes = [
        {
          "attribute_id": 1210,
          "attribute_display_name": "Product Type",
          "attribute_code": "product_type",
          "attribute_field_type": "Textfield",
          "cvl_option_values": [],
          "validation_rules": {}
        },
        {
          "attribute_id": 902,
          "attribute_display_name": "VAT",
          "attribute_code": "vat",
          "attribute_field_type": "dropdown",
          "cvl_option_values": [
            {
              "option_id": "5",
              "value": "5%"
            },
            {
              "option_id": "6",
              "value": "Exempt"
            }
          ],
          "validation_rules": {}
    }];
})

问题可能在于:

element.html(template);
ctrl.compile(element.html());  //try to bind template to outer scope
html()以字符串的形式返回html,而不是实际的dom内容,因此插入到指令元素中的内容永远不会被angular编译,从而解释您(不存在)的行为

element.append(ctrl.compile(template));
应该会更好

对于需要父控制器的指令,我还将更改您的ctrl.compile方法(此处重命名为insertAndCompile)

你可以这样称呼它:

ctrl.insertAndCompile(template);

我建议使用模板,而不是手动编译html。方法简单得多:

控制器将包含数据声明:

app.controller('ProductDetailsController', function($scope) {
  $scope.prodAttribs = {
    name: '',
    description: '',
    price: [0.0],
    condition: null
  }
  $scope.all_attribs = [{
    "attribute_id": 1210,
    "attribute_display_name": "Product Type",
    "attribute_code": "product_type",
    "attribute_field_type": "Textfield",
    "cvl_option_values": [],
    "validation_rules": {}
  }, {
    "attribute_id": 902,
    "attribute_display_name": "VAT",
    "attribute_code": "vat",
    "attribute_field_type": "dropdown",
    "cvl_option_values": [{
      "option_id": "5",
      "value": "5%"
    }, {
      "option_id": "6",
      "value": "Exempt"
    }],
    "validation_rules": {}
  }];
});
您的指令将非常简单:

app.directive('productAttribute', function() {
  return {
    restrict: 'A',
    scope: {
      attribModel: '=',
      prodAttribute: '=productAttribute'
    },
    templateUrl: 'template.html',
    controller: function($scope) {}

  }
});
template.html
将是:

<div>
  <select ng-show="prodAttribute.attribute_field_type.toLowerCase() == 'dropdown'" class="cvl" id="" ng-model="prodAttribs.attribute_code">
    <option value="">Select One</option>
    <option ng-repeat="item in prodAttribute.cvl_option_values track by $index"  value="{{item.value}}">{{item.value}}</option>
  </select>
  <input ng-show="prodAttribute.attribute_field_type.toLowerCase() == 'textfield'" type="text" id="{{prodAttribute.attribute_code}}" ng-model="prodAttribute.attribute_code">
</div> 

选择一个
{{item.value}}
以及您的html:

<div ng-controller="ProductController"> 
    <div ng-repeat="attrib in all_attribs" product-attribute="attrib">{{attrib}}</div>
</div>

{{attrib}}

谢谢@Pierre Gaywallet
ctrl.insertAndCompile()
是我需要的修复程序!太痛苦了,这么少的东西让我彻夜未眠。我不想创建臃肿的html,因为页面上会有很多这样的控件,导致很多不必要的隐藏输入元素。我在link函数中使用它的原因。尽管如此,还是要感谢你为这个答案所付出的努力,这是有道理的,但是用这样的方式来创造直接的答案实在是太肮脏了。
<div ng-controller="ProductController"> 
    <div ng-repeat="attrib in all_attribs" product-attribute="attrib">{{attrib}}</div>
</div>