web-dev-qa-db-fra.com

Comment arrêter mat-autocomplete pour séparer les valeurs d'entrée utilisateur personnalisées des options données?

J'utilise un composant complet mat-auto de material.angular.io. Le comportement par défaut est que l'utilisateur peut entrer n'importe quelle valeur et donne des options à choisir. Vous pouvez aussi ajouter votre entrée aux valeurs choisies. Vous pouvez vérifier exemple ici. https://stackblitz.com/angular/ngmvgralayd?file=app%2Fautocomplete-simple- example.html

voici le code que j'utilise pour générer un champ de saisie automatique. 

<form class="example-form">
  <mat-form-field class="example-full-width">
    <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto" disabled="true">
    <mat-autocomplete #auto="matAutocomplete">
      <mat-option *ngFor="let option of options" [value]="option">
        {{ option }}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>

Mais je veux que le champ de formulaire ne prenne que des valeurs de l'option donnée et je veux empêcher d'entrer des valeurs par les utilisateurs en dehors de l'option donnée. Comment y parvenir? C'est comme sélectionner l'entrée avec la fonction de complétion automatique. 

4
jaydeep marvaniya

Vous pouvez faire quelque chose comme ça

Balisage:

<md-input-container class="full-width">
<input mdInput [mdAutocomplete]="autoData"
       #searchMyData
       formControlName="myControl"
       (keyup)="changeMyControl()">
</md-input-container>
<md-autocomplete #autoData="mdAutocomplete">
<md-option
    *ngFor="let option of options"
    [value]="option.name"
    (onSelectionChange)="onSelectedOption($event.source.selected, option.id);">
    {{ option.name }}
</md-option>
</md-autocomplete>

Composant:

selectedOption;
changeMyControl(): void {
    if (isUndefined(this.selectedOption) {
        // also check selected item and entered text are not same
        this.myForm.get('myControl').setErrors({'incorrect': true});
    }
}

onSelectedOption(isSelected: boolean, id: number): void {
    if (isSelected) {
        setTimeout(() => {
            const option = this.options.filter(bt => bt.id === id);
            if (option.length > 0) {
                this.selectedOption= option[0];
               // patch formcontrol value here
            }
        }, 200);
    }
}
4
Ketan Akbari

Comme déjà suggéré dans le commentaire de @trichetriche, il s'agit d'un cas d'utilisation pour select.

Vous pouvez utiliser la version matérielle de select, comme ceci

<mat-form-field>
  <mat-select placeholder="Favorite food">
    <mat-option *ngFor="let food of foods" [value]="food.value">
      {{ food.viewValue }}
    </mat-option>
  </mat-select>
</mat-form-field>

Si vous avez besoin de filtrer au-dessus de la sélection, je vous le suggère PrimeNg Dropdown https://www.primefaces.org/primeng/#/dropdown

2
David Votrubec

La démo Material pour les puces à complétion automatique affiche les liaisons à la fois dans les variables input et mat-autocomplete:

<input (matChipInputTokenEnd)="add($event)">
<mat-autocomplete (optionSelected)="selected($event)"></mat-autocomplete>

Si vous souhaitez uniquement autoriser les options à partir de la saisie semi-automatique, omettez simplement la fonction add de l'entrée. 

0
adamdport

Je pense qu’il ya ici une question d’UI/UX: comment empêcher l’utilisateur de saisir quelque chose qui ne figure pas dans la liste des options tout en lui permettant de filtrer par une chaîne?

Je vois quelques options possibles. La première consiste simplement à afficher une erreur «Entrée non valide» lorsque l’option ne figure pas dans la liste adjacente à l’entrée. La deuxième option serait d'empêcher réellement la saisie de caractères qui ne correspondent plus à aucune option. Donc, s'il n'y a qu'une seule option "foo" et qu'un utilisateur tape "pour", seul "fo" sera accepté et le "r" sera jeté.

La solution PrimeNg n'est pas tout à fait la même chose qu'un champ de texte qui permet à un utilisateur de commencer à taper sur le focus. L'utilisateur doit d'abord cliquer pour ouvrir une recherche et il semble n'y avoir aucune accessibilité au clavier. Je ne vois pas vraiment pourquoi ils ne l'ont pas implémenté de telle sorte que l'affichage et la recherche soient les mêmes, sauf qu'ils ont des logos affichés.

0
Mark