Javascript 手动应用ngModel指令
我的指令需要使用Javascript 手动应用ngModel指令,javascript,angularjs,angularjs-directive,angular-ngmodel,Javascript,Angularjs,Angularjs Directive,Angular Ngmodel,我的指令需要使用ngModel 我需要从另一个指令中动态地完成这项工作,因为我想用作用域做一些时髦的事情,并将其从编写HTML的人那里抽象出来 我的第一个想法是使用link函数中的attrs参数提供的$set函数,该函数可以修改HTML,但指令本身不会被编译。然后我们可以将它与$compile提供程序结合起来,它就可以工作了 attrs.$set('ngModel', someVar); $compile(element)(scope); 问题是,如果在指令被无限期地重新应用和重新编译时,我不
ngModel
我需要从另一个指令中动态地完成这项工作,因为我想用作用域做一些时髦的事情,并将其从编写HTML的人那里抽象出来
我的第一个想法是使用link
函数中的attrs
参数提供的$set
函数,该函数可以修改HTML,但指令本身不会被编译。然后我们可以将它与$compile
提供程序结合起来,它就可以工作了
attrs.$set('ngModel', someVar);
$compile(element)(scope);
问题是,如果在指令被无限期地重新应用和重新编译时,我不(也不能)替换elements标记,这将创建无限递归
然而,我可以摆弄优先事项并使其发挥作用:
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);
}
};
}
]);
这很好,但感觉不对:
- 我现在必须确保元素上的所有其他指令 能够被重新编译,因为它们都会被编译两次
- 我必须确保没有人使用更高的优先级
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]);
}
};
}
]);
见:
没有抛出错误,但什么也没有发生。似乎这还不足以连接它,所以我的问题是,有人能详细说明我需要做什么吗?在不强制重新编译的情况下,将
ngmodeldirection
链接到我的自定义指令?我认为不重新编译是不可能的
ngModel
被设计成同一元素中的其他指令和父表单指令之间的协作者。例如,在编译期间:
- 其他指令(如输入、必需或ng更改)可将其自身的
或$parser
添加到ngModel$formatter
- ngModel将自身添加到父窗体指令(如果存在)
ngModel
,则上述两个操作将丢失
编辑:如果要分配给ng模型属性的值在编译时是已知的,则可能是这样的:
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
}
};
});
下面是plunker示例:
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
可以通过绑定到外部世界来读取和写入模型变量。我已经成功地做到了这一点。这不是最漂亮的东西,但它可以工作,我可以连接我的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
我想要ngModel
的原因是它允许用户在不知道我的语法的情况下扩展它,同时也增加了其他人的代码能够很好地使用它的机会。另外,我还需要使用$modelValue
和$viewValue
。我同意在一个封闭的环境中,我可能会编写一个更有效的解决方案,但这是一个库。@ GoGreReHe你是否考虑过手动实现它,只是简单地复制(一些)源代码和?只是为了让你知道我找到了一个工作解决方案(见)+ 1的帮助。只想让你知道我设法解决这个问题(参见)。1用于指出有关指令特定链接的内容。我会在事先不知道的情况下挣扎。