Mat-ошибка не отображается для пользовательского контроля формы - PullRequest
0 голосов
/ 01 октября 2019

Создан контроллер адреса пользовательской формы адреса и используется внутри CustomerForm, при отправке формы, не заполняя ничего, получая ошибку мата обязательного поля для кода клиента и имени клиента, не получая никакой ошибки мата обязательного поля в Address1, Country, City,и Zipcode.

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

customer.component.html

<form (ngSubmit)=" custForm.valid && saveOrUpdateCustomer()" [formGroup]="custForm">

    <!-- Customer Code -->
     <mat-form-field>
        <input matInput placeholder="Customer Code" formControlName="custCode" required >
        <mat-error *ngIf="custForm.get('custCode').hasError('required')">
            *Required field
        </mat-error>
    </mat-form-field>

    <!-- Customer Name -->
    <mat-form-field>
        <input matInput placeholder="Customer Name" formControlName="custName" required>
        <mat-error *ngIf="custForm.get('custName').hasError('required')">
            *Required field
        </mat-error>
    </mat-form-field>

    <h6>Address Details</h6>
    <!--Address Detail-->
    <app-address formControlName="address" #address></app-address>
    <div *ngIf="custForm.controls['address'].hasError('isNotValid')">
    </div>
    <div>
        <button type="submit" >Submit</button>
    </div>
</form>

address.component.hml

<form [formGroup]="addressForm">

  <!-- Address 1 -->
  <mat-form-field>
    <input matInput placeholder="Address 1" formControlName="address1" required>
    <mat-error *ngIf="addressForm.get('address1').hasError('required')">
      *Required field
    </mat-error>
  </mat-form-field>
`
  <!-- Address 2 -->
  <mat-form-field>
    <input matInput placeholder="Address 2" formControlName="address2">
  </mat-form-field>

  <!-- Address 3 -->
  <mat-form-field>
    <input matInput placeholder="Address 3" formControlName="address3">
  </mat-form-field>

    <!-- Country -->
    <mat-form-field>
    <input matInput placeholder="Country" formControlName="country" required>
    <mat-error *ngIf="addressForm.get('country').hasError('required')">
      *Required field
    </mat-error>
  </mat-form-field>

    <!-- State -->
    <mat-form-field>
    <input matInput placeholder="State" formControlName="state">
  </mat-form-field>

    <!-- City -->
    <mat-form-field>
    <input matInput placeholder="City" formControlName="city" required>
    <mat-error *ngIf="addressForm.get('country').hasError('required')">
      *Required field
    </mat-error>
  </mat-form-field>

  <!-- Zip Code -->
  <mat-form-field>
    <input matInput placeholder="Zip Code">
    <mat-error *ngIf="addressForm.get('country').hasError('required')">
      *Required field
    </mat-error>
  </mat-form-field>

</form>

address.component.ts

import { Component, OnInit, forwardRef} from '@angular/core';
import { FormGroup, FormBuilder, Validators, ControlValueAccessor, NG_VALUE_ACCESSOR, FormControl, NG_VALIDATORS } from '@angular/forms';
import { Address } from 'app/model/address/address.interface';

@Component({
  selector: 'app-address',
  templateUrl: './address.component.html',
  styleUrls: ['./address.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: AddressComponent,
      multi: true
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => AddressComponent),
      multi: true,
    }
  ]
})
export class AddressComponent implements OnInit, ControlValueAccessor, Validators {

  public addressForm: FormGroup;
  private _address: any = {};
  istoched = false;

  constructor(
    private fb: FormBuilder,
  ) { }

  ngOnInit() {
    this.addressForm = this.fb.group({
      address1: ['', [Validators.required]],
      address2: [''],
      address3: [''],
      country: ['', [Validators.required]],
      state: [''],
      city: ['', [Validators.required]],
      zip: [''],
    });
  }

  propagateChange = (_: any) => { };

  writeValue(address: Address) {
    this._address = address;
    if (address) {
      this.addressForm.setValue({
        address1: address.address1,
        address2: address.address2,
        address3: address.address3,
        country: address.country,
        state: address.state,
        city: address.city,
        zip: address.zip,
      });
    }
  }

  registerOnChange(fn: any) {
    this.addressForm.valueChanges.subscribe(() => {
      fn(this.addressForm.value);
    });
  }

  registerOnTouched(fn: any) {
    this.propagateChange = fn;
  }

  public validate(formControl: FormControl) {
    let isValid = true;
    Object.keys(this.addressForm.controls).forEach((control) => {
      if (this.addressForm.controls[control] instanceof FormControl) {
        if (!(<FormControl>this.addressForm.controls[control]).valid) {
          isValid = false;
          if (this.istoched) {
            this.addressForm.controls[control].markAsTouched();
          }
        }
      }
    });
    this.istoched = true;
    if (isValid) {
      return null;
    } else {
      return {
        primaryContactError: {
          valid: false,
        }
      };
    }
  }
}

При нажатии на кнопку отправки формы клиента, если какое-либо обязательное поле не заполнено, в нем должна отображаться требуемая ошибка.

1 Ответ

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

Я думаю, вы, возможно, неправильно поняли, как использовать ControlValueAccessor. Он работает вместе с объектом FormControl, поэтому изменения, внесенные программно в FormControl, передаются в представление компонента. Вы реализовали ControlValueAccessor в AddressComponent, что требует использования типа <app-address [formControl]="..."> или <app-address formControlName="...">, но кажется, что AddressComponent представляет собой FormGroup. Таким образом, ни одна из ваших реализаций ControlValueAccessor не будет работать так, как задумано - и вам она может вообще не понадобиться.

Ваша логика validate() требует, чтобы элемент управления формы был недействительным, чтобы он был помечен как затронутый,но если элемент управления не трогать, он всегда будет действительным (поведение по умолчанию). Чтобы изменить поведение по умолчанию, внедрите свой собственный ErrorStateMatcher и примените его к своим MatInput входам. Я не вижу ничего, что регистрирует или вызывает validate() - вам нужно, чтобы это также происходило.

Кроме того, нет необходимости использовать условия *ngIf с <mat-error> элементами, если у вас нет нескольких <mat-error> s для разных типов ошибок, или вы хотите скрыть ошибки для других типов ошибок. <mat-error> будет отображаться, только если состояние элемента управления формы недопустимо.

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