#javascript #angular #typescript #angular8
#javascript #угловой #typescript #angular8
Вопрос:
Я создал поле динамической формы, которое я добавляю и удаляю с помощью функции обратного вызова на кнопках DelBtn()
, чтобы удалить элемент и AddBtn()
добавить элемент
Каждое из полей этой формы имеет value
ввод
У меня также есть totalval
поле. Я ожидаю, что сумма значений во всех value
полях не будет превышать totalval
. Если это так, мы выводим сообщение об ошибке a, и если значение равно, мы выводим поле reason
формы.
Пример:
Если у меня есть totalValue = 100
. Теперь допустим, у меня есть мое первое поле формы value = 90
.
Затем я дублирую форму и в следующем наборе полей value = 10
reason
поле должно появиться, потому 90 10 = 100
что. По мере totalValue
достижения должно появиться поле reason
формы, а кнопка добавления должна быть отключена.
Если при второй попытке пользователь попытается ввести значение больше 10, должно появиться сообщение об ошибке.
Ниже приведен мой текущий код
В моем TS-файле у меня есть
ischecks: boolean = true;
formsArray = [""];
count: number = 0;
totalval: number = 100;
ngOnInit(): void {}
constructor() {}
clickCount(): void {
this.count ;
}
DelBtn = delIndex => this.formsArray.splice(delIndex, 1);
AddBtn = () => this.formsArray.push("");
HTML
<h2> Form</h2>
<pre style="font-weight: bolder;font-family:verdana;margin-left: 35px;">Total Value:{{totalval}} </pre>
<div *ngFor="let i of formsArray; let a = index">
<div>
<form>
<table>
<div>
<label for="fname">Value:</label><br>
<input type="text" id="fname" name="fname" ><br>
<tr>
<td>
<button type="button" class="btn btn-outline-success"
style="border-radius:40px;margin-left: 50px" (click)="DelBtn(a)" ><span class="fa fa-plus"></span>Delete</button>
</td>
</tr>
<tr>
</div>
</table>
</form>
</div>
</div>
<div *ngIf=ischecks style="margin-left:35%">
<label for="fname">Reason:</label><br>
<input type="text" id="fname" name="fname" ><br>
</div>
<br>
<button type="button" class="btn btn-outline-success"
style="border-radius:40px;margin-left: 50px;margin-bottom: 30%;" (click)="AddBtn()" ><span class="fa fa-plus"></span>Add</button>
https://stackblitz.com/edit/angular-ivy-3pbdwv?file=src/app/app.component.html
Примечание: Если вы не понимаете вопрос, не стесняйтесь задавать мне в комментариях, adn Я работаю в angular (typescript)
Ответ №1:
Этого будет трудно достичь с помощью basic Javascript
. Приведенный ниже подход использует ReactiveForm
подход
Мы выполняем следующие шаги
- Добавьте
ReactiveFormsModule
вimports
массив модуля
@NgModule({
imports:[ ReactiveFormsModule, ... ],
- Внедрить
FormBuilder
класс
constructor(private fb: FormBuilder) {}
- Определите форму
myForm = this.fb.group({
totalVal: [100],
formsArray: this.fb.array([this.fb.control("", { validators: [Validators.required] })]),
reason: ["", [Validators.required]]
}, { validators: [sumMatches] });
Мы добавили средство проверки cusom sumMatches
. Мы будем использовать это, чтобы проверить, была ли сопоставлена сумма общего значения
function sumMatches(control): ValidationErrors | undefined {
const totalVal = Number(control.get("totalVal").value);
const formsArrayTotal = control
.get("formsArray")
.value.reduce((a, b) => Number(a) Number(b), 0);
if (formsArrayTotal !== totalVal) {
return {
sumMismatch: true
};
}
return;
}
- Далее мы определяем вспомогательные
getter
функции для извлечения свойств изformGroup
get sumMismatch(): boolean {
return this.myForm.hasError('sumMismatch')
}
get arrayFullyFilled() {
return !this.formsArray.controls.some(item => item.errors)
}
get formsArray() {
return this.myForm.get("formsArray") as FormArray;
}
get totalVal() {
return this.myForm.get("totalVal") as FormControl;
}
- Нам также необходимо изменить функции для добавления и удаления элементов из FormArray
DelBtn = delIndex => this.formsArray.controls.splice(delIndex, 1);
AddBtn = () => this.formsArray.push(this.fb.control(""));
- Наконец, мы можем реализовать
formGroup
в html
<h2> Form</h2>
<span class='totalVal'>Total Value:{{ totalVal.value }}</span>
<form [formGroup]='myForm'>
<ng-container formArrayName='formsArray'>
<table *ngFor="let item of formsArray.controls; let i = index">
<tr>
<td>
<div>
<label [attr.for]="'fname' i">Value:</label><br>
<input type="number" [formControlName]="i" type="text" [id]="'fname' i" name="fname" ><br>
</div>
</td>
<td>
<button type="button" class="btn btn-outline-success"
s (click)="DelBtn(i)" ><span class="fa fa-plus"></span>Delete</button></td>
<tr>
</table>
</ng-container>
<div *ngIf='!sumMismatch amp;amp; arrayFullyFilled'>
<label for="fname">Reason:</label><br>
<input type="text" id="fname" name="fname" ><br>
</div>
<br>
<button type="button" class="btn btn-outline-success"
(click)="AddBtn()" ><span class="fa fa-plus"></span>Add</button>
<br>
<span class="error" *ngIf="sumMismatch amp;amp; myForm.touched">Total Value Mismatch</span>
</form>
Я извлек css в собственный файл
.totalVal {
font-weight: bolder;
font-family: verdana;
}
.btn-outline-success {
border-radius: 40px;
margin-left: 50px;
}
.error {
color: red;
}
Редактировать 1 — Как работает валидатор?
Чтобы понять это, мы рассмотрим, как мы создаем нашу группу форм. Мы определили структуру, которая создает значение в форме
{
totalVal: 100,
formsArray: [''],
reason: ''
}
Определяя нашу группу форм как this.fb.group({ ... }, {validators: [ sumMatches ] }
группу форм с указанным выше значением, она будет передана функции суммирования
В у sumMatches
нас будет что-то вроде a formGroup
со значением
{
totalVal: 100,
formsArray: ['50', '20', '10'],
reason: ''
}
В приведенном выше примере мы просто извлекаем 100 из того formGroup
control.get('totalVal').value
же to formArray
. Поскольку formArray
значение будет массивом, мы можем использовать reduce
функцию для суммирования этого.. Мы, наконец, сравниваем это и возвращаем null, если они совпадают, и an Object
, если они не совпадают.
При вышеуказанном подходе угловые реактивные формы обновят значение статуса формы valid
на основе того, что предоставлено пользователем. Следовательно, мы можем использовать этот valid
статус для обновления UI
arrayFullyFilled()
get arrayFullyFilled() {
return !this.formsArray.controls.some(item => item.errors)
}
Приведенный выше код пытается определить, заполнил ли пользователь ВСЕ входные данные в массиве. В нашем массиве мы получаем все элементы управления, проверяем, есть ли в некоторых из них ошибки, и если в каком-либо из них есть ошибка, возвращает false, в противном случае возвращает true. Это стало возможным, учитывая, что в моем formGroup
я сделал formControls
as required
с помощью Validators.required
проверки
Комментарии:
1. Привет, спасибо за ответ. не могли бы вы подробно объяснить код?
2. В какой части вы хотели бы получить разъяснения?
3. Можете ли вы объяснить мне раздел, требующий проверки. Я понимаю функциональность, но можете ли вы объяснить, как вы зациклили formbuilder внутри себя?
4. get arrayFullyFilled() { return !this.formsArray.controls.some(item => item.errors) } Я тоже не совсем понимаю эту строку?