Updating users

There are two things we need to do to support updating users:

  • Add a component that supports updating
  • Adding a CASE to our reducer that listens to an action and calls the appropriate adapter method

Let's start with our component:

// edit-user.component.ts

import {
Component,
OnInit,
Output,
Input,
EventEmitter
}
from "@angular/core";

@Component({
selector: "edit-user",
template: `
<div>
<input [(ngModel)]="user.name" />
<button (click)="save.emit(user)" >Save</button>
</div>
`
})
export class EditUserComponent implements OnInit {
private _user;

@Input()
get user() {
return this._user;
}


set user(val) {
this._user = Object.assign({}, val);
}


@Output() save = new EventEmitter();

constructor() {}
ngOnInit() {}
}

Here, we have a component that takes a user as input and is able to invoke a save as output thereby calling the parent component. In short, this component allows us to edit a user.

Now we need to add this component to app.module.ts so that other components within this module can use it:

// excerpt from app.module.ts

@NgModule({
declarations: [AppComponent, EditUserComponent],
imports: [
BrowserModule,
FormsModule,
StoreModule.forRoot({
users: userReducer
})],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}

Now we are ready to add the component to the parent components template, like so:

// app.component.ts - adding EditUserComponent to the markup

import { Component } from "@angular/core";
import { AppState } from "./app-state";
import { Store } from "@ngrx/store";
import { map } from "rxjs/operators";

@Component({
selector: "app-root",
template: `
<div style="border: solid 1px black; padding: 10px;"
*ngFor="let user of users$ | async">
{{ user.name }}
<edit-user [user]="user" (save)="update($event)" ></edit-user>
</div>
<div>
<input [(ngModel)]="user" /> <button (click)="add()">Add</button>
</div>
`
})
export class AppComponent {
title = "app";
users$;
user;
id = 1;

constructor(private store: Store<AppState>) {
this.users$ = this.store
.select(state => state.users.entities)
.pipe(map(this.toArray));
this.users$.subscribe(data => console.log("users", data));
}

toArray(obj) {
const keys = Object.keys(obj);
return keys.map(key => obj[key]);
}

add() {
const newUser = { id: this.id++, name: this.user };
this.store.dispatch({
type: "ADD_USER",
payload: newUser
});
}

update(user) {
console.log("updating", user);
this.store.dispatch({ type: "UPDATE_USER", payload: user });
}

}

This code shows us how we add the EditUserComponent to the markup, as well as us adding the update() method that, when invoked, dispatches the action UPDATE_USER. This will lead to our reducer being invoked which leads us to our final piece of the puzzle, the required changes we need to make to the reducer:

// excerpt from app.module.ts

function userReducer(state = initial, action: ActionPayload<User>): State {
switch (action.type) {
case "ADD_USER":
return userAdapter.addOne(action.payload, state);
case "UPDATE_USER":
return userAdapter.updateOne({

id: action.payload.id,
changes: action.payload
},
state
);
default:
return state;
}
}

We now support the ability to update our users list.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset