我想听一个指令中的表单提交。说我有这样的指示:
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');
});
}
}
});
通过上述方法,我可以看到第一次提交,但不是其余的。我试着做这样的事情:
scope.$watch(function () {
return formCtrl.$submitted;
}, function (currentValue) {
if (currentValue) {
console.log('submitted');
formCtrl.$setPristine(); // Watch this line!
}
});
但问题是,如果我不止一次在表单中使用该指令,它只适用于第一次使用。
我想知道的是,如果有类似formCtrl.onsubmit(...)
的内容或任何解决方法来获得相同的功能。提前感谢您的帮助......
答案 0 :(得分:15)
您可以创建一个与$submitted
指令同名的指令,而不是观察form
属性,该指令附加了表单提交的事件处理程序,用于广播您可以使用的角度事件听你的myDirective
指令。您不必担心覆盖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”)属性在它的父表单中?所以我可以使用 “myDirective”有或没有“myForm”(并且相应地表现出来) 当然)
有几种方法可以做到:
.data()
指令中的myForm
方法,如果分配了数据,则使用myDirective
方法在.inheritedData()
的链接功能中访问该方法存在form
指令。请注意,我在form
指令的广播中传递了myForm
控制器。这可确保您收到来自form
元素的父表单控制器。在某些用例中,您可以通过myDirective
在嵌套表单中使用ng-form
,因此不要将form.$setPristine()
设置为您要设置的form
元素表单控制器ngForm
表单控制器。
<强> 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中实现的那样,.data()
- inheritedData()
在myDirective
被深埋并嵌套在很多元素中时很慢,因为它向上遍历DOM
直到data
为止。它找到了特定的?^myForm
。使用下面的实现,您可以检查父级中是否存在所需的?
控制器,请注意它代表可选要求的myForm
。此外,在myForm
指令中将范围设置为true允许您使指令可重用,例如在页面中有多个 .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();
});
}
};
});
指令.. <强> DEMO 强>
{{1}}
答案 1 :(得分:2)
您可以将ng-submit
用于广播或类似内容,但可能先尝试$setUntouched()
,或者在完成后手动将$submitted
设置回false
目前的提交。
答案 2 :(得分:0)
答案 3 :(得分:-1)
这篇文章可能已经死了但是基于上面的内容,我发现form指令没有正确地向其他指令广播,所以我将所有内容都包含在一个指令中。
这是一个基于表单生成警报的简单函数。如果表单无效,则为$ 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();
});
}
};
}])