Reputation: 1967
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;
}
Upvotes: 7
Views: 13396
Reputation: 11
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;
}
Upvotes: 1
Reputation: 11
<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.name">
<span>{{ state.name }}</span>
</md-option>
</md-autocomplete>
Upvotes: 0
Reputation: 73337
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;
}
Upvotes: 16
Reputation: 13297
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;
}
Upvotes: 2