Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop mat-autocomplete to take custom user input values apart from given options?

I am using mat-auto complete component from material.angular.io. The default behavior is user can input any value as well as it gives options to choose from. Also you can add your input to chosen values. You can check example here. https://stackblitz.com/angular/ngmvgralayd?file=app%2Fautocomplete-simple- example.html

here is the code I am using for generating auto complete input field.

<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>

But I want the form field to take only values from the given option and want to prevent from entering any values by users apart from given option. How to achieve this? It is like select input with auto complete feature.

like image 344
Talk is Cheap Show me Code Avatar asked Mar 22 '18 10:03

Talk is Cheap Show me Code


People also ask

How do you clear mat autocomplete when no option is selected from autocomplete dropdown?

You can remove the formControl-binding from your input and when you select an option you set that id to your form. You are already calling such a function (onSelectionChange)="onEnteredAccount(accountOption)" in which you can do that.

How do you use autocomplete mat?

Simple autocompleteStart by creating the autocomplete panel and the options displayed inside it. Each option should be defined by a mat-option tag. Set each option's value property to whatever you'd like the value of the text input to be when that option is selected.

How do you increase the width of an autocomplete mat?

In order to change width use below CSS. width: auto ! important; works a little better than min-width since it won't make the overlay large if it doesn't need to. Then you can use a max-width too keep it from getting to unreasonable.

How do I disable the autocomplete for input fields?

To disable the autocomplete for input fields, we need to set its autocomplete attribute to off. Here is an example, that turnsoff the autocomplete for email input field: We can also disable the autocomplete for an entire form, instead of a specific input field by setting an autocomplete="off" to the html <form> element.

How do I use the autocomplete attribute?

The autocomplete attribute works with the following <input> types: text, search, url, tel, email, password, datepickers, range, and color. Let’s see an example where the autocomplete for the whole form is set to "on" and only for a specific <input> is set to "off". Fill the form and submit, then reload the page to see how the autocomplete works.

What happens when autocomplete is set to off?

These are things that happen if you set an autocomplete="off" to the form fields. It tells the browser not to save user-inputted data for later autocompletion.

How to disable the underlayed input in mat-autocomplete?

User selects an item from mat-autocomplete. (works as expected.) The user clicks on the clear button on the right (matSuffix). The method on the clear button disables the input and sets event.stopPropagation () to prevent the underlayed input get focused. Result: The options panel still showing. The user can select an item.


4 Answers

Found this solution on github it may provide a simple alternative to those who end up here.

Create a custom validator:

private requireMatch(control: FormControl): ValidationErrors | null {
  const selection: any = control.value;
  if (this.options && this.options.indexOf(selection) < 0) {
    return { requireMatch: true };
  }
  return null;
}

Attach it to your control (we need to bind it to this so that our validator can access our options in our component's scope)

  myControl = new FormControl(undefined, [Validators.required, this.requireMatch.bind(this)]);

Optionally show error:

  <mat-error *ngIf="myControl.errors?.requireMatch">Value need match available options</mat-error>

Example here -----------> https://stackblitz.com/edit/angular-hph5yz

like image 89
Arno 2501 Avatar answered Oct 09 '22 00:10

Arno 2501


You can do something like this

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>

Component:

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);
    }
}
like image 39
Ketan Akbari Avatar answered Oct 09 '22 01:10

Ketan Akbari


The Material demo for chips autocomplete shows bindings on both the input and to the mat-autocomplete:

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

If you only want to allow options from the autocomplete, just omit the add function from the input.

like image 1
adamdport Avatar answered Oct 09 '22 02:10

adamdport


I think there is a UI/UX question here - in what way do we prevent the user from typing something that is not in the list of options, but still allow them to filter by a string?

I see a couple of potential options. First one is to just display an error "Invalid entry" when the option isn't in the list adjacent to the input. The second option would be to actually prevent the entry of characters that no longer match any options. So if there is a single option "foo" and a user types "for", only "fo" would be accepted, and the 'r' gets thrown out.

The PrimeNg solution is not quite the same as a text field that allows a user to start typing on focus. The user needs to first click to open a search, and there appears to be no keyboard accessibility. I don't really see why they haven't implemented it such that display and the search are the same, except they've got logos displayed.

like image 1
Mark Avatar answered Oct 09 '22 02:10

Mark