Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

material/select(ivy): breaking changes in Ivy for binding order with ngFor and value binding #18167

Closed
Splaktar opened this issue Jan 14, 2020 · 2 comments · Fixed by #18216
Closed
Assignees
Labels

Comments

@Splaktar
Copy link
Member

@Splaktar Splaktar commented Jan 14, 2020

Reproduction

Here is the StackBlitz, but since it doesn't run in Ivy, it's better to run this in the dev-app or a local app.
https://stackblitz.com/edit/angular-mj1ljk-5s64n6?file=src/app/select-value-binding-example.html

Steps to reproduce:

Given the following template

<mat-form-field>
  <mat-label>Native in MatFormField</mat-label>
  <select matNativeControl [value]="matAndNativeSelected">
    <option>None</option>
    <option [value]="option" *ngFor="let option of matAndNativeOptions">{{ option }}</option>
  </select>
</mat-form-field>

<p>You selected: {{matAndNativeSelected}}</p>

<label>Native Select</label>&nbsp;
<select [value]="nativeSelected">
  <option>None</option>
  <option [value]="option" *ngFor="let option of nativeOptions">{{ option }}</option>
</select>

<p>You selected: {{nativeSelected}}</p>

Expected Behavior

In View Engine, both [value] bindings on the <select> elements would properly set the initial value to 'option2'.

Actual Behavior

Both [value] bindings on the <select> elements will have no effect. No error is generated, but the template value is not set as expected.

This breaking change is covered in a recent documentation update on angular.io.

The suggested solution is to change to the following template:

<mat-form-field>
  <mat-label>Native in MatFormField</mat-label>
  <select matNativeControl>
    <option>None</option>
    <option [value]="option" [selected]="matAndNativeSelected === option" *ngFor="let option of matAndNativeOptions">{{ option }}</option>
  </select>
</mat-form-field>

<p>You selected: {{matAndNativeSelected}}</p>

<label>Native Select</label>&nbsp;
<select>
  <option>None</option>
  <option [value]="option" [selected]="nativeSelected === option" *ngFor="let option of nativeOptions">{{ option }}</option>
</select>

<p>You selected: {{nativeSelected}}</p>

When using the non-native <mat-select> with <mat-option> elements, applying a similar pattern is not supported as there is no selected Input on MatOption.

<mat-form-field>
  <mat-label>Material Select</mat-label>
  <mat-select>
    <mat-option>None</mat-option>
    <mat-option [value]="option" [selected]="materialSelected === option" *ngFor="let option of materialOptions">{{ option }}</mat-option>
  </mat-select>
</mat-form-field>

<p>You selected: {{materialSelected}}</p>
error NG8002: Can't bind to 'selected' since it isn't a known property of 'mat-option'.
1. If 'mat-option' is an Angular component and it has 'selected' input, then verify that it is part of this module.

36     <mat-option [value]="option" [selected]="materialSelected === option" *ngFor="let option of materialOptions">{{ option }}</mat-option>
                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  src/components-examples/material/select/select-overview/select-overview-example.ts:8:16
    8   templateUrl: 'select-overview-example.html',
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component SelectOverviewExample.

It's good that <mat-select> supports the View Engine [value] binding approach without any breaking change.
However, it unfortunately does not support the new recommended style used by native <select>. This is a bit confusing and complicates moving back and forth between <mat-select> and <select> in <mat-form-field> elements.

<mat-form-field>
  <mat-label>Material Select</mat-label>
  <mat-select [value]="materialSelected">
    <mat-option>None</mat-option>
    <mat-option [value]="option" *ngFor="let option of materialOptions">{{ option }}</mat-option>
  </mat-select>
</mat-form-field>

<p>You selected: {{materialSelected}}</p>

Actions needed

  1. Update the MatSelect docs to demonstrate the proper way to do this to reduce confusion and issue reports
  2. Consider adding a selected Input to MatOption

Environment

  • Angular: 9.0.0-rc.8
  • CDK/Material: 9.0.0-rc.7
  • Browser(s): Chrome
  • Operating System (e.g. Windows, macOS, Ubuntu): macOS

Related issues

@Splaktar

This comment has been minimized.

Copy link
Member Author

@Splaktar Splaktar commented Jan 15, 2020

From @crisbeto

If we add the selected Input, we'll have two sources of truth for the selected value: the select itself that matches options based on their value and the option's selected state which is completely independent and could conflict with the select. We had an issue recently in mat-selection-list that was due to the selected input #17840.

Splaktar added a commit that referenced this issue Jan 19, 2020
…o form

- demonstrates the new style of assigning initial values to native select
  - that is required by Ivy in version 9
- Related breaking change docs:
  - https://next.angular.io/guide/ivy-compatibility-examples#cannot-bind-to-value-property-of-select-with-ngfor

Fixes #18167
@Splaktar Splaktar removed the discussion label Jan 19, 2020
@Splaktar Splaktar self-assigned this Jan 19, 2020
@Splaktar Splaktar added the has pr label Jan 19, 2020
Splaktar added a commit that referenced this issue Jan 19, 2020
… value w/o form

- demonstrates the new style of assigning initial values to native select
  - that is required by Ivy in version 9
- Related breaking change docs:
  - https://next.angular.io/guide/ivy-compatibility-examples#cannot-bind-to-value-property-of-select-with-ngfor

Fixes #18167
Splaktar added a commit that referenced this issue Jan 20, 2020
… value w/o form

- demonstrates the new style of assigning initial values to native select
  - that is required by Ivy in version 9
- Related breaking change docs:
  - https://next.angular.io/guide/ivy-compatibility-examples#cannot-bind-to-value-property-of-select-with-ngfor

Fixes #18167
jelbourn added a commit that referenced this issue Jan 22, 2020
… value w/o form (#18216)

- demonstrates the new style of assigning initial values to native select
  - that is required by Ivy in version 9
- Related breaking change docs:
  - https://next.angular.io/guide/ivy-compatibility-examples#cannot-bind-to-value-property-of-select-with-ngfor

Fixes #18167
jelbourn added a commit that referenced this issue Jan 22, 2020
… value w/o form (#18216)

- demonstrates the new style of assigning initial values to native select
  - that is required by Ivy in version 9
- Related breaking change docs:
  - https://next.angular.io/guide/ivy-compatibility-examples#cannot-bind-to-value-property-of-select-with-ngfor

Fixes #18167

(cherry picked from commit 0a3b20f)
@Splaktar

This comment has been minimized.

Copy link
Member Author

@Splaktar Splaktar commented Jan 22, 2020

  1. Done
  2. Deferred
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant
You can’t perform that action at this time.