如何修复:Angular 7(SmartAdmin模板)表单验证在导航后停止工作
我正在尝试在angular 7应用程序上执行表单验证,该应用程序使用智能管理模板(wrapbootstrap中的主题) 我的问题是,它在浏览器第一次刷新时,甚至在我导航到不包含其他表单的组件时,都能正常工作。 当我导航到一个组件时,会出现这个问题,该组件还包括一个具有自身验证选项的表单 此外,表单的实际“有效性”状态仍按预期工作。它只是没有在表单上显示引导类和消息 我尝试过重置表单,重置任何异步/非异步验证器以及我能想到的任何其他东西 最后,在组件之间的导航过程中没有错误或任何东西 这是我处理导航的主要模块(main.routing.ts): 这是一个表单示例(create team.component.html): 编辑:为了提供更多信息,以下是SmartAdmin模板使用的自定义验证:如何修复:Angular 7(SmartAdmin模板)表单验证在导航后停止工作,angular,angular7,angular-reactive-forms,smartadmin,angular2-form-validation,Angular,Angular7,Angular Reactive Forms,Smartadmin,Angular2 Form Validation,我正在尝试在angular 7应用程序上执行表单验证,该应用程序使用智能管理模板(wrapbootstrap中的主题) 我的问题是,它在浏览器第一次刷新时,甚至在我导航到不包含其他表单的组件时,都能正常工作。 当我导航到一个组件时,会出现这个问题,该组件还包括一个具有自身验证选项的表单 此外,表单的实际“有效性”状态仍按预期工作。它只是没有在表单上显示引导类和消息 我尝试过重置表单,重置任何异步/非异步验证器以及我能想到的任何其他东西 最后,在组件之间的导航过程中没有错误或任何东西 这是我处理导
import { Directive, Input, ElementRef } from "@angular/core";
@Directive({
selector: "[saUiValidate]"
})
export class UiValidateDirective {
@Input() saUiValidate: any;
constructor(private el: ElementRef) {
Promise.all([
import("jquery-validation/dist/jquery.validate.js"),
import("jquery-validation/dist/additional-methods.js")
])
.then(() => {
this.attach();
});
}
attach() {
const $form = $(this.el.nativeElement);
const validateCommonOptions = {
rules: {},
messages: {},
errorElement: "em",
errorClass: "invalid",
highlight: (element, errorClass, validClass) => {
$(element)
.addClass(errorClass)
.removeClass(validClass);
$(element)
.parent()
.addClass("state-error")
.removeClass("state-success");
},
unhighlight: (element, errorClass, validClass) => {
$(element)
.removeClass(errorClass)
.addClass(validClass);
$(element)
.parent()
.removeClass("state-error")
.addClass("state-success");
},
errorPlacement: (error, element) => {
if (element.parent(".input-group").length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
}
};
$form
.find("[data-smart-validate-input], [smart-validate-input]")
.each(function() {
var $input = $(this),
fieldName = $input.attr("name");
validateCommonOptions.rules[fieldName] = {};
if ($input.data("required") != undefined) {
validateCommonOptions.rules[fieldName].required = true;
}
if ($input.data("email") != undefined) {
validateCommonOptions.rules[fieldName].email = true;
}
if ($input.data("maxlength") != undefined) {
validateCommonOptions.rules[fieldName].maxlength = $input.data(
"maxlength"
);
}
if ($input.data("minlength") != undefined) {
validateCommonOptions.rules[fieldName].minlength = $input.data(
"minlength"
);
}
if ($input.data("message")) {
validateCommonOptions.messages[fieldName] = $input.data("message");
} else {
Object.keys($input.data()).forEach(key => {
if (key.search(/message/) == 0) {
if (!validateCommonOptions.messages[fieldName])
validateCommonOptions.messages[fieldName] = {};
var messageKey = key.toLowerCase().replace(/^message/, "");
validateCommonOptions.messages[fieldName][
messageKey
] = $input.data(key);
}
});
}
});
$form.validate($.extend(validateCommonOptions, this.saUiValidate));
}
}
编辑2:我已经设法找到了解决这个问题的办法,尽管我有点不喜欢。似乎在调用自定义UI验证时,组件尚未呈现(我猜这与异步运行有关)。
解决方案是在验证组件中添加0毫秒的“设置超时”,如下所示:
constructor(private el: ElementRef) {
Promise.all([
import("jquery-validation/dist/jquery.validate.js"),
import("jquery-validation/dist/additional-methods.js")
])
.then(() => {
setTimeout(_ => {
this.attach();
}, 0);
});
}
如果有人能想出更好的解决方案,我们将不胜感激:)
期待听到你的想法。因此,我遇到了与你相同的问题,也尝试了你的方法。虽然它确实可以工作,但请注意,通过将逻辑移动到ngOnInit()方法(无需修改),它也可以工作。我相信这与ngOnInit在调用组件之前等待组件完全呈现和初始化有关,这反过来确保绑定可用 下面是我用来让它工作的相关代码(attach()方法之前的所有内容)。这在ui-validate.directive.ts中:
import { Directive, Input, ElementRef, OnInit } from "@angular/core";
@Directive({
selector: "[saUiValidate]"
})
export class UiValidateDirective implements OnInit {
@Input() saUiValidate: any;
constructor(private el: ElementRef) { }
ngOnInit(){
Promise.all([
import("jquery-validation/dist/jquery.validate.js"),
import("jquery-validation/dist/additional-methods.js")
])
.then(() => {
this.attach();
});
}
import { Directive, Input, ElementRef } from "@angular/core";
@Directive({
selector: "[saUiValidate]"
})
export class UiValidateDirective {
@Input() saUiValidate: any;
constructor(private el: ElementRef) {
Promise.all([
import("jquery-validation/dist/jquery.validate.js"),
import("jquery-validation/dist/additional-methods.js")
])
.then(() => {
this.attach();
});
}
attach() {
const $form = $(this.el.nativeElement);
const validateCommonOptions = {
rules: {},
messages: {},
errorElement: "em",
errorClass: "invalid",
highlight: (element, errorClass, validClass) => {
$(element)
.addClass(errorClass)
.removeClass(validClass);
$(element)
.parent()
.addClass("state-error")
.removeClass("state-success");
},
unhighlight: (element, errorClass, validClass) => {
$(element)
.removeClass(errorClass)
.addClass(validClass);
$(element)
.parent()
.removeClass("state-error")
.addClass("state-success");
},
errorPlacement: (error, element) => {
if (element.parent(".input-group").length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
}
};
$form
.find("[data-smart-validate-input], [smart-validate-input]")
.each(function() {
var $input = $(this),
fieldName = $input.attr("name");
validateCommonOptions.rules[fieldName] = {};
if ($input.data("required") != undefined) {
validateCommonOptions.rules[fieldName].required = true;
}
if ($input.data("email") != undefined) {
validateCommonOptions.rules[fieldName].email = true;
}
if ($input.data("maxlength") != undefined) {
validateCommonOptions.rules[fieldName].maxlength = $input.data(
"maxlength"
);
}
if ($input.data("minlength") != undefined) {
validateCommonOptions.rules[fieldName].minlength = $input.data(
"minlength"
);
}
if ($input.data("message")) {
validateCommonOptions.messages[fieldName] = $input.data("message");
} else {
Object.keys($input.data()).forEach(key => {
if (key.search(/message/) == 0) {
if (!validateCommonOptions.messages[fieldName])
validateCommonOptions.messages[fieldName] = {};
var messageKey = key.toLowerCase().replace(/^message/, "");
validateCommonOptions.messages[fieldName][
messageKey
] = $input.data(key);
}
});
}
});
$form.validate($.extend(validateCommonOptions, this.saUiValidate));
}
}
constructor(private el: ElementRef) {
Promise.all([
import("jquery-validation/dist/jquery.validate.js"),
import("jquery-validation/dist/additional-methods.js")
])
.then(() => {
setTimeout(_ => {
this.attach();
}, 0);
});
}
import { Directive, Input, ElementRef, OnInit } from "@angular/core";
@Directive({
selector: "[saUiValidate]"
})
export class UiValidateDirective implements OnInit {
@Input() saUiValidate: any;
constructor(private el: ElementRef) { }
ngOnInit(){
Promise.all([
import("jquery-validation/dist/jquery.validate.js"),
import("jquery-validation/dist/additional-methods.js")
])
.then(() => {
this.attach();
});
}