tl;博士;
辅助服务用作指令和控制器之间的通信机制。服务注册和取消注册元素(在指令链接函数中)并通过函数调用(在控制器中)启用和禁用所有注册的元素。
解决方案 1 -- 任何位置的只读元素
HERE 是我的解决方案的种子1,其中元素可能位于 DOM 树中的任何位置。
辅助服务
app.factory("demoReadonlyState", function(){
var elements = [];
var state = false;
return {
enable : function(){
state = false;
for (var i = 0, len = elements.length; i < len; i++){
elements[i].removeAttribute('readonly');
}
},
disable : function(){
state = true;
for (var i = 0, len = elements.length; i < len; i++){
elements[i].setAttribute('readonly', "True");
}
},
addElement : function(domEl) {
elements.push(domEl);
if(state){
domEl.setAttribute('readonly', state);
}
else {
domEl.removeAttribute('readonly');
}
console.log("add -- # elements: ", elements.length);
},
removeElement : function(el) {
var index = elements.indexOf(el);
if (index > -1) {
elements.splice(index, 1);
}
console.log("remove -- # elements: ", elements.length);
}
}
})
指令
app.directive("demoReadonly", function(demoReadonlyState){
return {
link : function(scope, element){
console.log(demoReadonlyState);
demoReadonlyState.addElement(element[0]);
element.on('$destroy', function(){
demoReadonlyState.removeElement(element);
})
}
}
})
用法
在JS:
app.controller("MainCtrl", function($scope, demoReadonlyState){
$scope.roState = demoReadonlyState;
$scope.roState.enable();
//$scope.roState.disable();
});
在HTML:
<body ng-controller="MainCtrl">
<input demo-readonly />
<input />
<input demo-readonly />
<input />
<input demo-readonly />
<input />
<div>
<button ng-click="roState.enable()">enable</button>
<button ng-click="roState.disable()">disable</button>
</div>
<div>
<button ng-click="arr.push([])">add element</button>
<button ng-click="arr.length && arr.splice(0,1)">remove element</button>
</div>
<div ng-repeat="x in arr">
<input demo-readonly/>
</div>
</body>
1 我的意思是种子是不可配置的。在正常的解决方案中,指令可以传递一个字符串 (demo-readonly="type_X"),它指定一组元素应该是 enabled/disabled 在一起,而所有其他组保持不变。
解决方案 2 -- DOM 子树中的只读元素
HERE 是一种稍微不同的方法,它使用单个指令处理子树。它可以处理多个相互独立的子树。在这种形式下,它不适用于动态ng-repeat well2,但可以轻松实现更强大的机制(尽管需要使用额外的指令)。
辅助服务
app.factory("demoReadonlyState", function(){
var elements = {};
return {
enable : function(type){
element = elements[type];
var inputs = element.querySelectorAll('input');
for (var i = 0, len = inputs.length; i < len; i++){
inputs[i].removeAttribute('readonly');
}
},
disable : function(type){
element = elements[type];
var inputs = element.querySelectorAll('input');
for (var i = 0, len = inputs.length; i < len; i++){
inputs[i].setAttribute('readonly', "True");
}
},
addElement : function(type, domEl) {
elements[type] = domEl;
},
removeElement : function(type) {
delete elements[type];
}
}
})
指令
app.directive("demoReadonly", function(demoReadonlyState){
return {
scope : {
type : "@demoReadonly"
},
link : function(scope, element){
demoReadonlyState.addElement(scope.type, element[0]);
element.on('$destroy', function(){
demoReadonlyState.removeElement(scope.type);
})
}
}
})
用法
在JS:
app.controller("MainCtrl", function($scope, demoReadonlyState){
$scope.roState = demoReadonlyState;
$scope.roState.enable('XXX');
//$scope.roState.disable('XXX');
});
在HTML:
<body ng-controller="MainCtrl">
<div>
<button ng-click="roState.enable('XXX')">enable</button>
<button ng-click="roState.disable('XXX')">disable</button>
</div>
<div demo-readonly="XXX">
<input/>
<input/>
<div>
<input/>
<input/>
</div>
</div>
</body>
1 基本上使用动态ng-repeat 需要在每次更新集合后手动调用enable/disable。