NGXS
NGXS
If you have not previously installed Angular CLI globally on your machine, then install it using
the following command.
# or
ng new ng6xs
Step 2: Install NGXS Store.
Next, we’ll install ngxs store.
// app.module.ts
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
NgxsModule.forRoot(),
NgxsReduxDevtoolsPluginModule.forRoot(),
NgxsLoggerPluginModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
ng serve -o
You can see the logs, so when the state changes, we can its old and new values.
Now, we will create and display the user information like name and email. We do not make a
backend to store the user information. We need to add the data to the store and display data on the
Angular Frontend.
We will create two components, so type the following command to generate the Angular
components.
ng g c components/create --spec=false
ng g c components/index --spec=false
Now, add the following code inside src >> styles.css file.
@import "~bootstrap/dist/css/bootstrap.min.css"
Inside src >> app >> components >> create folder, we need to add some HTML code
inside create.component.html file.
<div class="card">
<div class="card-body">
<form>
<div class="form-group">
<label class="col-md-4">Name</label>
<input type="text" class="form-control" #name/>
</div>
<div class="form-group">
<label class="col-md-4">Email</label>
<input type="email" class="form-control" #email/>
</div>
<div class="form-group">
<button (click)="addUser(name.value, email.value)" class="btn btn-primary">
Create User</button>
</div>
</form>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-6">
<app-create></app-create>
</div>
<div class="col-md-6"></div>
</div>
</div>
Save the file and go to the: http://localhost:4200/. You can see something like below.
Okay, now we need the ReactiveFormsModule. We will use the Reactive approach to the form
and not template-driven approach. So Inside app.module.ts file, add
the ReactiveFormsModule from @angular/forms package.
// app.module.ts
import { ReactiveFormsModule } from '@angular/forms';
imports: [
BrowserModule,
NgxsModule.forRoot(),
NgxsReduxDevtoolsPluginModule.forRoot(),
NgxsLoggerPluginModule.forRoot(),
ReactiveFormsModule
],
// create.component.ts
@Component({
selector: 'app-create',
templateUrl: './create.component.html',
styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {
angForm: FormGroup;
createForm() {
this.angForm = this.fb.group({
name: ['', Validators.required ],
email: ['', Validators.required ]
});
}
addUser(name, email) {
console.log(name, email);
}
ngOnInit() {
}
<div class="card">
<div class="card-body">
<form [formGroup]="angForm">
<div class="form-group">
<label class="col-md-4">Name</label>
<input type="text" class="form-control" formControlName="name" #name/>
<div *ngIf="angForm.controls['name'].invalid && (angForm.controls['name'].dir
ty || angForm.controls['name'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['name'].errors.required">
Name is required.
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-4">Email</label>
<input type="email" class="form-control" formControlName="email" #email/>
<div *ngIf="angForm.controls['email'].invalid && (angForm.controls['email'].d
irty || angForm.controls['email'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['email'].errors.required">
Email is required.
</div>
</div>
</div>
<div class="form-group">
<button (click)="addUser(name.value, email.value)"
class="btn btn-primary"
[disabled]="angForm.pristine || angForm.invalid">Create User</button>
</div>
</form>
</div>
</div>
// User.ts
// user.action.ts
Inside src >> app folder, create one folder called state and in that folder, create one file
called user.state.ts.
// user.action.ts
@State<UserStateModel>({
name: 'users',
defaults: {
users: []
}
})
export class UserState {
@Selector()
static getUsers(state: UserStateModel) {
return state.users;
}
@Action(AddUser)
add({getState, patchState }: StateContext<UserStateModel>, { payload }: AddUser)
{
const state = getState();
patchState({
users: [...state.users, payload]
});
}
}
Here, we have defined the action to save the user data into the store. When the user tries to create
the new user, we get those payload values here and add into the user’s state array. So, when the
user is created, the store will update its user state and that state is fetched by another component.
In our case it is index.component.ts. So it will change its UI and display the newly created user.
// create.component.ts
@Component({
selector: 'app-create',
templateUrl: './create.component.html',
styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {
angForm: FormGroup;
createForm() {
this.angForm = this.fb.group({
name: ['', Validators.required ],
email: ['', Validators.required ]
});
}
addUser(name, email) {
this.store.dispatch(new AddUser({ name, email}));
}
ngOnInit() {
}
imports: [
BrowserModule,
NgxsModule.forRoot([
UserState
]),
NgxsReduxDevtoolsPluginModule.forRoot(),
NgxsLoggerPluginModule.forRoot(),
ReactiveFormsModule
],
// index.component.ts
@Component({
selector: 'app-index',
templateUrl: './index.component.html',
styleUrls: ['./index.component.css']
})
export class IndexComponent implements OnInit {
users: Observable<User>;
ngOnInit() {
}
Here, if the user’s state array is changed then this component rerenders and display the changes.
For example, if the new user is added then this component rerenders and display the new user.
<div class="container">
<div class="row">
<div class="col-md-6">
<app-create></app-create>
</div>
<div class="col-md-6">
<app-index></app-index>
</div>
</div>
</div>
Save the file and go to the browser. You can see below.