监听指令中的表单提交事件 [英] Listen for form submit event in directive
问题描述
我想听指令中的表单提交.说我有一个这样的指令:
I want to listen for form submitting in a directive. Say I have a directive like this:
app.directive('myDirective', function () {
return {
restrict: 'A',
require: '^form',
scope: {
smth: '='
},
link: function (scope, el, attrs, formCtrl) {
scope.$watch(function(){
return formCtrl.$submitted;
},function(currentValue){
console.log('submitted');
});
}
}
});
使用上述方法,我可以监视第一个提交,而其余的则不能.我试图做这样的事情:
With the above method I can watch for first submit, but not the rest. I tried to do something like this:
scope.$watch(function () {
return formCtrl.$submitted;
}, function (currentValue) {
if (currentValue) {
console.log('submitted');
formCtrl.$setPristine(); // Watch this line!
}
});
但是然后的问题是,如果我以一种以上的形式使用该指令,则该指令仅在第一次使用时有效.
我想知道的是是否有类似formCtrl.onsubmit(...)
之类的东西或任何变通办法来获得相同的功能.预先感谢您的帮助...
But then the problem is, if I use the directive in a form more than once, it works only for the first usage.
What I want to know is if there is something like formCtrl.onsubmit(...)
or any workaround to get the same functionality. Thanks in advance for any help...
推荐答案
您可以创建与具有事件处理程序的form
指令同名的指令,而无需查看$submitted
属性.表单提交广播一个角度事件,您可以在myDirective
指令中收听.您不必担心会覆盖form
指令的有角度的实现,它只会附加您的行为而不会覆盖内置的实现.
Instead of watching the $submitted
property, you can create a directive that has the same name as the form
directive which is attached with an event handler for form submit that broadcasts an angular event that you can listen in your myDirective
directive. You don't have to worry about overriding the angular implementation of the form
directive, it will simply append your behavior not overwrite the built-in implementation.
DEMO
注意:您还可以选择不向form
指令附加功能,而是选择另一个指令名称,只需确保将该指令名称作为属性附加在form标记中即可触发事件.
Note: You can also choose not to append functionality to the form
directive and instead choose another directive name, just make sure to attach that directive name as an attribute in the form tag to trigger the event.
Javascript
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();
});
}
};
});
更新
鉴于以下评论中提出的问题:
Update
In light of the question raised in the comment below:
最有效的方法来检查元素是否具有 "my-directive"属性具有"my-form"(如果我将"form"指令命名为 父表单中的"myForm")属性?所以我可以使用 带或不带"myForm"的"myDirective"(并相应地表现为 课程)
what's the most efficient way to check if the element that has "my-directive" attribute has "my-form" (if I name "form" directive to "myForm") attribute in it's parent form? So I can either use "myDirective" with or without "myForm" (and behave accordingly of course)
有几种方法可以做到:
- 在编译阶段在
myForm
指令中使用.data()
方法,如果form
指令中分配的数据存在,则在myDirective
的链接函数中使用.inheritedData()
方法对其进行访问.
- Use the
.data()
method in yourmyForm
directive during the compile phase, and access it in the link function in yourmyDirective
using the.inheritedData()
method if the data assigned in theform
directive exists.
请注意,我在myForm
指令的广播中通过了form
控制器.这样可以确保您收到来自form
元素的父表单控制器.在某些用例中,您将通过ng-form
在嵌套表单中使用myDirective
,因此,代替将form.$setPristine()
设置为form
元素表单控制器,您将设置ngForm
表单控制器.
Note that I passed the form
controller within the broadcast in the myForm
directive. This ensures that you receive the parent form controller which is the from the form
element. There are certain use cases wherein you would use the myDirective
inside a nested form via ng-form
, so instead of setting form.$setPristine()
to the form
element form controller you'd be setting the ngForm
form controller.
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
指令中将scope设置为true可以使该指令可重用,例如一个页面内有多个myForm
指令.
- Another way which is probably something that is highly optimized for this specific use case. To create a controller in the
myForm
directive which stores form event handlers to be iterated when a form event is triggered. Instead of using the$broadcast
angular event which is actually slower than the implementation below because it traverses each scope from theform
element down to the last scope chain. ThemyForm
controller below creates its own mechanism for storing the event handlers. As implemented in #1, using the.data()
-inheritedData()
is slow when themyDirective
is buried deep and nested from a lot of elements, since it traverses theDOM
upwards until it finds that specificdata
. Using the implementation below, you can check if the required?^myForm
controller exists in the parent, notice the?
it represents an optional requirement. Additionally, setting scope to true in themyForm
directive allows you to have the directive reusable, e.g. have multiplemyForm
directives inside a page..
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();
});
}
};
});
这篇关于监听指令中的表单提交事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!