I'm trying to get this component working that will take an object of key/value pairs, display them in input tags, and change them on the original object. So say I have an object like:
{
name: "John",
id: "12345",
preferences: { foo: "bar", biz: "baz" }
}
I can call <key-value [obj]="profile.preferences"></key-value>
and the data will be printed in two pairs in input tags. If I then changed "foo" to "qux" the property key would change. To accomplish this I have a key-value component that really simply does:
<div *ngFor="let pref of obj | keyvalue">
<input [(ngModel)]="pref.key"><br />
<input [(ngModel)]="pref.value"><br />
</div>
Which I feel is very simple. It's an object passed in, so it's a reference to the original object, and the ngModels in literally every other input of my application work so I assume that's not wrong.
I've done a lot of looking around and I did actually get it working if I had a "changeKey/changeValue" function that would change this.obj in the component rather than relying on binding:
<div *ngFor="let pref of obj | keyvalue">
<input (change)="changeKey(/*???*/)" [ngModel]="pref.key"><br />
<input (change)="changeValue(pref.key, pref.value) [ngModel]="pref.value"><br />
</div>
That works for the changeValue because I have the key I need to change and the new value. But the issue with the changeKey is because pref.key has been changed I don't know which key to update.
I feel like this shouldn't be that difficult, I'm still quite new to Angular and I'm hoping someone here knows what's going on. Thanks.
KeyValuePipe in a nutshell:
Transforms Object or Map into an array of key value pairs.
The keyvalue
pipe creates a new array from a given object, and as such, binding to it will not affect the original object.
As for your issue, instead of using the (change)
event listener, you can bind ngModel
to your original object and point to it directly:
<div *ngFor="let prop of myObject | keyvalue">
<input [(ngModel)]="myObject[prop.key]">
</div>
You can define the changeKey
function like the following code.
In Component
changeKey(prevKey, newKey) {
const value = this.obj[prevKey];
delete this.obj[prevKey];
this.obj[newKey] = value;
}
In HTML
<input (change)="changeKey(pref.key, $event.target.value)" [ngModel]="pref.key"><br />
I created a working example on stackblitz.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With