gpt4 book ai didi

javascript - AngularJS:使隔离范围指令模板绑定(bind)到父范围

转载 作者:行者123 更新时间:2023-11-29 21:36:20 25 4
gpt4 key购买 nike

我已经为 Angular 的隔离作用域苦苦挣扎了超过 24 小时。这是我的场景:我有一个 ng-repeat迭代我想使用自定义指令从中生成 <select> 的对象数组或 <input>基于 field_type正在迭代的当前对象的属性。这意味着我必须生成模板和 $compile在指令的后链接函数中,因为我无权访问模板函数中的迭代对象。

除了生成的模板实际绑定(bind)到外部范围内的 Controller (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
}
}
}]);

html:

<div ng-controller="ProductController as vm">
<div product-attribute="attrib" ng-repeat="attrib in vm.all_attribs"></div>
</div>

Controller :

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

element.html() 返回一个 html 作为字符串,而不是实际的 dom 内容,所以你插入到你的指令元素中的内容实际上从来没有被 Angular 编译过,解释了你的(不存在的)行为。

element.append(ctrl.compile(template));

应该工作得更好。

对于需要父 Controller 的指令,我也会更改你的 ctrl.compile 方法(在这里重命名为 insertAndCompile)

ctrl.insertAndCompile = function(content) {
$compile(content)($scope, function(clone) {
$element.append(clone);
}
}

你只需要这样调用它:

ctrl.insertAndCompile(template);

而不是我给出的第一个答案的 2 行。

关于javascript - AngularJS:使隔离范围指令模板绑定(bind)到父范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34745155/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com