components: bug(material/chip): Mdc Chip Grid empties all options when using Reactive Forms and focusing out
Is this a regression?
- Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
14.2.6
Description
Having Reactive forms attached to mat-chip-grid
which accepts an array of object values, clears them on focus out.
Reproduction
Steps to reproduce:
- Create a formgroup with some formControl
- Bind it to
<mat-chip-grid>
- Add some new options (or the same works if the list is already populated) that are arrays of objects.
- Focus out of the component
Upon further investigation, figured that the core problem is that on focus out, object values are transformed to strings hence why we don’t see the name property. Nevertheless objects were not transformed in v 14.
Note: In the Docs Chip list works as expected because it is not bound to Reactive forms
Expected Behavior
All options remain with previously defined object values
Actual Behavior
All options are transformed to strings thus we have empty text options
Environment
- Angular: 15.0.4
- CDK/Material: 15.0.3
- Browser(s): Chrome 108.0.5359.124
- Operating System: macOS Ventura 13.1
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 12
- Comments: 17
Ok, so I ran into the same issue as OP and luckily it looks like I was able to figure it out.
There’s a mistake in the template in the attached stackblitz example (the one from the starting post - just copying link here for convenience) which causes this issue (see picture below).
[value]
should be bound tooption
instead ofoption.name
. Losing focus causes re-evaluation of the array which boils down to here - which ultimately causes array of objects to turn into an array of strings.So, unless I missed something else, looks like there’s no bug here, just a little misunderstanding.
In my opinion, just defaulting to innerText is not a very good idea, and this thread is a very good example of why, especially the last issue reported by @poveu. I think this is not a bug in the sense that the code behaves as designed and doesn’t just break unexpectedly. The issue here is that the design itself is very confusing and unclear. I think the component should kick and scream at you if you don’t provide a value the way it expects it to be provided. Silent crippling the data without any explanations doesn’t seem acceptable to me.
Yeah… That’s an issue too albeit a different one. Mat components can’t really make any assumptions about the object being bound to the value property, hence they should ask app to provide some info/mappings/whatever it is about those objects, or they should clearly describe what assumptions mat components impose on those objects (like having certain field or something) in order for other functionality - like tag editing - to work correctly. This looks either like a missing functionality or a design flaw.
I suspect you can work around this particular issue by redefining
.toString()
in the tag objects but it feels more like a hack rather than a solution.I think that since
[value]
appears to be from logical perspective, mandatory for<mat-chip-row>
, and since we already have angular 16 in material, we can benefit from required inputs. The solution would be to make@Input({requred: true}) value
in MatChip source code and at least catch some error in console. Also would be great if this information was documented. So I guess there are a couple of action points to be done.That is very true @AlexanderLeonov & @jonastg ! Setting
[value]
param format-chip-row
even fixes the issue I have reported a few posts above.Looks like a breaking change that wasn’t reported in any clear way.
I’ll tell you something, the issue seems much bigger than that, as I have a case where your fix won’t help.
In some part of the application I’m using chips that display their name + description
As I have described previously, the focus out (blur) event causes the selected items array to become an array of strings. However, the bigger issue is that if I’m displaying name + description, then these two values get combined in the array, so the array (ngModel or control’s value) becomes:
['Google Chrome: Fast & Securecom.android.chrome']
Looks like the focus out event takes the innerText of the chip element and uses it as the item’s value, which seems like a huge misconception.