Как очистить и показать ошибку в нескольких автозаполненных компонентах, когда элемент не выбран из предложенных вариантов - PullRequest
0 голосов
/ 28 мая 2019

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

https://stackblitz.com/edit/angular-nkajg5

Я хочу очистить или установить значение компонента равным '', если ввод, введенный пользователем, не является элементом из предложенных элементов в mat-autocomplete. Затем я также хочу отобразить для них ошибку mat: «Введенное значение НЕ ДЕЙСТВИТЕЛЬНО, выберите только из предложенных значений».

Я получил его на работу, следуя двум примерам, которые нашел. Очистка ввода

https://stackblitz.com/edit/autocomplete-force-selection-tests-w2fqww?file=app%2Fapp.component.html

С сообщением об ошибке

https://stackblitz.com/edit/angular-kdym4u

Однако у меня есть три компонента автозаполнения, и это вызывает проблемы, когда я пытаюсь использовать метод на всех трех компонентах и ​​вызывать их из ngAfterViewInit. Нет сообщений об ошибках, он просто не очищает ввод или не показывает сообщение об ошибке. Так что моя функция, похоже, не вызывается. (если честно, я не совсем уверен, для чего используется переменная подписки в коде) Я думаю, что это должно что-то делать с подпиской и откуда я ее вызываю из ngAfterViewInt (). Я проверил это, и только первый компонент работает сам по себе. Я тоже попробовал два других компонента по темам, и они не работают вообще, даже когда они являются единственным используемым элементом управления. У меня есть три matAutocomplete в tabGroup, а два других находятся на второй вкладке tabGroup.

Мой конструктор с моими группами форм

  constructor(private dialogRecipient:MatDialog,private fb: FormBuilder, private dialogRef: MatDialogRef<UpdateTaskComponent>,private snackBar: MatSnackBar, 
    @Inject(MAT_DIALOG_DATA){Enabled ,TaskName, TaskDescription,EmailSubject, EmailBody, tTaskTeam, PK_Task}, private service: TaskService ) { 
      this.pk_Task = PK_Task;
      console.log(this.pk_Task)
      this.form = fb.group({
        enabled: [Enabled],
        tTaskTeam: [tTaskTeam, Validators.required],
        taskName: [TaskName],
        taskDescription: [TaskDescription],
        emailSubject: [EmailSubject],
        emailBody: [EmailBody]
      })

      this.AdditionalRecipientForm = fb.group({
        recipientType: ['',Validators.required],
        tofficeUser: ['',Validators.required],
        tOfficeUserEmail: '',
        FK_Task: [this.pk_Task]
      })

    }

Как я использую @ViewChild для получения MatAutoCompletes

  @ViewChild(MatAutocomplete) autoCompleteForTaskTeam: MatAutocomplete;
  @ViewChild('auto') auto: MatAutocomplete;
  @ViewChild('autotest') autotest: MatAutocomplete;
  @ViewChild(MatTable) table: MatTable<RecipientInterface>;
  @ViewChild(MatAutocompleteTrigger) trigger: MatAutocompleteTrigger;
  subscription: Subscription;

Где я вызываю метод на элементах управления

ngAfterViewInit() {

Если я вызываю только элемент управления tTaskTeam, он работает, но когда я ставлю все три, он перестает работать

this._subscribeToClosingActions(this.form.controls.tTaskTeam); 
this._subscribeToClosingActions(this.AdditionalRecipientForm.controls.recipientType);
    this._subscribeToClosingActions(this.AdditionalRecipientForm.controls.tofficeUser);
        }

ngOnDestroy() {
  if (this.subscription && !this.subscription.closed) {
    this.subscription.unsubscribe();
  }
}

метод, который показывает ошибку, устанавливает для моего элемента управления значение '' и очищает его, если это не значение из предложенного.

private _subscribeToClosingActions(control): void {
  if (this.subscription && !this.subscription.closed) {
    this.subscription.unsubscribe();
  }
  this.subscription = this.trigger.panelClosingActions
    .subscribe(e => {
      if (!e || !e.source) {
       control.setValue('');
      }
    },
    err => this._subscribeToClosingActions(control),
    () => this._subscribeToClosingActions(control));
}

код шаблона:

<h2 mat-dialog-title>Update Entry</h2>
<mat-tab-group dynamicHeight>
  <mat-tab label="Task Information">
    <div class="example-small-box mat-elevation-z4">
      <mat-dialog-content  [formGroup]="form" class="example-form" >
        <mat-slide-toggle color="primary" (click)="textForToggle()" formControlName="enabled" >{{toggle ? 'Enabled': 'Disabled'}}</mat-slide-toggle>

            <mat-form-field class="task-info-form-field" >
                <input matInput placeholder="Report Name" formControlName="taskName">
            </mat-form-field>
            <br>
            <mat-form-field  appearance="outline" class="task-info-form-field" >

Первый компонент автозаполнения

<input matInput (keyup.enter)="chooseFirstOption(autoCompleteForTaskTeam)" [matAutocomplete]="autoCompleteForTaskTeam" formControlName="tTaskTeam" matTooltip="You can search and it will try to autocomplete the name for you!" placeholder="Select Group">
                  <mat-autocomplete #autoCompleteForTaskTeam='matAutocomplete'  [displayWith]="displayTeamName">
                    <mat-option class="matAutoCompleteSelect"*ngFor="let user of filteredOptions | async" 
                      [value]="user">
                      <span>{{ user.TeamName }}</span>
                    </mat-option>
                  </mat-autocomplete>
                  <mat-error >
                    Value entered is NOT VALID please selected only from suggested values.
                  </mat-error>
                </mat-form-field>
                <br>
                <mat-form-field class="task-info-form-field" >
                  <textarea #message matInput placeholder="Report Description"  formControlName="taskDescription"></textarea>
                  <mat-hint align="end">{{message.value.length}} / 256</mat-hint>
                  <mat-hint align="start"><strong>Put a detailed Description</strong> </mat-hint>
                  <mat-error >
                    Please enter less than 256 characters.
                  </mat-error>
                </mat-form-field>
                <br>
                <mat-form-field class="task-info-form-field" >
                  <input matInput placeholder="Email Subject: " formControlName="emailSubject">
                </mat-form-field>
                <br>
                <mat-form-field class="task-info-form-field">
                  <textarea matInput #message2 placeholder="Email Body"  formControlName="emailBody"></textarea>
                  <mat-hint align="end">{{message2.value.length}} / 256</mat-hint>
                  <mat-error >
                    Please enter less than 256 characters.
                  </mat-error>
                </mat-form-field>
          </mat-dialog-content>

        </div>
      </mat-tab>
      <mat-tab class="example-containerGrid" label="Recipient Information">

        <div class="example-containerGrid mat-elevation-z8">
          <div class="example-header">
            <mat-form-field class="searchGrid-form-field">
              <input matInput #filter (keyup)="applyFilter($event.target.value)" placeholder="Filter Doesn't Work At The Moment">
              <button mat-icon-button matSuffix aria-label="clear" *ngIf="filter.value" (click)="filter.value=''; applyFilter('');">
                <mat-icon>close</mat-icon>
              </button>
            </mat-form-field>
          </div>

          <mat-table #table [dataSource]="dataSource">

            <ng-container matColumnDef="Login">
              <mat-header-cell *matHeaderCellDef> Login </mat-header-cell>
              <mat-cell *matCellDef="let element"> {{element.tOfficeUser.Login}} </mat-cell>
            </ng-container>

            <ng-container matColumnDef="Email">
              <mat-header-cell class="actionsCell" *matHeaderCellDef> Email </mat-header-cell>
              <mat-cell *matCellDef="let element"> {{element.tOfficeUser.Email}} </mat-cell>
            </ng-container>

            <ng-container matColumnDef="typerecipient">
              <mat-header-cell *matHeaderCellDef> Type Of Recipient </mat-header-cell>
              <mat-cell *matCellDef="let element"> {{element.RecipientType.typerecipient}} </mat-cell>
            </ng-container>

            <ng-container matColumnDef="Actions">
                <mat-header-cell  *matHeaderCellDef> Actions  </mat-header-cell>
                <mat-cell  *matCellDef="let element"> {{element.Actions}}
                <div class="example-button-row">  
                  <button mat-raised-button color="primary"  (click)="updateRecipientInfo(element)"> <mat-icon class="example-icon" matTooltip="You can edit this report">edit</mat-icon> <b>Edit</b></button>
                  <!-- <button mat-raised-button (click)="test">  <mat-icon class="example-icon" matTooltip="This button is to copy reports"> filter_none </mat-icon><b>Copy</b></button> -->
                  <button mat-raised-button color="warn" (click)="deleteRecipient(element)">  <mat-icon class="example-icon" matTooltip="This is to delete this report"> delete_outline</mat-icon><b>Delete</b></button>
                </div>
              </mat-cell>
            </ng-container>

            <!-- Fav Column -->
            <!-- <ng-container matColumnDef="fav">
              <mat-header-cell *matHeaderCellDef> Favorite </mat-header-cell>
              <mat-cell *matCellDef="let element">
                <mat-form-field floatLabel="never">
                  <mat-select [(value)]="element.fav" placeholder="Favorite">
                    <mat-option>None</mat-option>
                    <mat-option value="Yes">Yes</mat-option>
                  </mat-select>
                </mat-form-field>
              </mat-cell>
            </ng-container> -->

            <mat-header-row *matHeaderRowDef="columnsToDisplay; sticky: true"></mat-header-row>
            <mat-row *matRowDef="let row; columns: columnsToDisplay;"></mat-row>
          </mat-table>
          <mat-card class="spinnerMatCard" *ngIf="isLoading">
              <mat-progress-spinner 
                color="primary" 
                mode="indeterminate">
              </mat-progress-spinner>
            </mat-card>
        </div>



        <div class="example-container mat-elevation-z8">
            <mat-accordion>
                <mat-expansion-panel [formGroup]="AdditionalRecipientForm"> 
                  <mat-expansion-panel-header [collapsedHeight]="customCollapsedHeight" [expandedHeight]="customExpandedHeight">
                    <mat-panel-title>
                      Add Additional Recipients
                    </mat-panel-title>
                    <mat-panel-description>
                      Type your name and age
                    </mat-panel-description>
                  </mat-expansion-panel-header>
                  <button mat-raised-button (click)="createNewRecipientUser()" [disabled]="!AdditionalRecipientForm.valid" [disabled]="!AdditionalRecipientForm.dirty" color="primary"><b>Update</b></button>
                  <button mat-raised-button  (click)="resetFields()" color="primary"><b>Reset</b></button>
                  <br>

                    <mat-form-field appearance="outline">
                        <mat-label>Login Name Field</mat-label>

Второй компонент автозаполнения

 matTooltip="You can search and it will try to autocomplete the name for you!" placeholder="Select Type Of Logins">

                <mat-hint>You can type in the name and it will autocomplete for you!</mat-hint>
              <mat-autocomplete #auto [displayWith]="displayLogin">
                  <mat-option class="matAutoCompleteSelect"*ngFor="let user of OfficeUserfilteredOptions | async" 
                    [value]="user">
                    <span>{{ user.Login }}</span>
                  </mat-option>
              </mat-autocomplete>
              <mat-error >
                Value entered is NOT VALID please selected only from suggested values.
              </mat-error>
            </mat-form-field>

            <mat-form-field class="add-addtional-recipients-form-field" appearance="outline">
                <mat-label>Email Field</mat-label>
              <input  matInput placeholder="User Email Address"   formControlName="tOfficeUserEmail">

              <mat-hint align="left"><strong>You cannot edit user email address here! Select a login to see the email.</strong> </mat-hint>
            </mat-form-field>

            <mat-form-field class="add-addtional-recipients-form-field" appearance="outline">
                <mat-label>Recipient Type</mat-label>

Третий компонент автозаполнения

   <input matInput [matAutocomplete]="autotest" (keyup.enter)="chooseFirstOptionForAutoTest()" formControlName="recipientType" matTooltip="You can search and it will try to autocomplete the name for you!" placeholder="Select Type Of Recipient">
                <mat-hint>Start typing in the type of reicpient you want. </mat-hint>
                <mat-autocomplete #autotest  [displayWith]="displayRecipientName">
                  <mat-option class="matAutoCompleteSelect"*ngFor="let user of filteredRecipientOptions | async" 
                    [value]="user">
                    <span>{{ user.typerecipient }}</span>
                  </mat-option>
                </mat-autocomplete>
                <mat-error >
                  Value entered is NOT VALID please selected only from suggested values.
                </mat-error>
              </mat-form-field>
        </mat-expansion-panel>
      </mat-accordion>
</div> 

близко Сохранить

1 Ответ

0 голосов
/ 29 мая 2019

Если кто-то когда-либо начинает работать с более чем одним автозаполнением в форме и хочет очистить ввод, если это не один из элементов, предложенных в ваших данных, и показать сообщение об ошибке.Я нашел решение:

Моя проблема в том, что триггер, на который я пытался сослаться, находит только первое автозаполнение, найденное в DOM.

 @ViewChild(MatAutocompleteTrigger) trigger: MatAutocompleteTrigger;

Итак, мне нужно подписаться на каждый триггер MatAutoComplete, поскольку каждый из них имеет свой собственный.Чтобы сделать это, мы должны создать

@ViewChildren(MatAutocompleteTrigger) triggerCollection: QueryList<MatAutocompleteTrigger>;

. Он будет содержать коллекцию всех триггеров элементов управления matAutComplete.

Оттуда мы можем пройти коллекцию, сделав ее массивом и проверив, какой из элементов управления является грязным.

private _subscribeToClosingActions(): void {

    if (this.subscription && !this.subscription.closed) {
      this.subscription.unsubscribe();
    }

for (var trigger of this.triggerCollection.toArray()) {
    this.subscription = trigger.panelClosingActions
      .subscribe(e => {
        if (!e || !e.source) {
        if(this.CarsFormGroup.controls.carCtrl.dirty) {
 this.CarsFormGroup.controls.carCtrl.setValue(null);
          }
        if(this.StatesFormGroup.controls.stateCtrl.dirty) {
 this.StatesFormGroup.controls.stateCtrl.setValue(null);
          }
        }
  });
}
  }
...