我使用angularjs指令模板从传入的模型中渲染单个计算值(总和)。
如果我使用模板正常渲染值,则没有问题。 渲染的值只是传递给指令/模板的一堆行对象值的总和,如下所示:
ngApp.directive('subtotal', function() {
return {
restrict: 'E',
scope: {
icRows: '='
},
template: '<div><strong>Sub Total:</strong> {{subTotal()}}</div>',
replace: true,
link: function($scope, $element, $attr) {
$scope.subTotal = function() {
var t = 0;
for(var i=0; i<$scope.icRows.length; i++ ) {
t += $scope.icRows[i].price;
}
return t;
}
}
};
});
<div ng-app="app">
<div ng-controller="MyCtrl">
<div ng-repeat="row in rows">
<input ng-model="row.name" /> | <input ng-model="row.price" />
</div>
<hr/>
<subtotal ic-rows="rows"></subtotal>
</div>
</div>
这很好用。 在这里演示:http://jsfiddle.net/jralston/p8FLV/
我的问题是&#39; subTotal&#39;变量实际上是AJAX调用的结果。当更改“&#39;行”时,需要调用此ajax调用。变量发生。为此,我已将指令中的模板调整为:
<div><strong>Sub Total:</strong> {{subTotalInvoker()}} {{subTotal}}</div>
现在在指令中,函数$ scope.subTotalInvoker()调用ajax调用。来自的回调设置了&#39; subTotal&#39;
的值同样,这完全正常。
在这里演示: http://jsfiddle.net/jralston/wpYjL/
然而,这似乎是一种完全错误的做法。
我尝试在$ scope.icRows中添加$ watch,但它没有用。也许我做错了什么。
非常欢迎任何有关如何做到这一点的指示和/或更正。
由于
约翰
答案 0 :(得分:2)
您可以使用$ watchCollection。 $ watchCollection将在范围内替换整个数组时调用其监视处理程序(即$ scope.icRows = []),在icRows中添加或删除项目时,或替换其中一个项目。
ngApp.directive('subtotal', function() {
return {
restrict: 'E',
scope: {
icRows: '='
},
template: '<div><strong>Sub Total:</strong> {{subTotal}}</div>',
replace: true,
link: function($scope, $element, $attr) {
$scope.subTotal = 0;
$scope.$watchCollection('icRows', function(newVal) {
var t = 0;
for(var i=0; i<newVal.length; i++ ) {
t += newVal[i].price;
}
$scope.subTotal = t;
}
}
};
});
但我怀疑这不合适,因为'。price'可能会改变,而$ watchCollection不会检查项目的属性是否有变化。
如果您需要深度监视(搜索属性和子属性的更改),则使用$ watch并将true作为第二个参数传递:
$scope.$watch('icRows', function(newVal) {
...
}, true);
$ watch(true)具有您需要注意的细微差别。我不确定最近Angular的更新是否有所改变,但是当我使用它时,我发现$ watch(true)不检查数组的添加/删除,或者即使数组完全被替换。虽然它确实做了很深的观察。
过滤器的工作方式类似于$ watchCollection。缺点是当项目的.price属性更改时,过滤器不会更新。
ngApp.filter('subtotal', function() {
return function(input) {
var t = 0;
for (var i= 0; i < input.length; ++i) {
t += parseFloat(input[i].price);
}
return t;
}
});
然后在HTML中,您可以将过滤器应用于范围内的数组:
<div ng-app="app">
<div ng-controller="MyCtrl">
<div ng-repeat="row in rows">
<input ng-model="row.name" /> | <input ng-model="row.price" />
</div>
<hr/>
{{ rows | subtotal | currency }}
</div>
</div>
如果这符合您的要求,则无需自定义指令,您可以使用currency filter进一步将结果格式化为货币。
答案 1 :(得分:1)
您不需要指令或过滤器。只需在控制器中添加subTotal()
功能:
$scope.subTotal = function(rows){
var t = 0;
for(var i=0; i<rows.length; i++ ) {
t += rows[i].price;
}
return t;
}
并在HTML中绑定该函数:
<div><strong>Sub Total:</strong> {{subTotal(rows)}}</div>