Angular 2 Material - Using MD's autocomplete example in a form

12,969

Solution 1

Take a look at this GitHub example: Demo with md-autocomplete (forms)

There is an example with both reactive and template-driven form. With the template driven form you remove the formControl completely, and just use [(ngModel)] and (ngModelChange) instead. Here's sample for you with the template-driven solution:

<form #f="ngForm">
  <md-input-container>
    <input mdInput placeholder="State" [mdAutocomplete]="tdAuto" name="state" 
       #state="ngModel" [(ngModel)]="currentState"
      (ngModelChange)="tdStates = filterStates(currentState)">
  </md-input-container>

  <md-autocomplete #tdAuto="mdAutocomplete">
    <md-option *ngFor="let state of tdStates" [value]="state">
      <span>{{ state }}</span>
    </md-option>
  </md-autocomplete>    
</form>

and in component we assign the filtered value to a different variable (tdStates) and keep all states in the states array:

filterStates(val: string) {
  if (val) {
    const filterValue = val.toLowerCase();
    return this.states.filter(state => state.toLowerCase().startsWith(filterValue));
  }
  return this.states;
}

DEMO

Solution 2

I have taken the example form from material's website and added md-autocomplete to it. In the demo, you can filter and select a state from the autocomplete. When the form is submitted, you can see the value getting passed to alert.

HTML:

Full code in plunker demo

<form>

// add all form code

<md-autocomplete #auto="mdAutocomplete" >
    <md-option *ngFor="let state of filteredStates | async" [value]="state" (onSelectionChange)="selectState(state, addForm.value)">
      {{ state }}
    </md-option>
</md-autocomplete>

</form>

app.ts:

selectState(state, form){
    form.state = state;
  }

Solution 3

  states = [];
  tdStates = [];
  currentState = '';

  ngOnInit() {
    this.states= [
      {code: 'AL', name: 'Alabama'},
      {code: 'AK', name: 'Alaska'},
      {code: 'AZ', name: 'Arizona'},
      {code: 'AR', name: 'Arkansas'},
      {code: 'CA', name: 'California'},
      {code: 'CO', name: 'Colorado'},
      {code: 'CT', name: 'Connecticut'},
      {code: 'DE', name: 'Delaware'},
      {code: 'FL', name: 'Florida'},
      {code: 'GA', name: 'Georgia'},
      {code: 'HI', name: 'Hawaii'},
      {code: 'ID', name: 'Idaho'},
      {code: 'IL', name: 'Illinois'},
      {code: 'IN', name: 'Indiana'},
      {code: 'IA', name: 'Iowa'},
      {code: 'KS', name: 'Kansas'},
      {code: 'KY', name: 'Kentucky'},
      {code: 'LA', name: 'Louisiana'},
      {code: 'ME', name: 'Maine'},
      {code: 'MD', name: 'Maryland'},
      {code: 'MA', name: 'Massachusetts'},
      {code: 'MI', name: 'Michigan'},
      {code: 'MN', name: 'Minnesota'},
      {code: 'MS', name: 'Mississippi'},
      {code: 'MO', name: 'Missouri'},
      {code: 'MT', name: 'Montana'},
      {code: 'NE', name: 'Nebraska'},
      {code: 'NV', name: 'Nevada'},
      {code: 'NH', name: 'New Hampshire'},
      {code: 'NJ', name: 'New Jersey'},
      {code: 'NM', name: 'New Mexico'},
      {code: 'NY', name: 'New York'},
      {code: 'NC', name: 'North Carolina'},
      {code: 'ND', name: 'North Dakota'},
      {code: 'OH', name: 'Ohio'},
      {code: 'OK', name: 'Oklahoma'},
      {code: 'OR', name: 'Oregon'},
      {code: 'PA', name: 'Pennsylvania'},
      {code: 'RI', name: 'Rhode Island'},
      {code: 'SC', name: 'South Carolina'},
      {code: 'SD', name: 'South Dakota'},
      {code: 'TN', name: 'Tennessee'},
      {code: 'TX', name: 'Texas'},
      {code: 'UT', name: 'Utah'},
      {code: 'VT', name: 'Vermont'},
      {code: 'VA', name: 'Virginia'},
      {code: 'WA', name: 'Washington'},
      {code: 'WV', name: 'West Virginia'},
      {code: 'WI', name: 'Wisconsin'},
      {code: 'WY', name: 'Wyoming'},
    ];
  }

  filterStates(val: string) {
    if (val) {
      const filterValue = val.toLowerCase();
      return this.states.filter(state => state.name.toLowerCase().startsWith(filterValue));
    }
    return this.states;
  }
Share:
12,969
av0000
Author by

av0000

Updated on June 13, 2022

Comments

  • av0000
    av0000 almost 2 years

    Is there a way to have the autocomplete work inside a form? I have a form that takes input for an address. I'm using autocomplete (copied from Material Design's docs) for states (this is in the US) and that is working except that the selected state is not being set to user.state. So when I console log out the myForm.form.value on submit it looks like this:

    user.name : "Test"
    user.phone: ...
    etc.
    

    with user.state not even showing up.

    My (relevant) code:

    <md-input-container>
      <input 
        mdInput 
        placeholder="State" 
        [mdAutocomplete]="auto"
        [formControl]="stateCtrl"
        name="user.state" 
        [(ngModel)]="user.state"
      >
    </md-input-container>
    
    <md-autocomplete 
        #auto="mdAutocomplete"
    >
      <md-option 
        *ngFor="let state of filteredStates | async" [value]="state"
        (onSelectionChange)="selectState(state)"
      >
        {{ state }}
      </md-option>
    </md-autocomplete> 
    

    TS:

      constructor(public dialog: MdDialog,) { 
        this.stateCtrl = new FormControl();
        this.filteredStates = this.stateCtrl.valueChanges
            .startWith(null)
            .map(name => this.filterStates(name));
      }
    
      filterStates(val: string) {
        return val ? this.states.filter(s => new RegExp(`^${val}`, 'gi').test(s))
                   : this.states;
      }
    

    Even when I try to use (onSelectionChange) to call function selectState(state) to set the user.state it still doesn't show up when I console.log the form on submit.

      selectState(value){
        this.user.state = value;
      }