Пользовательский элемент управления не обновляет проверку родительской формы - PullRequest
0 голосов
/ 04 октября 2019

Я работал над добавлением пользовательского элемента управления в форму, я хотел бы сделать это, потому что я знаю, что у нас есть несколько компонентов, которые могут составлять форму.

Так, например, у вас может быть что-токак в 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, однако он никогда не срабатывает при изменении значений в базовом массиве.

Может кто-нибудь объяснить, почему это так?

1 Ответ

0 голосов
/ 04 октября 2019

Хорошо, поэтому мне пришлось сделать несколько вещей здесь, чтобы заставить это работать. Я не буду публиковать весь код только соответствующие части.

  1. Мне нужно было добавить этоновый пользовательский Validator

    static ArrayMustBeValid (control: AbstractControl) {if (control.value) {if (control.value.length> 0) {let items: Model [] = control.value;

        let invalidIndex = items.findIndex(x=> !x.isValid);
        if(invalidIndex === -1) return null;
    
        return {'array': 'array items are not valid'};
      }
    }
    return {'array':'array cannot be null'};
    

    }

  2. Затем мне нужно было добавить событие обновления на вход, которое должно срабатывать при keyup

    onUpdate(){
        this.onChange(this.items);
      }
    
  3. Имелдобавить валидатор к FormControl в app.component.ts

    this.form.addControl('items', new FormControl([],[(control)=>MyValidator.MustHaveOne(control), (control)=>MyValidator.ArrayMustBeValid(control) ]))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...