Я работал над добавлением пользовательского элемента управления в форму, я хотел бы сделать это, потому что я знаю, что у нас есть несколько компонентов, которые могут составлять форму.
Так, например, у вас может быть что-токак в app.components.ts
:
import { Component, OnInit, AfterViewInit } from '@angular/core';
import { FormGroup, FormBuilder, FormControl, Validators, AbstractControl } from '@angular/forms';
import { Model } from './cool-array/cool-array.component';
@Component({
selector: 'app-root',
styleUrls: ['./app.component.css'],
template:`
<!--The content below is only a placeholder and can be replaced.-->
<div class="col-md-6">
<form [formGroup]="form" >
<div class="form-group">
<label >Name</label>
<input formControlName="name" type="text" class="form-control" >
</div>
<app-cool-array formControlName="items"></app-cool-array>
</form>
</div>
<div class="col-md-6">
<div class="row">
IsValid Form: <strong> {{form.valid}}</strong>
Total Errors: <strong>{{form.errors? form.errors.length:0}}</strong>
</div>
<div class="row">
<table class="table table-stripped">
<thead>
<tr>
<th>Error</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let error of form.errors">
</tr>
</tbody>
</table>
</div>
</div>
`
})
export class AppComponent implements OnInit, AfterViewInit {
/**
*
*/
constructor(private formBuilder:FormBuilder) {
}
form:FormGroup;
model:MyModel;
ngOnInit(): void {
this.model = new MyModel();
this.form = this.formBuilder.group({ });
this.form.addControl('name', new FormControl('', Validators.required));
this.form.addControl('items', new FormControl([],[(control)=>MyValidator.MustHaveOne(control) ]))
}
ngAfterViewInit(): void {
console.log(this.form.errors)
}
}
export class MyValidator{
static MustHaveOne(control:AbstractControl){
if(control.value.length === 0) return {'length':'Items Must Have at least 1 item'};
return null;
}
}
export class MyModel{
name:string='';
items:Model[]=[];
}
Вы также можете добавить дочерний компонент:
import { Component, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-cool-array',
styleUrls: ['./cool-array.component.css'],
providers:[
{
provide:NG_VALUE_ACCESSOR,
multi:true,
useExisting:CoolArrayComponent
}
],
template:`
<button (click)="onAdd()" class="btn btn-primary" >Add</button>
<button (click)="onRemove()" class="btn">Remove</button>
<table class="table table-striped table-responsive">
<thead>
<tr>
<th>Something Required</th>
<th>Something Not Requred</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of items" (click)="onSelectedItem(item)" [ngClass]="{'selected-item':item === selectedItem}">
<td><input class="form-control" required [(ngModel)]="item.somethingRequired"/></td>
<td><input class="form-control" [(ngModel)]="item.somethingNotRequired"/></td>
</tr>
</tbody>
</table>
`
})
export class CoolArrayComponent implements OnInit, ControlValueAccessor {
onChange:any = ()=>{};
onTouched: any = () => { };
writeValue(obj: any): void {
this.items = obj;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
disabled:boolean=false;
items:Model[]=[];
selectedItem:Model;
constructor() { }
ngOnInit() {
}
onAdd():void{
this.items.push(new Model());
}
onRemove():void{
let index = this.items.indexOf(this.selectedItem);
if(index>-1)
this.items.splice(index, 1);
}
onSelectedItem(event){
this.selectedItem = event;
}
}
export class Model{
somethingRequired:string;
somethingNotRequired:string;
get isValid():boolean{
return this.somethingRequired !==undefined && this.somethingRequired.length>0;
}
}
Когда дочерний компонент становится недействительным, это должно сделать форму недействительной. Я попытался добавить CustomValidator, однако он никогда не срабатывает при изменении значений в базовом массиве.
Может кто-нибудь объяснить, почему это так?