如果我有一个没有模板的AngularJS指令,并且我希望它在当前作用域上设置属性,那么最好的方法是什么?
例如,一个计算按钮点击次数的指令:
<button twoway="counter">Click Me</button>
<p>Click Count: {{ counter }}</p>
使用指令将点击次数分配给双向属性中的表达式:
.directive('twoway', [
'$parse',
function($parse) {
return {
scope: false,
link: function(scope, elem, attrs) {
elem.on('click', function() {
var current = scope.$eval(attrs.twoway) || 0;
$parse(attrs.twoway).assign(scope, ++current);
scope.$apply();
});
}
};
}
])
有更好的方法吗?从我所读到的,一个孤立的范围将是矫枉过正,但我需要一个儿童范围?除了使用$parse
之外,是否有更简洁的方法来回写指令属性中定义的范围变量。我觉得我这样做太难了。
Full Plunker here。
答案 0 :(得分:30)
为什么隔离范围过大?它对这种事情非常有用:
scope: {
"twoway": "=" // two way binding
},
对于这个问题,这是一个非常惯用的角度解决方案,所以这就是我坚持的。
答案 1 :(得分:23)
我很惊讶没有人提到ng-model
,这是进行双数据绑定的默认指令。也许它不是那么出名,但链接功能有第四个参数:
angular.module('directive-binding', [])
.directive('twoway',
function() {
return {
require: '?ngModel',
link: function(scope, elem, attrs, ngModel) {
elem.on('click', function() {
var counter = ngModel.$viewValue ? ngModel.$viewValue : 0
ngModel.$setViewValue(++counter);
scope.$apply();
});
}
};
}
);
在你的观点
<button twoway ng-model="counter">Click Me</button>
<p>Click Count: {{ counter }}</p>
第四个参数是ngModelController的API,它有许多用于处理(例如解析和格式化)以及在指令和范围之间共享数据的用途。
这是更新后的Plunker。
答案 2 :(得分:2)
如果不使用$parse
angular.module('directive-binding', []).directive('twoway', [function () {
return {
scope: false,
link: function (scope, elem, attrs) {
elem.on('click', function () {
scope[attrs.twoway] = scope[attrs.twoway] == null ? 1 : scope[attrs.twoway] + 1;
scope.$apply();
});
}
};
}]);
答案 3 :(得分:2)
应用双向绑定的一种好方法是使用指令组件。这是我的解决方案。它允许使用ng-repeat和可扩展的数据绑定。
<强> HTML 强>
<body ng-controller='MainCtrl'>
Data: {{data}}
<hr>
<mydirective name='data[0]'></mydirective>
<hr>
<mydirective name='data[1]'></mydirective>
</body>
<强>控制器强>
app.controller('MainCtrl', function($scope) {
$scope.data = [];
$scope.data[0] = 'Marco';
$scope.data[1] = 'Billy';
});
<强>指令强>
app.directive("mydirective", function(){
return {
restrict: "EA",
scope: {name: '='},
template: "<div>Your name is : {{name}}</div>"+
"Change your name : <input type='text' ng-model='name' />"
};
});
对于计数器,可以使用相同的方法完成。
答案 4 :(得分:-1)
将模板更改为:
<button twoway bind="counter">Click Me</button>
<p>Click Count: {{ counter.val }}</p>
和指令:
.directive('twoway',
function() {
return {
scope: {
localValue: '=?bind'
},
link: function(scope, elem, attrs) {
scope.localValue = {
val: 0
};
elem.on('click', function() {
scope.localValue.val = scope.localValue.val + 1;
scope.$apply();
});
}
};
}
);