我希望每当appUsers: AppUser[]
中所有AppUserService
的全局数组更新时,Angular Material Table都会动态更新。
我知道,如果表是用*ngFor
构造的,那么我所知道的解决方案就可以正常工作。但是,它与Angular Material Table的工作方式有所不同。
Angular Material的official documentation说:
向表提供数据的另一种方法是传递一个Observable流,该流在每次更改时都会发出要呈现的数据数组。该表将侦听此流,并在每次发出新的数据数组时自动触发对行的更新。
这是我想追求的,但是我找不到真正的例子。
AdminComponent
保留了我表的数据源。
export class AdminComponent implements OnInit, OnDestroy {
dataSource = new MatTableDataSource<AppUser>();
private getAppUsersSubscription: Subscription;
columnsToDisplay = ['userName', 'lastLogin', 'changePassword', 'deleteCustomer'];
constructor(
private appUserService: AppUserService,
private newCustomerDialog: MatDialog) { }
ngOnInit() {
this.getAppUsersSubscription = this.appUserService.getAppUsers().subscribe(
(response: AppUser[]) => {
this.dataSource.data = response;
},
error => {
console.log(error);
}
);
}
newAppUser() {
const dialogConfig = new MatDialogConfig();
dialogConfig.autoFocus = true;
dialogConfig.disableClose = true;
this.newCustomerDialog.open(NewAppUserComponent, dialogConfig);
}
ngOnDestroy() {
this.getAppUsersSubscription.unsubscribe();
}
}
admin.component.html
这是视图。
<div class="container-fluid">
<div class="row">
<div class="col-12 col-sm-12 col-md-6 col-lg-6 new">
<button class="btn btn-primary new-button" (click)="newAppUser()">New Customer</button>
</div>
<div class="col-12 col-sm-12 col-md-6 col-lg-6 new">
<button class="btn btn-primary new-button">New Setting</button>
</div>
</div>
<mat-tab-group mat-stretch-tabs [dynamicHeight]="true">
<mat-tab label="Customers">
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="userName">
<th mat-header-cell *matHeaderCellDef> Customer </th>
<td mat-cell *matCellDef="let appUser"> {{ appUser.userName }} </td>
</ng-container>
<ng-container matColumnDef="lastLogin">
<th mat-header-cell *matHeaderCellDef> Last Login </th>
<td mat-cell *matCellDef="let appUser"> {{ appUser.lastLogin | date: 'yyyy-MM-dd HH:mm' }} </td>
</ng-container>
<ng-container matColumnDef="changePassword">
<th class="text-center" mat-header-cell *matHeaderCellDef> Change Password </th>
<td class="clickable" mat-cell *matCellDef="let appUser"><i class="fas fa-key"></i></td>
</ng-container>
<ng-container matColumnDef="deleteCustomer">
<th class="text-center" mat-header-cell *matHeaderCellDef> Delete Customer </th>
<td class="clickable" mat-cell *matCellDef="let appUser"><i class="fas fa-trash"></i></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let myRowData; columns: columnsToDisplay"></tr>
</table>
</mat-tab>
<mat-tab label="Settings">
</mat-tab>
</mat-tab-group>
</div>
NewAppUserComponent
是对话框窗口组件,在其中创建新的AppUser
export class NewAppUserComponent implements OnInit {
newAppUserForm: FormGroup;
submitted = false;
appUser: AppUser;
constructor(
public dialogRef: MatDialogRef<NewAppUserComponent>,
private formBuilder: FormBuilder,
private appUserService: AppUserService
) {
this.appUser = new AppUser();
}
ngOnInit() {
this.newAppUserForm = this.formBuilder.group({
userName: ['', Validators.required],
password: ['', [Validators.required, Validators.minLength(6)]],
confirmPassword: ['', Validators.required]
});
}
get f() {
return this.newAppUserForm.controls;
}
onSubmit() {
this.submitted = true;
this.appUser.userName = this.f.userName.value;
this.appUser.password = this.f.password.value;
this.appUserService.postAppUser(this.appUser)
.pipe(first())
.subscribe(
data => {
this.dialogRef.close();
},
error => {
console.log(error);
}
)
}
onCancel() {
this.dialogRef.close();
}
}
AppUserService
将AppUser
发布到API并在一切顺利的情况下收到副本。我将新创建的AppUser
推送到appUsers: AppUser[]
的全局数组中。我希望此更改反映在AdminComponent
中的表中。
export class AppUserService {
public appUsers: AppUser[];
private appUsersSubject: BehaviorSubject<AppUser[]>;
public appUsersObservable: Observable<AppUser[]>;
constructor(private repository: RepositoryService) {
this.appUsers = new Array<AppUser>();
this.appUsersSubject = new BehaviorSubject<AppUser[]>(null);
this.appUsersObservable = this.appUsersSubject.asObservable();
}
getAppUsers(): Observable<AppUser[]> {
let api: string = "api/appuser";
return this.repository.get(api).pipe(
map(response => {
this.appUsers = Object.assign(this.appUsers, response);
this.appUsersSubject.next(this.appUsers);
return this.appUsers;
})
);
}
postAppUser(appUser: AppUser): Observable<AppUser> {
let api: string = "api/appuser";
return this.repository.post(api, appUser).pipe(
map(response => {
let appUser = new AppUser();
appUser = Object.assign(appUser, response);
// Add new AppUser to AppUsers array
this.appUsers.push(appUser);
return appUser;
})
)
}
}
答案 0 :(得分:0)
尝试以下代码将dataSource.data数组重置为空数组,然后将响应数组附加到该数组以触发更改检测。
ngOnInit() {
this.getAppUsersSubscription = this.appUserService.getAppUsers().subscribe(
(response: AppUser[]) => {
this.dataSource.data = [];
this.dataSource.data.push(...response);
},
error => {
console.log(error);
}
);
}
答案 1 :(得分:0)
通过添加以下内容解决了问题。
admin.component.html
在这里我添加了对MatTable的引用,名为#appUserTable
,并将该引用传递给了(click)="newAppUser(appUserTable)
<table mat-table #appUserTable [dataSource]="dataSource">
</table>
...
<button class="btn btn-primary new-button" (click)="newAppUser(appUserTable)">New Customer</button>
admin.component.ts
在这里,我获取引用并将其传递给new-appuser.component.ts
newAppUser(appUserTable: MatTable<AppUser>) {
const dialogConfig = new MatDialogConfig();
dialogConfig.autoFocus = true;
dialogConfig.disableClose = true;
dialogConfig.data = { appUserTable }
this.newCustomerDialog.open(NewAppUserComponent, dialogConfig);
}
new-appuser.component.ts
现在,对话框中有引用。当我收到来自API调用的成功响应时,我运行this.appUserTable.renderRows();
appUserTable: MatTable<AppUser>;
constructor(
@Inject(MAT_DIALOG_DATA) public data,
) {
this.appUserTable = data.appUserTable;
}
...
this.appUserService.postAppUser(this.appUser)
.pipe(first())
.subscribe(
data => {
this.dialogRef.close();
this.appUserTable.renderRows();
},
error => {
console.log(error);
}
)