[英]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!
}
});
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. 我想知道的是,是否有类似
formCtrl.onsubmit(...)
或任何解决方法来获得相同的功能。 Thanks in advance for any help... 在此先感谢任何帮助......
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. 而是看的
$submitted
属性,你可以创建一个具有相同的名称作为一个指令form
其连接与形式的事件处理程序提交广播,你可以在你听角事件指令myDirective
指令。 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. 您不必担心覆盖
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. 注意:您也可以选择不向
form
指令附加功能,而是选择另一个指令名称,只需确保将该指令名称作为表单标记中的属性附加以触发事件。
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();
});
}
};
});
In light of the question raised in the comment below: 鉴于以下评论中提出的问题:
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?
什么是最有效的方法来检查具有“my-directive”属性的元素是否具有“my-form”(如果我将“form”指令命名为“myForm”)属性为其父表单? So I can either use "myDirective" with or without "myForm" (and behave accordingly of course)
所以我可以使用“myDirective”,有或没有“myForm”(当然也有相应的行为)
There are several ways to do it: 有几种方法可以做到:
.data()
method in your myForm
directive during the compile phase, and access it in the link function in your myDirective
using the .inheritedData()
method if the data assigned in the form
directive exists. .data()
在你的方法myForm
指令在编译阶段,并访问它的连接功能在myDirective
使用.inheritedData()
方法,如果在指定的数据form
存在的指令。 Note that I passed the form
controller within the broadcast in the myForm
directive. 请注意,我在
myForm
指令的广播中传递了form
控制器。 This ensures that you receive the parent form controller which is the from the form
element. 这可以确保您收到来自
form
元素的父表单控制器。 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. 在某些用例中,您可以通过
ng-form
在嵌套表单中使用myDirective
,而不是将form.$setPristine()
设置为form
元素表单控制器,您将设置ngForm
表单控制器。
.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
directive which stores form event handlers to be iterated when a form event is triggered. myForm
指令中创建一个控制器,该指令存储表单事件处理程序,以便在触发表单事件时进行迭代。 Instead of using the $broadcast
angular event which is actually slower than the implementation below because it traverses each scope from the form
element down to the last scope chain. $broadcast
角度事件,因为它遍历每个范围从form
元素到最后一个范围链。 The myForm
controller below creates its own mechanism for storing the event handlers. myForm
控制器创建了自己的存储事件处理程序的机制。 As implemented in #1, using the .data()
- inheritedData()
is slow when the myDirective
is buried deep and nested from a lot of elements, since it traverses the DOM
upwards until it finds that specific data
. .data()
- inheritedData()
在myDirective
被深埋并嵌套在很多元素中时很慢,因为它向上遍历DOM
直到找到特定data
。 Using the implementation below, you can check if the required ?^myForm
controller exists in the parent, notice the ?
?^myForm
控制器,注意?
it represents an optional requirement. myForm
directive allows you to have the directive reusable, eg have multiple myForm
directives inside a page.. myForm
指令中将scope设置为true允许您使指令可重用,例如在页面内有多个myForm
指令。 .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();
});
}
};
});
您可以将ng-submit
与广播或类似内容一起使用,但可以先尝试$setUntouched()
,或者在完成当前提交后手动将$submitted
$setUntouched()
设置$submitted
false
。
This post is probably dead but to build on the above, I found the form directive was not broadcasting to the other directives properly so I included everything in one directive. 这篇文章可能已经死了,但是基于上面的内容,我发现form指令没有正确地向其他指令广播,所以我将所有内容都包含在一个指令中。
Here is a simple functions that generates an alert based on form.$error if the form is invalid:- 这是一个基于表单生成警报的简单函数。如果表单无效,则为$ error: -
// automated handling of form submit errors
myApp.directive('form', [ function() {
return {
restrict: 'E',
require: '^form',
link: function (scope, elem, attr, form) {
elem.on('submit', function () {
if(form.$invalid){
console.log('form.$error: ', form.$error);
Object.keys(form.$error).forEach(error => {
form.$error[error].forEach(elem => {
console.log('error elem is: ', elem);
alert(error + ' for ' + elem.$name + ' is invalid! Current: ' + elem.$modelValue);
})
})
}
form.$setPristine();
});
}
};
}])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.