Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 8 ngFor's keyvalue pipe and ngModels. Having issues binding values

Tags:

angular

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.

like image 461
Thomas Riley Avatar asked Jun 25 '19 03:06

Thomas Riley


2 Answers

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>
like image 136
Shaya Avatar answered Nov 12 '22 04:11

Shaya


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.

like image 37
Samuel Avatar answered Nov 12 '22 03:11

Samuel