2
votes

Using Angular 2 and Angular Material 6.4.7

I need to set a default selected option using the mat-select component.

The following code works as it should and sets the default value when I do not use the [formControl] binding.

example below:

<mat-form-field>
    <mat-select [(value)]="currentYear" placeholder="Select A Year" [formControl]="year.get('year')" >
        <mat-option *ngFor="let y of yearsArr;" [value]="y">{{ y }}</mat-option>
    </mat-select>
</mat-form-field>

The current year (currentYear) is a variable that gets set the value of the current year.

However when I use the form control binding it fails to set the default option on the mat-select component.

example below:

<mat-form-field>
    <mat-select [(value)]="currentYear" placeholder="Select A Year" [formControl]="year.get('year')" >
        <mat-option *ngFor="let y of yearsArr;" [value]="y">{{ y }}</mat-option>
    </mat-select>
</mat-form-field>

I searched stack overflow and came across this solution which works however I get a warning in the browsers console, I'm not sure if this is the correct method of achieving this.

example below:

<mat-form-field>
    <mat-select [(ngModel)]="currentYear" placeholder="Select A Year" [formControl]="year.get('year')" >
        <mat-option *ngFor="let y of yearsArr;" [value]="y">{{ y }}</mat-option>
    </mat-select>
</mat-form-field>

The warning I get is below:

It looks like you're using ngModel on the same form field as formControl. Support for using the ngModel input property and ngModelChange event with reactive form directives has been deprecated in Angular v6 and will be removed in Angular v7. For more information on this, see our API docs here: https://angular.io/api/forms/FormControlDirective#use-with-ngmodel

I have read the above output, but still can't understand how to fix this.

Any help to clarify or enlighten me on the correct method of achieving this would be greatly appreciated.

3
Hi, your suggestion is used just to inject a 'default option control'. I want to select and set an existing default option that is equal to the currentYear variable.Adamski

3 Answers

5
votes

The console warning tells you exactly what the issue is, either use the ngModel directive or the formControl directive, not both.

Check this question on how to select a default option with a formControl (it is for a multi select, but it works the same for your case).

Your template code should look something like this:

<mat-form-field>
  <mat-select placeholder="Select A Year" [formControl]="year.get('year')" >
      <mat-option *ngFor="let y of yearsArr;" [value]="y">{{ y }}</mat-option>
  </mat-select>
</mat-form-field>

And in your component you can set the value of your FormControl, i.e. something like this:

ngOnInit() {
  this.year.get('year').setValue(this.currentYear);
}
0
votes

You can set the value of the control when you build the form to the current year, in that way Angular will retrieve the value on form control binding.

0
votes

When I use a Angular material date picker I use that :

import {Component} from '@angular/core';
import {FormControl} from '@angular/forms';
import {MAT_MOMENT_DATE_FORMATS, MomentDateAdapter} from '@angular/material-moment-adapter';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';

// Depending on whether rollup is used, moment needs to be imported differently.
// Since Moment.js doesn't have a default export, we normally need to import using the `* as`
// syntax. However, rollup creates a synthetic default module and we thus need to import it using
// the `default as` syntax.
import * as _moment from 'moment';
// tslint:disable-next-line:no-duplicate-imports
import {default as _rollupMoment} from 'moment';

const moment = _rollupMoment || _moment;

/** @title Datepicker that uses Moment.js dates */
@Component({
  selector: 'datepicker-moment-example',
  templateUrl: 'datepicker-moment-example.html',
  styleUrls: ['datepicker-moment-example.css'],
  providers: [
    // `MomentDateAdapter` and `MAT_MOMENT_DATE_FORMATS` can be automatically provided by importing
    // `MatMomentDateModule` in your applications root module. We provide it at the component level
    // here, due to limitations of our example generation script.
    {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
    {provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS},
  ],
})
export class DatepickerMomentExample {
  // Datepicker takes `Moment` objects instead of `Date` objects.
  date = new FormControl(moment([getFullYear(), getMonth(), getDate()]));
}
<mat-form-field>
  <input matInput [matDatepicker]="dp" placeholder="Moment.js datepicker" [formControl]="date">
  <mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
  <mat-datepicker #dp></mat-datepicker>
</mat-form-field>

That work for you ?