Reputation: 483
I have this code in my constructor
public constructor() {
this.dropdown = signal([
{
name: 'Normal Text',
tag: 'p',
selected: true
},
{
name: 'Heading 1',
tag: 'h1',
selected: false,
},
{
name: 'Heading 2',
tag: 'h2',
selected: false
},
{
name: 'Heading 3',
tag: 'h3',
selected: false
},
{
name: 'Heading 4',
tag: 'h4',
selected: false
},
{
name: 'Heading 5',
tag: 'h5',
selected: false
},
{
name: 'Heading 6',
tag: 'h6',
selected: false
}
]);
this.selectedTextType = computed(() => this.dropdown().find(x => x.selected) as DropdownOption);
}
and when an option is clicked from the dropdown this code is executed
public textTypeChange(option: DropdownOption, e: Event): void {
e.preventDefault();
this.selectedTextType().selected = false;
option.selected = true;
}
The selectedTextType
signal does not get recomputed. The dropdown option does not change in the html. What am I doing wrong?
Upvotes: 0
Views: 89
Reputation: 17758
By default, Angular signals use referential equality to track whether the value has changed. If you are storing objects or arrays in your Signal, this means that the value is treated as unchanged as long as the reference is the same. If you are updating an object inside your array, the reference remains unchanged. Angular thinks that the value is not changed and thus the template doesn't update, which is by design.
To fix it, I strongly recommend to separate the data from the selection state. For example, you can simply store the tag
of the selected value in a separate signal:
this.dropdown = signal([
{
name: "Normal Text",
tag: "p",
},
{
name: "Heading 1",
tag: "h1",
},
// ...
]);
this.selectedTextType = signal('p');
Another approach would be to install @angular/cdk
in your project and use their SelectionModel
. The code should look somewhat like the following:
this.dropdown = signal([
{
name: "Normal Text",
tag: "p",
},
{
name: "Heading 1",
tag: "h1",
},
// ...
]);
this.selectionModel = new SelectionModel(false, ['p']);
Upvotes: 1