Angular router.navigate 后组件未更新
Angular Components is not updated after router.navigate
我有两个组成部分。 users.components.ts 和 register.components.ts。 users.components.ts 显示 table 用户,register.components.ts 是我们 add/edit 用户。
当我们 add/edit 用户通过 router.navigate() 重定向回 users.components.ts。但是,在刷新页面之前,用户 table 中看不到更改。
这似乎是一个常见问题,但我仍然找不到解决方案。这是我的代码
app-routing.module.ts
import { Routes, RouterModule } from '@angular/router';
import { AuthGuard } from './guards/auth.guard';
import { AdminGuard } from './guards/admin.guard';
import { RegisterComponent } from './components/register/register.component';
import { UsersComponent } from './components/users/users.component';
const routes: Routes = [
{ path: 'users', component: UsersComponent, canActivate: [AdminGuard] },
{ path: 'register', component: RegisterComponent, canActivate: [AdminGuard] },
{ path: 'login', component: LoginComponent },
// otherwise redirect to users
{ path: '**', redirectTo: 'users' }
];
export const AppRouting = RouterModule.forRoot(routes);
users.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { first } from 'rxjs/operators'; // What is this? Look it up
import { MatPaginator, MatTableDataSource,
MatDialog, MatDialogConfig
} from '@angular/material';
import { User } from './../../models/user';
import { UserService } from './../../services/user.service';
import { AlertService } from './../../services/alert.service';
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {
loading = false;
displayedColumns: string[] = [
'id',
'name',
'email',
'contactNumber',
'lastActive',
'edit'
];
users: User[] = [];
dataSource = new MatTableDataSource<User>();
@ViewChild(MatPaginator) paginator: MatPaginator;
constructor(
private router: Router,
private route: ActivatedRoute,
private userService: UserService,
private alertService: AlertService
) {
this.loadUsers();
this.dataSource.paginator = this.paginator;
}
editUser(user: User): void {
this.clear();
window.localStorage.setItem('editUserId', user.id.toString());
this.router.navigate(['register']);
}
addUser(): void {
this.clear();
this.router.navigate(['register']);
}
private async loadUsers() {
this.loading = true;
try {
this.users = await this.userService.get().toPromise();
this.dataSource = new MatTableDataSource<User>(this.users);
} catch (error) {
this.alertService.error(error);
}
this.loading = false;
}
private clear() {
window.localStorage.removeItem('editUserId');
}
}
register.component.ts
import { Component, OnInit } from '@angular/core';
import { first } from 'rxjs/operators';
import { Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { User } from './../../models/user';
import { CheckUsernameEmailRequest } from 'src/app/models/check.username.email.request';
import { UserService } from './../../services/user.service';
import { AlertService } from './../../services/alert.service';
import { ValidationService } from './../../services/validation.service';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss']
})
export class RegisterComponent implements OnInit {
editUserId: string;
userForm: FormGroup;
loading = false;
submitted = false;
constructor(
private formBuilder: FormBuilder,
private router: Router,
private userService: UserService,
private alertService: AlertService,
private validationService: ValidationService
) { }
ngOnInit() {
this.editUserId = window.localStorage.getItem('editUserId');
const checkUsernameEmailRequest: CheckUsernameEmailRequest = <CheckUsernameEmailRequest>({
userId: this.editUserId,
usernameOrEmail: ''
});
this.userForm = this.formBuilder.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
contactNumber: this.validationService.phoneNumberValidators(),
email: this.validationService.emailValidators(checkUsernameEmailRequest),
username: this.validationService.usernameValidators(checkUsernameEmailRequest),
password: ['', Validators.required],
admin: false
});
if (this.editUserId) {
this.loadUser();
}
}
// convenience getter for easy access to form fields
get controls() { return this.userForm.controls; }
getErrorMessage(formControl: FormControl) {
return this.validationService.getErrorMessage(formControl);
}
public onSubmit() {
this.submitted = true;
if (this.userForm.invalid) { return; }
this.loading = true;
const user: User = <User>({
firstName: this.controls.firstName.value,
lastName: this.controls.lastName.value,
contactNumber: this.controls.contactNumber.value,
email: this.controls.email.value,
username: this.controls.username.value,
password: this.controls.password.value,
admin: this.controls.admin.value
});
if (this.editUserId) {
this.edit(user);
} else {
this.register(user);
}
this.router.navigate(['users']);
}
private populateForm(user: any) {
this.controls.firstName.setValue(user.firstName);
this.controls.lastName.setValue(user.lastName);
this.controls.contactNumber.setValue(user.contactNumber);
this.controls.email.setValue(user.email);
this.controls.username.setValue(user.username);
this.controls.password.setValue(user.password);
this.controls.admin.setValue(user.admin);
}
private loadUser() {
this.userService
.getById(+this.editUserId) // + operator is a quick way to convert a string to int
.pipe(first())
.subscribe(data => {
this.populateForm(data);
}, error => {
this.alertService.error(error);
this.loading = false;
});
}
private register(user: User) {
this.userService
.register(user)
.pipe(first())
.subscribe(data => {
this.alertService.handleResponse(data);
}, error => {
this.alertService.error(error);
this.loading = false;
});
}
private edit(user: User) {
user.id = +this.editUserId;
this.userService
.update(user)
.pipe(first())
.subscribe(data => {
this.alertService.handleResponse(data);
}, error => {
this.alertService.error(error);
this.loading = false;
});
window.localStorage.removeItem('editUserId');
}
}
user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from './../models/user';
import { ApiResponse } from './../models/api.response';
import { environment } from 'src/environments/environment';
@Injectable({ providedIn: 'root' })
export class UserService {
apiUrl: string = environment.apiUrl;
constructor(private http: HttpClient) { }
get() {
return this.http.get<User[]>(`${this.apiUrl}/users`);
}
getById(id: number) {
return this.http.get(`${this.apiUrl}/users/${id}`);
}
register(user: User) {
return this.http.post<ApiResponse>(`${this.apiUrl}/users/register`, user);
}
update(user: User) {
return this.http.put<ApiResponse>(`${this.apiUrl}/users/edit`, user);
}
}
您正在同步重定向,在调用 edit/register 方法后,尝试在这些方法的订阅回调中重定向
该行为的原因可能是在您的 UsersComponent 中,您在构造函数中而不是在 ngOnInit() 中调用方法 loadUsers()。
尝试将此方法移至 ngOnInit()。
我有两个组成部分。 users.components.ts 和 register.components.ts。 users.components.ts 显示 table 用户,register.components.ts 是我们 add/edit 用户。
当我们 add/edit 用户通过 router.navigate() 重定向回 users.components.ts。但是,在刷新页面之前,用户 table 中看不到更改。
这似乎是一个常见问题,但我仍然找不到解决方案。这是我的代码
app-routing.module.ts
import { Routes, RouterModule } from '@angular/router';
import { AuthGuard } from './guards/auth.guard';
import { AdminGuard } from './guards/admin.guard';
import { RegisterComponent } from './components/register/register.component';
import { UsersComponent } from './components/users/users.component';
const routes: Routes = [
{ path: 'users', component: UsersComponent, canActivate: [AdminGuard] },
{ path: 'register', component: RegisterComponent, canActivate: [AdminGuard] },
{ path: 'login', component: LoginComponent },
// otherwise redirect to users
{ path: '**', redirectTo: 'users' }
];
export const AppRouting = RouterModule.forRoot(routes);
users.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { first } from 'rxjs/operators'; // What is this? Look it up
import { MatPaginator, MatTableDataSource,
MatDialog, MatDialogConfig
} from '@angular/material';
import { User } from './../../models/user';
import { UserService } from './../../services/user.service';
import { AlertService } from './../../services/alert.service';
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {
loading = false;
displayedColumns: string[] = [
'id',
'name',
'email',
'contactNumber',
'lastActive',
'edit'
];
users: User[] = [];
dataSource = new MatTableDataSource<User>();
@ViewChild(MatPaginator) paginator: MatPaginator;
constructor(
private router: Router,
private route: ActivatedRoute,
private userService: UserService,
private alertService: AlertService
) {
this.loadUsers();
this.dataSource.paginator = this.paginator;
}
editUser(user: User): void {
this.clear();
window.localStorage.setItem('editUserId', user.id.toString());
this.router.navigate(['register']);
}
addUser(): void {
this.clear();
this.router.navigate(['register']);
}
private async loadUsers() {
this.loading = true;
try {
this.users = await this.userService.get().toPromise();
this.dataSource = new MatTableDataSource<User>(this.users);
} catch (error) {
this.alertService.error(error);
}
this.loading = false;
}
private clear() {
window.localStorage.removeItem('editUserId');
}
}
register.component.ts
import { Component, OnInit } from '@angular/core';
import { first } from 'rxjs/operators';
import { Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { User } from './../../models/user';
import { CheckUsernameEmailRequest } from 'src/app/models/check.username.email.request';
import { UserService } from './../../services/user.service';
import { AlertService } from './../../services/alert.service';
import { ValidationService } from './../../services/validation.service';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss']
})
export class RegisterComponent implements OnInit {
editUserId: string;
userForm: FormGroup;
loading = false;
submitted = false;
constructor(
private formBuilder: FormBuilder,
private router: Router,
private userService: UserService,
private alertService: AlertService,
private validationService: ValidationService
) { }
ngOnInit() {
this.editUserId = window.localStorage.getItem('editUserId');
const checkUsernameEmailRequest: CheckUsernameEmailRequest = <CheckUsernameEmailRequest>({
userId: this.editUserId,
usernameOrEmail: ''
});
this.userForm = this.formBuilder.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
contactNumber: this.validationService.phoneNumberValidators(),
email: this.validationService.emailValidators(checkUsernameEmailRequest),
username: this.validationService.usernameValidators(checkUsernameEmailRequest),
password: ['', Validators.required],
admin: false
});
if (this.editUserId) {
this.loadUser();
}
}
// convenience getter for easy access to form fields
get controls() { return this.userForm.controls; }
getErrorMessage(formControl: FormControl) {
return this.validationService.getErrorMessage(formControl);
}
public onSubmit() {
this.submitted = true;
if (this.userForm.invalid) { return; }
this.loading = true;
const user: User = <User>({
firstName: this.controls.firstName.value,
lastName: this.controls.lastName.value,
contactNumber: this.controls.contactNumber.value,
email: this.controls.email.value,
username: this.controls.username.value,
password: this.controls.password.value,
admin: this.controls.admin.value
});
if (this.editUserId) {
this.edit(user);
} else {
this.register(user);
}
this.router.navigate(['users']);
}
private populateForm(user: any) {
this.controls.firstName.setValue(user.firstName);
this.controls.lastName.setValue(user.lastName);
this.controls.contactNumber.setValue(user.contactNumber);
this.controls.email.setValue(user.email);
this.controls.username.setValue(user.username);
this.controls.password.setValue(user.password);
this.controls.admin.setValue(user.admin);
}
private loadUser() {
this.userService
.getById(+this.editUserId) // + operator is a quick way to convert a string to int
.pipe(first())
.subscribe(data => {
this.populateForm(data);
}, error => {
this.alertService.error(error);
this.loading = false;
});
}
private register(user: User) {
this.userService
.register(user)
.pipe(first())
.subscribe(data => {
this.alertService.handleResponse(data);
}, error => {
this.alertService.error(error);
this.loading = false;
});
}
private edit(user: User) {
user.id = +this.editUserId;
this.userService
.update(user)
.pipe(first())
.subscribe(data => {
this.alertService.handleResponse(data);
}, error => {
this.alertService.error(error);
this.loading = false;
});
window.localStorage.removeItem('editUserId');
}
}
user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from './../models/user';
import { ApiResponse } from './../models/api.response';
import { environment } from 'src/environments/environment';
@Injectable({ providedIn: 'root' })
export class UserService {
apiUrl: string = environment.apiUrl;
constructor(private http: HttpClient) { }
get() {
return this.http.get<User[]>(`${this.apiUrl}/users`);
}
getById(id: number) {
return this.http.get(`${this.apiUrl}/users/${id}`);
}
register(user: User) {
return this.http.post<ApiResponse>(`${this.apiUrl}/users/register`, user);
}
update(user: User) {
return this.http.put<ApiResponse>(`${this.apiUrl}/users/edit`, user);
}
}
您正在同步重定向,在调用 edit/register 方法后,尝试在这些方法的订阅回调中重定向
该行为的原因可能是在您的 UsersComponent 中,您在构造函数中而不是在 ngOnInit() 中调用方法 loadUsers()。
尝试将此方法移至 ngOnInit()。