所以我的用例是:
cols = [{field="product.productId"},{field="product.productPrice"}];
data = {products:[{product:{productId:1,productPrice:10}, {product:{productId:2, productPrice:15}}]}
我想做的是:
<div ng-repeat="product in data.products">
<div ng-repeat="col in cols">
<input type="text" ng-model="product[col.field]"></>
</div>
</div>
现在如果col.field只是'someField'而不是'some.deep.field',那么这将有效。因为该字段有许多元素,所以如果我不想要通用并且允许我的数据和列更改,那么执行ng-model的正确方法将是“product [some] [deep] [field]”。我尝试过这种方法,它适用于非通用用例。
我试图让它变得通用:
重新编译我的'input'元素。这就创造了完美的HTML E.G它有ng-model =“product ['some'] ['deep'] ['field']”就可以了,但绝不会受到任何限制。也许我在这里编写错误的范围?我已经尝试过在这一点上添加属性ng-init =“hello ='嘿'”ng-model =“hello”并且它正常工作和绑定...所以我觉得我在这里缺少关于范围的东西。
compile: function (templateElement) {
templateElement[0].removeAttribute('recursive-model');
templateElement[0].removeAttribute('recursive-model-accessor');
return {
pre: function (scope, element, attrs) {
function convertDotToMultiBracketNotation(dotNote) {
var ret = [];
var arrayOfDots = dotNote.split('.');
for (i = 0; i < arrayOfDots.length; i++) {
ret.push("['" + arrayOfDots[i] + "']");
}
return ret.join('');
}
if (attrs.recursiveModel && attrs.recursiveModelAccessor) {
scope[scope.recursiveModel] = scope.ngModel;
element[0].setAttribute('ng-model', scope.recursiveModel + convertDotToMultiBracketNotation(scope.recursiveModelAccessor));
var res = $compile(element[0])(scope);
console.info('new compiled element:', res);
return res;
}
}
}
}
使用NgModelController进行格式化和解析。在这种情况下,我将整个'row'对象放入ng-model中,然后使用formatter / parser来处理我感兴趣的1字段。这一直有效,直到您清除该字段。在那一点上,它似乎完全消灭了modelCtrl。$ modelValue。 换句话说 - 我的console.log说:
将字段设置为行[object]
上的val'Text'在[object]
行上将字段设置为val'Tex'在[object]
行上将字段设置为val'Te'在[object]
行上将字段设置为val'T'在行[object]
上将字段设置为val''将字段设置为'未定义行
上的'A'
link: function (scope, element, attrs, ctrls) {
if(ctrls[2] && scope.recursiveModelAccessor){
var modelCtrl = ctrls[2];
modelCtrl.$formatters.push(function (inputValue) {
function getValue(object, string){
var explodedString = string.split('.');
for (i = 0, l = explodedString.length; i < l; i++) {
object = object[explodedString[i]];
}
return object;
};
function getValueRecursive (row, field) {
if (field instanceof Array) {
var ret = [];
for (var i = 0; i < col.field.length; i++) {
ret.push(getValue(row, field[i]));
}
return ret.join('/');
} else {
return getValue(row, field);
}
};
return getValueRecursive(modelCtrl.$modelValue, scope.recursiveModelAccessor);
});
modelCtrl.$parsers.push(function (inputValue) {
function setValueRecursive (row, field, newValue) {
if (field instanceof Array) {
var firstField = field.shift();
if(field.length==1){
field = field[0];
}
setValueRecursive(row[firstField], field, newValue);
} else {
console.log("Setting "+field+" to val:"+newValue+" on row:"+row);
row[field]=newValue;
}
};
setValueRecursive(modelCtrl.$modelValue, scope.recursiveModelAccessor.split('.'), modelCtrl.$viewValue);
return modelCtrl.$modelValue;
});
答案 0 :(得分:1)
长话短说(浪费了8个小时) - 不要把ng-model =&#34;&#34;&#34;在您的对象上,如果您计划在修改ng-model属性后重新编译。
重新绑定ngModel的工作指令(只是不要在你的对象上拥有该属性!)
<div ng-repeat="product in data.products">
<div ng-repeat="col in cols">
<input type="text" recursive-model="product" recursive-model-accessor="some.deep.field"></input>
</div>
</div>
确保你没有ng-model =&#34;&#34;。
当然 - 如果存在ng-model属性,100%完美的解决方案会抛出异常:)
module.directive('rebindModel', ['$compile','$parse',function($compile,$parse){
return {
restrict:'A',
compile: function (templateElement) {
templateElement[0].removeAttribute('recursive-model');
templateElement[0].removeAttribute('recursive-model-accessor');
return {
post: function (scope, element, attrs) {
function convertDotToMultiBracketNotation(dotNote) {
var ret = [];
var arrayOfDots = dotNote.split('.');
for (i = 0; i < arrayOfDots.length; i++) {
ret.push("['" + arrayOfDots[i] + "']");
}
return ret.join('');
}
if (attrs.recursiveModel && attrs.recursiveModelAccessor) {
var parsedModelAccessor = $parse(attrs.recursiveModelAccessor)
var modelAccessor = parsedModelAccessor(scope);
element[0].setAttribute('ng-model', attrs.recursiveModel + convertDotToMultiBracketNotation(modelAccessor));
var res = $compile(element[0])(scope);
return res;
}
}
}
},
}
}]);