21 votes

Comment empêcher mat-autocomplete de prendre des valeurs d'entrée utilisateur personnalisées en dehors des options données ?

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

Voici le code que j'utilise pour générer un champ de saisie auto complet.

<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 du formulaire ne prenne que les valeurs de l'option donnée et je veux empêcher les utilisateurs de saisir d'autres valeurs que celles de l'option donnée. Comment y parvenir ? C'est comme une entrée de sélection avec une fonction de complétion automatique.

8voto

Ketan Akbari Points 3727

Vous pouvez faire quelque chose comme ceci

Markup :

<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);
    }
}

1voto

adamdport Points 495

El Démonstration matérielle de l'autocomplétion des puces montre les liaisons à la fois sur le input et à la mat-autocomplete :

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

Si vous souhaitez uniquement autoriser les options de la saisie semi-automatique, il suffit d'omettre l'élément add à partir de l'entrée.

1voto

Mark Points 2448

Je pense qu'il s'agit d'une question UI/UX ici - de quelle manière pouvons-nous empêcher l'utilisateur de taper quelque chose qui n'est pas dans la liste d'options, tout en lui permettant de filtrer par une chaîne ?

Je vois deux options potentielles. La première consiste à afficher simplement 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 l'entrée de caractères qui ne correspondent plus à aucune option. Ainsi, s'il n'y a qu'une seule option "foo" et que l'utilisateur tape "for", seul "fo" sera accepté, et le "r" sera rejeté.

El PrimeNg n'est pas tout à fait la même chose qu'un champ de texte qui permet à l'utilisateur de commencer à taper au moment où il se concentre. L'utilisateur doit d'abord cliquer pour ouvrir une recherche, et il ne semble pas y avoir d'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 identiques, sauf qu'ils ont des logos affichés.

0voto

David Votrubec Points 50

Comme déjà suggéré dans le commentaire de @trichetriche c'est 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 d'un filtre au dessus de la sélection, je vous suggère d'utiliser PrimeNg Dropdown. https://www.primefaces.org/primeng/#/dropdown

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X