简体   繁体   English

Mat-Error 首次打开表单时显示所需的验证错误消息

[英]Mat-Error Required validation error message shows when form is first open

I have a custom control component that is used to show a required validation error for mat-chip-lists.我有一个自定义控件组件,用于显示 mat-chip-lists 所需的验证错误。 On the form that I'm using this component, when I first open this form the required validation message shows.在我使用此组件的表单上,当我第一次打开此表单时,会显示所需的验证消息。 I only want it to show when the field is not populated with any data.我只希望它在该字段未填充任何数据时显示。 Can someone please provide a reason why and a solution to what I need to do to get the validation to work properly.有人可以提供一个原因以及我需要做什么才能使验证正常工作的解决方案。

I could be overcomplicating this and it's much simpler than I thought.我可能会过于复杂,它比我想象的要简单得多。

html where mat-error element for required show: html 其中所需显示的 mat-error 元素:

<mat-form-field [floatLabel]="floatLabel">
 <mat-label>{{ label }}</mat-label>
  <mat-chip-list #optionList aria-label="label" required>
   <mat-chip *ngFor="let item of selectedOptions" (removed)="removed(item)" 
 [removable]="!item.disabled" [disabled]="item.disabled">
  {{ item.text }}
  <mat-icon *ngIf="!item.disabled" matChipRemove>cancel</mat-icon>
</mat-chip>
  <input
  #optionInput
  type="text"
  [placeholder]="placeholder"
  [formControl]="formControl"
  [matAutocomplete]="optionAutoComplete"
  [matChipInputFor]="optionList"
  [required]="required"
  />
</mat-chip-list>
<mat-autocomplete #optionAutoComplete="matAutocomplete" 
 (optionSelected)="selected($event.option.value)">
  <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
  {{ option.text }}
  </mat-option>
 </mat-autocomplete>
 <mat-hint *ngIf="hint">{{ hint }}</mat-hint>
 </mat-form-field>
 <mat-error *ngIf="required === true && hasValue === false"> {{ label }} is 
 <strong>required</strong> </mat-error>

Typescript for the custom control The removed function fires when you remove selected items from the list.自定义控件的打字稿当您从列表中删除所选项目时,将触发删除的函数。 It turns the check back on and sends the update to the parent component.它重新打开检查并将更新发送到父组件。

 Component({
  selector: 'app-chips',
  templateUrl: './chips.component.html',
 })
 export class ChipsComponent implements OnInit, DoCheck {
  @Input() label = '';
  @Input() placeholder = '';
  @Input() options: Options[] = [];
  @Input() selectedOptions: Options[] = [];
  @Input() floatLabel: FloatLabelType = 'auto';
  @Input() hint!: string | undefined;
  @Input() required = true;
  hasValue: boolean = this.selectedOptions.length > 0;

 @ViewChild('optionInput') optionInput: ElementRef | undefined;

 @Output() onRemoved = new EventEmitter<Options>();
 @Output() selectedOptionsChanged = new EventEmitter<Options[]>();

formControl = new FormControl('');
filteredOptions: Observable<Options[]> | undefined;

iterableDiffer: IterableDiffer<Options>;

constructor(private readonly iterableDiffers: IterableDiffers) {
   this.iterableDiffer = this.iterableDiffers.find([]).create();
 }

 ngDoCheck(): void {
  const optionChanges = this.iterableDiffer.diff(this.options);
   if (optionChanges) {
    this.filteredOptions = of(this.options);
   }
   if (this.required === undefined) {
    this.required = false;
   }
 }

 ngOnInit(): void {
   this.subscribeFilterOptions();
}

 selected(value: Options): void {
  if (this.optionInput) {
    this.optionInput.nativeElement.value = '';
   }
   if (!this.selectedOptions.find((x) => x.text === value.text)) {
    this.selectedOptions.push(value);
    this.selectedOptionsChanged.emit(this.selectedOptions);
  }
  this.hasValue = this.selectedOptions.length > 0;
}

private subscribeFilterOptions() {
  this.filteredOptions = this.formControl.valueChanges.pipe(
    startWith(''),
    map((value: string | Options) =>
    value && typeof value === 'string' ? this.options.filter((o) => 
 o.text.toLowerCase().includes(value.toLowerCase())) : this.options.slice()
   )
  );
}
removed(value: Options): void {
  this.onRemoved.emit(value);
  this.hasValue = this.selectedOptions.length > 0;
  }
 }

Mat-chip-list component on the form表单上的 Mat-chip-list 组件

<div class="col-md-12">
  <app-linq-chips
    label="Entities"
    placeholder="Add Entity..."
    [options]="entityOptions"
    [selectedOptions]="selectedEntities"
    [hint]="
      entityListHasDisabledOptions === true
        ? 'Please remove this contact from any roles for an entity prior to removing their 
     association to that entity.'
        : undefined
    "
    (onRemoved)="removeEntity($event)"
  >
  </app-linq-chips>
</div>

Your variable hasValue is only set when a chip is selected or removed.您的变量hasValue仅在选择或移除芯片时设置。 When the component is initialized it's value is false as the number of selected options is zero.当组件初始化时,它的值为 false,因为所选选项的数量为零。

hasValue: boolean = this.selectedOptions.length > 0;

The required variable is initialized to true, so the mat error condition below: required变量被初始化为 true,所以下面的 mat 错误条件:

<mat-error *ngIf="required === true && hasValue === false"> {{ label }} is 
 <strong>required</strong> </mat-error>

will be true, so the error will show initially.将是真的,所以最初会显示错误。

To fix this issue, add an extra boolean variable, isInitialized (or whatever you want to name it), set it to false in the ngOnInit(), then set it to true in the ngAfterViewinit().要解决此问题,请添加一个额外的布尔变量isInitialized (或任何您想命名的变量),在 ngOnInit() 中将其设置为 false,然后在 ngAfterViewinit() 中将其设置为 true。

Update your mat-error condition like follows:更新您的mat-error条件,如下所示:

<mat-error *ngIf="required === true && hasValue === false && isInitialized === true"> {{ label }} is 
 <strong>required</strong> </mat-error>

Try the above and it should only error check after the component selections are made.尝试以上操作,它应该只在组件选择后进行错误检查。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM