Я пытаюсь выполнить проверку формы в приложении Angular 7, использующем шаблон Smart Admin (тема из wrapbootstrap).
Моя проблема заключается в том, что он работает, как и ожидалось, при первом обновлении браузера,или даже когда я перехожу к компоненту, который не включает другую форму.Проблема возникает, когда я перехожу к компоненту, который также включает форму с собственными параметрами проверки.
Кроме того, фактический статус «Действительность» формы все еще работает, как и ожидалось.Он просто не показывает классы начальной загрузки и сообщения в форме.
Я попытался сбросить форму, сбросить все асинхронные / не асинхронные валидаторы и все остальное, о чем я мог подумать.
Наконец, нет ошибок или чего-либо еще во время навигации между компонентами.
Это мой основной модуль, который обрабатывает навигацию (main.routing.ts):
import { Routes, RouterModule } from '@angular/router';
import { ModuleWithProviders } from "@angular/core";
import { MainLayoutComponent } from '@app/shared/layout/app-layouts/main-layout.component';
import { MainComponent } from "./main.component";
import { SettingsComponent } from '../settings/settings.component';
import { GetAccountsComponent } from '../administration/get-accounts/get-accounts.component';
import { GetUsersComponent } from '../administration/get-users/get-users.component';
import { CreateAccountComponent } from '../administration/create-account/create-account.component';
import { CreateUserComponent } from '../administration/create-user/create-user.component';
import { GetTeamsComponent } from '../user/get-teams/get-teams.component';
import { GetGamesComponent } from '../user/get-games/get-games.component';
import { CreateTeamComponent } from '../game/create-team/create-team.component';
import { CreateRoundComponent } from '../game/create-round/create-round.component';
import { CreateRoundBetComponent } from '../game/create-round-bet/create-round-bet.component';
import { CreateGameComponent } from '../game/create-game/create-game.component';
export const mainRoutes: Routes = [
{
path: '',
component: MainLayoutComponent,
children: [
{
path: "",
redirectTo: "dashboard",
pathMatch: "full"
},
{
path: "dashboard",
component: MainComponent,
data: { pageTitle: "Dashboard" }
},
{
path: "settings",
component: SettingsComponent,
data: { pageTitle: "Settings" }
},
{
path: "administration/getusers",
component: GetUsersComponent,
data: { pageTitle: "Get Users" }
},
{
path: "administration/getaccounts",
component: GetAccountsComponent,
data: { pageTitle: "Get Accounts" }
},
{
path: "administration/createaccount",
component: CreateAccountComponent,
data: { pageTitle: "Create Account" }
},
{
path: "administration/createuser",
component: CreateUserComponent,
data: { pageTitle: "Create User" }
},
{
path: "user/getteams",
component: GetTeamsComponent,
data: { pageTitle: "Get Teams" }
},
{
path: "user/getgames",
component: GetGamesComponent,
data: { pageTitle: "Get Games" }
},
{
path: "game/createteam",
component: CreateTeamComponent,
data: { pageTitle: "Create Team" }
},
{
path: "game/createround",
component: CreateRoundComponent,
data: { pageTitle: "Create Round" }
},
{
path: "game/createroundbet",
component: CreateRoundBetComponent,
data: { pageTitle: "Create Round Bet" }
},
{
path: "game/creategame",
component: CreateGameComponent,
data: { pageTitle: "Create Game" }
}
]
}
];
export const mainRouting: ModuleWithProviders = RouterModule.forChild(mainRoutes);
Это примерформы (create-team.component.html):
<form id="checkout-form"
name="createTeamForm"
class="smart-form"
[saUiValidate]="validationOptions"
novalidate="novalidate"
[formGroup]="createTeamForm"
(ngSubmit)="onSubmit()">
<fieldset>
<div class="row">
<section class="col col-4">
<label class="select">
<select name="firstPerson"
formControlName="firstPerson">
<option value="0"
selected=""
disabled="">First Person</option>
<option value="{{user.id}}"
*ngFor="let user of users">{{user.email}}</option>
</select> <i></i> </label>
</section>
<section class="col col-4">
<label class="select">
<select name="secondPerson"
formControlName="secondPerson">
<option value="0"
selected=""
disabled="">Second Person</option>
<option value="{{user.id}}"
*ngFor="let user of users">{{user.email}}</option>
</select> <i></i> </label>
</section>
</div>
</fieldset>
<footer>
<button type="submit"
class="btn btn-primary">
Create Team
</button>
</footer>
</form>
и .ts-файл, который включает параметры проверки:
import { Component, OnInit } from '@angular/core';
import { ApiService } from '@app/core/services';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { first } from 'rxjs/operators';
@Component({
selector: 'app-create-team',
templateUrl: './create-team.component.html',
styleUrls: ['./create-team.component.css']
})
export class CreateTeamComponent implements OnInit {
public teamCreateSuccess: boolean;
public users: any;
public hasSubmitted: boolean;
public errorMessage: string;
public successMessage: string;
public validationOptions = {
rules: {
firstPerson: {
required: true
},
secondPerson: {
required: true
}
},
// Messages for form validation
messages: {
firstPerson: {
required: 'Please select the first person'
},
secondPerson: {
required: 'Please select the second person'
},
},
submitHandler: this.onSubmit
};
createTeamForm: FormGroup
constructor(
private apiService: ApiService
) { }
ngOnInit() {
console.log('Create Team Loaded');
this.apiService.userGetUsers()
.subscribe(
data => {
this.users = data;
// console.log(this.roles);
},
error => {
this.onCreateTeamError(error);
}
);
this.teamCreateSuccess = null;
this.hasSubmitted = null;
this.createTeamForm = new FormGroup({
firstPerson: new FormControl('0', Validators.required),
secondPerson: new FormControl('0', Validators.required),
});
}
onSubmit() {
this.hasSubmitted = true;
if (this.createTeamForm) {
console.log(this.createTeamForm.status);
console.log(this.createTeamForm.controls);
if (this.createTeamForm.status == 'VALID') {
this.apiService.createTeam(this.createTeamForm).pipe(first())
.subscribe(
data => {
this.onCreateTeamSuccess(data);
},
error => {
//console.log("failed identity check");
this.onCreateTeamError(error);
//console.log(error);
}
);
}
}
}
onCreateTeamSuccess(data: any) {
this.teamCreateSuccess = true;
this.successMessage = "Successfully created team with Id: " + data.id;
console.log(data);
}
onCreateTeamError(error: any) {
this.teamCreateSuccess = false;
this.errorMessage = "Failed to create team due to error: " + error.error;
console.log(error);
}
}
РЕДАКТИРОВАТЬ: для более глубокого понимания,Вот пользовательская проверка, которую использует шаблон SmartAdmin:
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: мне удалось найти обходной путь для этой проблемы, хотя мне это не нравится.Кажется, что когда вызывается пользовательская проверка пользовательского интерфейса, компонент еще не отображается (я предполагаю, что он как-то связан с асинхронной работой).Решением было добавить в компонент проверки 'setTimeout' в 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);
});
}
Если кто-то может придумать лучшее решение, было бы очень полезно :)
Будем рады услышать ваши идеи.