手动应用ngModel指令
Manually applying the ngModel directive
我的指令需要使用ngModel
。
我需要从另一个指令中动态地做到这一点,因为我想用作用域做一些时髦的东西,并将其从编写HTML的人抽象出来。
我的第一个想法是使用link
函数中attrs
参数提供的$set
函数,该函数用于修改HTML,但指令本身没有编译。然后,我们可以将它与$compile
提供程序结合使用,它就可以工作了。
attrs.$set('ngModel', someVar);
$compile(element)(scope);
问题是,如果我不(而且我不能)在指令被无限地重新应用和重新编译时替换元素标签,这会创建无限递归。
但是我可以调整优先级并使其工作:
module.directive('input', [
'$compile',
function($compile) {
return {
restrict: 'E',
scope: {},
priority: 100, // Set this high enough to perform other directives
terminal: true, // Make sure this is the last directive parsed
link: function(scope, element, attrs) {
var key = 'example';
attrs.$set('ngModel', key);
$compile(element, null, 100)(scope);
}
};
}
]);
这个工作正常,但是感觉不对:
我现在必须确保元素上的所有其他指令都是正确的
我必须确保没有人使用更高的优先级。
所以这让我思考为什么我不能注入ngModelDirective并强制编译它针对我的元素?
module.directive('input', [
'ngModelDirective',
function(ngModel) {
return {
restrict: 'E',
scope: {},
priority: 100, // Set this high enough to perform other directives
terminal: true, // Make sure this is the last directive parsed
require: '?^form',
link: function(scope, element, attrs, formCtrl) {
var key = 'example';
attrs.$set('ngModel', key);
var ngModelFactory = ngModel[0];
var ngModelLink = ngModelFactory.compile(element);
ngModelLink.call(this, scope, element, attrs, [ngModelFactory.controller, formCtrl]);
}
};
}
]);
见:https://github.com/angular/angular.js/blob/v1.2.x/src/ng/directive/input.js L1356
没有抛出错误,但什么也没发生。似乎这还不足以把它挂钩起来,所以我的问题是,有人能详细说明我需要做什么链接ngModelDirective
到我的自定义指令没有强制重新编译?
ngModel
似乎不适合你想做的事情。但你不需要它。你可以双向绑定一些变量,并将其名称传递到model指令作用域:
app.directive("myDirective", function() {
// ...
scope: {
myModel = "=",
modelName = "myModel"
// ...
}
// ...
});
app.directive("ngModelDirective", function() {
// ...
// ...
transclude: true,
link: function(scope, element, attrs) {
var modelName = scope.modelName;
console.assert(modelName, '`modelName` must be set when using `ngModelDirective`.');
// TODO: Check if `scope[modelName]` is actually bound
doSomethingFancyWith(scope, modelName);
}
});
模板示例:
<myDirective ngModelDirective my-model="..." />
请注意,doSomethingFancyWith
可以读写模型变量,并绑定到外部世界。
我认为不重新编译是不可能的。
ngModel
被设计成同一元素中其他指令和父表单指令之间的协作者。例如,在编译期间:
- 其他指令(例如input、required或ng-change)可以在ngModel中添加自己的
$parser
或$formatter
。 - 如果存在,ngModel会把自己添加到父表单指令中。
因此,如果在复杂过程已经结束后以某种方式添加ngModel
,则上述两个动作将缺失。
Edit:如果要分配给ng-model属性的值是在编译时已知的,则可能是这样的:
app.directive('myNgModel', function($compile) {
return {
restrict: 'A',
replace: false,
priority: 1000,
terminal: true, // these terminal and priority will stop all other directive from being compiled.
link: function (scope, element, attrs) {
var key = 'example';
attrs.$set('ngModel', key);
attrs.$set('myNgModel', null); // remove itself to avoid a recusion
$compile(element)(scope); // start compiling other directives
}
};
});
下面是柱塞的例子:http://plnkr.co/edit/S2ZkiVIyq2bOK04vAnFO?p=preview
我已经做到了。这不是最漂亮的东西,但它的工作,我可以连接我的input
指令工作使用本地inputDirective
,这样它就可以使用require
或验证特定的输入类型。
要针对实现特定ngModel
功能(如ngChange
)的另一个标准指令构建此命令,只需将注入的inputDirective
替换为正确的指令,例如ngChangeDirective
。
module.directive('input', function() {
return {
restrict: 'E',
scope: {},
require: '?ngModel',
priority: -1,
link: function(scope, element, attrs, ngModel) {
var key = 'example.property';
if (ngModel === undefined) {
attrs.$set('ngModel', key);
angular.injector(['ng']).invoke([
'inputDirective',
'ngModelDirective',
'$controller',
'$exceptionHandler',
'$parse',
'$animate',
function(inputDirective, ngModelDirective, $controller, $exceptionHandler, $parse, $animate) {
var ngModelFactory = ngModelDirective[0];
var ngModelLink = ngModelFactory.compile(scope); // Get the ngModel linkage function against this scope
ngModel = $controller(ngModelFactory.controller, {
$scope: scope,
$exceptionHandler: $exceptionHandler,
$attrs: attrs,
$element: element,
$parse: $parse,
$animate: $animate
}); // Call the ngModel controller and bootstrap it's arguments
// Call the inputDirective linkage function to set up the ngModel against this input
inputDirective[0].link(scope, element, attrs, ngModel);
element.data('$ngModelController', ngModel); // Allow additional directives to require ngModel on this element.
}
]);
}
}
};
});
注意:这对ngOptions
不起作用,因为它指定terminal: true
。
- Angular.js指令格式化程序只调用过一次,或者如何告诉ngModel表现得像watchCollection
- AngularJS - 在自定义指令中继承ngModel
- 缺少 Angular JS 必需控制器错误:找不到指令所需的控制器“ngModel”
- 如何使用.指令跟踪ngModel数组项的行为
- 如何在 AngularJS 指令中重命名 ngModel “require”
- 在指令链接中访问 ngModel 的父对象
- 动态 ngModel 和 ngBind 与自定义指令
- 创建 AngularJS 指令,如 ngModel 用于数组
- AngularJS - 是否可以在链接或编译中的指令上更改ngModel属性的值
- 观察父元素上指令的 ngModel 值变化
- 在指令中的输入上使用ngModel,保持ng-*兼容性
- 自定义 ngModel 指令以支持 jquery 插件中的模型>视图绑定
- 带有 ngModel 绑定的 AngularJS 自定义指令不起作用
- 你能在没有指令的情况下在ngModel上动态呈现HTML吗
- 使用ngModel的自定义输入指令不会更新模型值
- 具有独立作用域的指令中的表单输入:如何将ngModel设置为正确的作用域
- 将多个ngModel值传递给一个指令-是否可能
- 指令:ngModel不更改ng隐藏
- 在自定义指令中提供ngModel
- 如何将一个变量从指令(ngModel)传递到指令外部的html中