您可以创建一个与form 指令同名的指令,而不是查看$submitted 属性,该指令附加一个用于表单提交的事件处理程序,该事件处理程序广播一个角度事件,您可以在您的@ 中收听987654326@ 指令。您不必担心覆盖form 指令的角度实现,它只会附加您的行为而不是覆盖内置实现。
DEMO
注意:您也可以选择不向 form 指令附加功能,而是选择另一个指令名称,只需确保将该指令名称作为属性附加到表单标记中以触发事件。
Javascript
.directive('form', function() {
return {
restrict: 'E',
link: function(scope, elem) {
elem.on('submit', function() {
scope.$broadcast('form:submit');
});
}
};
})
.directive('myDirective', function() {
return {
require: '^form',
link: function(scope, elem, attr, form) {
scope.$on('form:submit', function() {
form.$setPristine();
});
}
};
});
更新
鉴于以下评论中提出的问题:
什么是检查元素是否具有的最有效方法
“my-directive”属性具有“my-form”(如果我将“form”指令命名为
“myForm”)属性在它的父表单中?所以我可以使用
带有或不带有“myForm”的“myDirective”(并相应地表现
当然)
有几种方法可以做到:
- 在编译阶段在
myForm 指令中使用.data() 方法,如果在form 指令中分配的数据存在,则使用.inheritedData() 方法在myDirective 的链接函数中访问它。
请注意,我在myForm 指令的广播中传递了form 控制器。这确保您收到来自form 元素的父表单控制器。在某些用例中,您可以通过ng-form 在嵌套表单中使用myDirective,因此您可以设置ngForm 表单控制器,而不是将form.$setPristine() 设置为form 元素表单控制器。
DEMO
.directive('myForm', function() {
return {
require: 'form',
compile: function(tElem, tAttr) {
tElem.data('augmented', true);
return function(scope, elem, attr, form) {
elem.on('submit', function() {
scope.$broadcast('form:submit', form);
});
}
}
};
})
.directive('myDirective', function() {
return {
link: function(scope, elem, attr) {
if(!elem.inheritedData('augmented')) {
return;
}
scope.$on('form:submit', function(event, form) {
console.log('submit');
form.$setPristine();
});
}
};
});
- 另一种可能是针对此特定用例高度优化的方法。在
myForm 指令中创建一个控制器,该指令存储表单事件处理程序,以便在触发表单事件时进行迭代。而不是使用$broadcast 角度事件,它实际上比下面的实现要慢,因为它遍历从form 元素到最后一个作用域链的每个作用域。下面的myForm 控制器创建了自己的机制来存储事件处理程序。正如在#1 中实现的那样,当myDirective 被深埋并嵌套在许多元素中时,使用.data() - inheritedData() 会很慢,因为它会向上遍历DOM,直到找到特定的data。使用下面的实现,您可以检查所需的?^myForm 控制器是否存在于父级中,注意? 它表示一个可选要求。此外,在 myForm 指令中将范围设置为 true 允许您使指令可重用,例如在一个页面中有多个 myForm 指令..
DEMO
.directive('myForm', function() {
return {
require: ['form', 'myForm'],
scope: true,
controller: function() {
this.eventHandlers = {
submit: [],
change: []
};
this.on = function(event, handler) {
if(this.eventHandlers[event]) {
this.eventHandlers[event].push(handler);
}
};
},
link: function(scope, elem, attr, ctrls) {
var form = ctrls[0],
myForm = ctrls[1];
angular.forEach(myForm.eventHandlers, function(handlers, event) {
elem.on(event, function(eventObject) {
angular.forEach(handlers, function(handler) {
handler(eventObject, form);
});
});
});
}
};
})
.directive('myDirective', function() {
return {
require: '?^myForm',
link: function(scope, elem, attr, myForm) {
if(!myForm) {
return;
}
myForm.on('submit', function(event, form) {
console.log('submit');
form.$setPristine();
});
}
};
});