0

Sorry if this is a duplicate! So I am trying to have my mat-select default to the first option in the list. Sounds easy enough, right? Wrong. I am using a modal that pops up to enter a task and am trying to set the default status (which you are only able to select once the project is selected). The compareWith function works just fine, but once you exit out of the modal and re-enter(without refreshing the page), the second parameter in the compareWith function is null and the status doesn't default to anything. When exiting the form, I reset it. I am using FormControl, not ngModel, just an FYI.

I have tried a couple different compareWith functions, but only found one that works. I have tried using the [selected]="whatever" on the select tag but quickly found out through research that it doesn't work for material inputs. I have also tried setting the formcontrol value equal to status when resetting the form. This works, but it is displaying already when I open the modal again. Since the status is disabled until the project is selected, I don't want to show any status on load.

Project select in the html:

<mat-form-field class="form-group">
      <mat-select id="project" name="project" placeholder="Project" formControlName="project" [required]="true"
        [ngClass]="{'is-invalid': formAddTask.project.errors}">
        <mat-option *ngFor="let project of availableProjects" [value]="project.id">{{project.name}}</mat-option>
      </mat-select>
      <mat-error *ngIf="addTaskForm.get('project').hasError('required')">Project is required</mat-error>
    </mat-form-field>

Status select in the html:

 <mat-form-field class="form-group">
      <div class="input-group"></div>
      <mat-select id="status" name="status" placeholder="Status" formControlName="status" [compareWith]="compareObjects">
        <mat-option *ngFor="let status of availableStatuses; let i = index" [class.selected]="status === selectedStatus" 
         [value]="status.id">{{status.name}}</mat-option>
      </mat-select>
    </mat-form-field>

CompareWith function in ts:

compareObjects(o1: any, o2: any): boolean {
return o1.name === o2.name && o1._id === o2._id;
}

Let me know if there is anything more I need to show!

The status shouldn't have anything in it until the project is selected, once that happens, I'd like the status to default to the first option in the list. What is actually happening is that once the modal is exited and returned to, the default status will no longer display after selecting a project, or it will display on the initial load of the modal, which I want it to only show the default once the project is selected.

Sorry if I was repeating myself too much, I'd rather give too much info than not enough. Thanks in advance, any help is appreciated! :)

Roman Skydan
  • 5,478
  • 4
  • 19
  • 39
Bri Prichard
  • 3
  • 1
  • 7

2 Answers2

0

First thing of the bat, Yes, [compareWith] can absolutely be used in modals

To fix the issue, use [(value)] instead of [value] and bind it to status instead of status.id. That means, compareWith will get the select value and the option value as status objects and the compare function, as you have it, will get ids and names from those objects and compare.

 <mat-form-field class="form-group">
      <div class="input-group"></div>
      <mat-select id="status" name="status" placeholder="Status" formControlName="status" [compareWith]="compareObjects">
        <mat-option *ngFor="let status of availableStatuses; let i = index" [class.selected]="status === selectedStatus" 
         [(value)]="status">{{status.name}}</mat-option>
      </mat-select>
    </mat-form-field>
Aragorn
  • 5,021
  • 5
  • 26
  • 37
  • Hi! Thanks for the answer. So when I change it to [ngValue], I get a console error that "Can't bind to ngValue' since it isn't a known property of 'mat-option". I have FormsModule and ReactiveFormsModule imported form angular/forms in my module.ts, So I'm not sure why this is giving me the error. I'm also pretty new to angular, so I'm hoping it isn't some error in my code somewhere else. – Bri Prichard Jan 22 '19 at 17:21
  • 1
    Also, I love your username haha. Huge nerd here ;) – Bri Prichard Jan 22 '19 at 17:24
  • @BriPrichard do you have FormsModule imported in app.module? If not, look here: https://stackoverflow.com/questions/38892771/cant-bind-to-ngmodel-since-it-isnt-a-known-property-of-input – Aragorn Jan 22 '19 at 18:56
  • Yes, I have it in both my app.module and the other module that I am using, but neither seems to like the ngValue. – Bri Prichard Jan 22 '19 at 19:04
  • Can you share the excerpt from app.module.ts, I can't really think why you'd not get [ngValue] – Aragorn Jan 22 '19 at 19:48
  • Sure, so this is the import `import { FormsModule } from '@angular/forms';` and this is where I'm importing it: `imports: [ FormsModule, [ then the rest of the imports] ]` – Bri Prichard Jan 22 '19 at 20:32
  • If you are still stuck, please create a stackblitz. – Aragorn Jan 22 '19 at 21:01
  • You mentioned you also have `ReactiveFormsModule` imported, is that right? – Aragorn Jan 22 '19 at 21:04
  • yep. So I finally figured it out. I ended up just making an onChange on the projects dropdown and inside I set the value of the status there. Sucks that it was such a workaround, but whatever it works now. – Bri Prichard Jan 22 '19 at 21:27
  • Hi - this was bothering me, so kept looking, I've tried on another post where there was a similar problem that I was able to solve using `[(value)]="status"`, Of course, you are free to continue using the changed approach you have, but in case you want to use the default select, I have updated the answer. – Aragorn Jan 24 '19 at 18:58
  • Thanks for the info :) – Bri Prichard Jan 25 '19 at 20:21
0

So I ended up finding a workaround. I added an onChange event to the project dropdown and set the value of the status dropdown there.

This is the code I ended up using:

onProjectChange() { this.addTaskForm.get('status').setValue(this.availableStatuses[0].id); }

Bri Prichard
  • 3
  • 1
  • 7