我想用自定义指令更新带有属性值的模型值。 让我们想象我有4个数字。我想做以下事情:
公式以custom指令的属性值表示。 我在Angular中没那么有经验并且有一些部分工作的解决方案,但我认为我的方向错误,所以我会在没有自定义指令的情况下发布代码。
以下是我试图构建自定义指令的代码,编写该指令(公式)的最佳方法是什么?
编辑:带有公式指令的输入字段将是只读的,它们只有一个目的 - 根据公式重新计算其他字段的值。
<!DOCTYPE html>
<html ng-app>
<head>
<script data-require="angular.js@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Cascade sum example</h1>
<input ng-model="A1" type="number">
<input ng-model="A2" type="number">
<input ng-model="A3" type="number">
<input ng-model="A4" type="number">
<input ng-model="A5" type="number" formula="A1+A2" readonly>
<input ng-model="A6" type="number" formula="A3+A4" readonly>
<input ng-model="A7" type="number" formula="A5+A6" readonly>
</body>
</html>
&#13;
答案 0 :(得分:2)
我认为你不需要编写自己的指令来解决这样的问题。 Angular允许您评估html页面内的表达式。例如,您可以使用您的ng模型值来内联评估您的公式,
<input ng-model="A5" type="number" value={{A1+A2}}>
angular将取此并将其替换为A1 + A2的值。
答案 1 :(得分:2)
(解决方案的工作人员 - http://plnkr.co/edit/nhlI4fSsK58mWS18RgUh?p=preview)
这是一个简单的模板来说明用法:
<h1>Cascade sum example</h1>
<ul>
<li ng-repeat="(key, input) in inputs">
<input type="number" ng-model="input.value"
formula="::input.formulaFn"/>
<span>{{::key}}</span>
<span ng-if="::input.formula">({{input.formula}})</span>
</li>
</ul>
首先,我们从数据库中获取输入,并为每个输入创建一个公式函数。调用时,公式函数会为给定的公式生成一个值:
Inputs.getAll()
.then(function(inputs) {
$scope.inputs = inputs
_.each($scope.inputs, function(input) {
if (input.formula) {
input.formulaFn = parseFormula(input.formula)
}
})
})
function parseFormula(expr) {
var parsed = $parse(expr)
return function apply() {
return parsed($scope.values)
}
}
肉是parseFormula。它使用angular的$ parse将表达式(例如'A1 + A2')转换为函数(plus(a,b)
)。如果您使用包含属性parsed
和A1
的对象调用A2
,则会生成其值的总和 - 这是apply()
正在执行的操作。
我们当前的对象$scope.inputs
不能用于为我们的解析表达式提供所需的值(它需要看起来像'A1': 1
,而不是'A1': { ... }
)。不幸的是,我们不能使用相同的对象来保存我们的值和我们的ng模型,因为角度ng-repeat
具有绑定和基元的特性(你可以在这里阅读更多关于它的信息 - https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-repeat - 这也被非正式地称为“点规则”)。这就是为什么我们需要$scope.inputs
(提供我们的可绑定模型)和同步$scope.values
,我们将用于表达式。
$scope.values = {}
$scope.$watch('inputs', function(value) {
$scope.values = _.mapValues($scope.inputs, function(input) {
return input.value
})
}, true)
该指令相当简单。如果元素上有一个公式(这实际上是我们之前创建的公式 functions ),它将会观察它(这意味着每个摘要都会调用该函数)。一旦公式产生一个新值(例如'A1 + A2',A1或A2被更改),那么我们只需将ngModel与它同步。
.directive('formula', function() {
return {
scope: {
formula: '=',
},
require: 'ngModel',
link: function(scope, element, attrs, ngModelCtrl) {
if (!scope.formula) return
element.attr('readonly', true)
scope.$watch(scope.formula, function(value) {
ngModelCtrl.$setViewValue(value)
ngModelCtrl.$render()
})
}
}
})