bes*_*oeu 20 crud angular-material2 angular
经过几周的谷歌搜索和迄今为止只有一个Stackoverflown问题,我终于设法使用Material Table Component构建了我的Angular CRUD应用程序.它显示来自后端(JSON)的数据和CRUD操作我使用的对话框如图所示(这是编辑,对克罗地亚人抱歉).对话可能不是最好的方法,内联编辑可能会更好.但是,为了添加新项目,你需要像对话这样的东西.
我最后一件事就是如何相应地更新表中的字段.因此,当您在对话框中按"保存"时,数据会在后端(在MySQL表中)更新,但不会在前端更新.目前我有一个丑陋的解决方法,每次当你做更新时,它也刷新整个表.
无论如何这里的代码:
表组件:
export class BazaComponent implements OnInit {
....
constructor(public httpClient: HttpClient, public dialog: MatDialog) {
}
ngOnInit() {
this.loadData();
}
// TODO: Simplfy this...
addNew(ident: number, naziv: string, mt: number, kutija: number,
komada: number, jm: string, orginal: number, lokacija: number, napomena: string) {
console.log('add new clicked');
const dialogRef = this.dialog.open(AddDialogComponent, {
data: {ident: ident, naziv: naziv, mt: mt, kutija: kutija,
komada: komada, jm: jm, orginal: orginal, lokacija: lokacija, napomena: napomena }
});
dialogRef.afterClosed().subscribe(result => {
console.log(result);
if (result === 1) {
this.loadData(); // --> This is a temp workaround, every time when I do CRUD operation just redraw whole thing again
}
});
}
startEdit(id: number, ident: number, naziv: string, mt: number, kutija: number,
komada: number, jm: string, orginal: number, lokacija: number, napomena: string) {
const dialogRef = this.dialog.open(EditDialogComponent, {
data: {id: id, ident: ident, naziv: naziv, mt: mt, kutija: kutija,
komada: komada, jm: jm, orginal: orginal, lokacija: lokacija, napomena: napomena}
});
dialogRef.afterClosed().subscribe(result => {
if (result === 1) {
this.loadData(); // --> This is a temp workaround, every time when I do CRUD operation just redraw whole thing again
}
});
}
deleteItem(id: number, ident: number, naziv: string, mt: number) {
const dialogRef = this.dialog.open(DeleteDialogComponent, {
data: {id: id, ident: ident, naziv: naziv, mt: mt}
});
dialogRef.afterClosed().subscribe(result => {
if (result === 1) {
this.loadData();
}
});
}
public loadData() {
this.exampleDatabase = new DataService(this.httpClient);
this.dataSource = new ExampleDataSource(this.exampleDatabase, this.paginator, this.sort);
Observable.fromEvent(this.filter.nativeElement, 'keyup')
.debounceTime(150)
.distinctUntilChanged()
.subscribe(() => {
if (!this.dataSource) {
return;
}
this.dataSource.filter = this.filter.nativeElement.value;
});
}
}
export class ExampleDataSource extends DataSource<Baza> {
_filterChange = new BehaviorSubject('');
get filter(): string {
return this._filterChange.value;
}
set filter(filter: string) {
this._filterChange.next(filter);
}
filteredData: Baza[] = [];
renderedData: Baza[] = [];
constructor(private _exampleDatabase: DataService,
private _paginator: MatPaginator,
private _sort: MatSort) {
super();
// Reset to the first page when the user changes the filter.
this._filterChange.subscribe(() => this._paginator.pageIndex = 0);
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<Baza[]> {
// Listen for any changes in the base data, sorting, filtering, or pagination
const displayDataChanges = [
this._exampleDatabase.dataChange,
this._sort.sortChange,
this._filterChange,
this._paginator.page,
];
this._exampleDatabase.getAllItems();
return Observable.merge(...displayDataChanges).map(() => {
// Filter data
this.filteredData = this._exampleDatabase.data.slice().filter((item: Baza) => {
const searchStr = (item.ident + item.naziv + item.mt + item.lokacija + item.napomena).toLowerCase();
return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
});
// Sort filtered data
const sortedData = this.sortData(this.filteredData.slice());
// Grab the page's slice of the filtered sorted data.
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
this.renderedData = sortedData.splice(startIndex, this._paginator.pageSize);
return this.renderedData;
});
}
disconnect() {
}
/** Returns a sorted copy of the database data. */
sortData(data: Baza[]): Baza[] {
... sort stuff
}
Run Code Online (Sandbox Code Playgroud)
这是DataService,我想我应该进行现场更新:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders} from '@angular/common/http';
import { Baza } from '../models/kanban.baza';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class DataService {
private readonly API_URL = 'http://localhost/api/'
/** Stream that emits whenever the data has been modified. */
dataChange: BehaviorSubject<Baza[]> = new BehaviorSubject<Baza[]>([]);
constructor(private httpClient: HttpClient) {
}
get data(): Baza[] {
return this.dataChange.value;
}
getAllItems(): void {
this.httpClient.get<Baza[]>(this.API_URL).subscribe(data => {
this.dataChange.next(data['items']);
});
}
addItem(baza: Baza): void {
this.httpClient.post(this.API_URL, Baza).subscribe(data => {
//THIS WAS MY BEST TRY BUT IT DOESN'T WORK :(
const copiedData = this.data.slice();
copiedData.push(baza);
console.log(copiedData);
this.dataChange.next(copiedData);
});
}
updateItem(baza: Baza): void {
this.httpClient.put(this.API_URL + baza.id, baza).subscribe();
}
deleteItem(id: number): void {
this.httpClient.delete(this.API_URL + id, {headers: new HttpHeaders().set('Access-Control-Allow-Origin', '*')} ).subscribe();
}
}
Run Code Online (Sandbox Code Playgroud)
更新于27.11.2017:
好的,我终于想出了如何触发新的行添加.我不得不dataChange.value
在表组件内部调用.一旦你用一些数据加载它,新行将立即出现.
const data = {id: 208, ident: 233, naziv: 'test', mt: 291, komada: 2, jm: 'a', orginal: 100, lokacija: 3, napomena: 'pls work'};
this.exampleDatabase.dataChange.value.push(data);
Run Code Online (Sandbox Code Playgroud)
DataService中的相同内容不起作用:
this.dataChange.value.push(data);
Run Code Online (Sandbox Code Playgroud)
Plunker在这里:
https://plnkr.co/edit/IWCVsBRl54F7ylGNIJJ3?p=info
编辑28.11.2017:
现在唯一剩下的就是为添加,编辑和删除构建逻辑.对于添加很容易,它只是`value.push(data)'.感谢大家的帮助.
bes*_*oeu 20
花了我一些时间,但我终于把一切都搞定了.您的答案和不同的方法也有帮助.所以,如果有人遇到麻烦,这是我的CRUD实现:
https://github.com/marinantonio/angular-mat-table-crud
截图:
或者您可以查看项目演示:https: //marinantonio.github.io/angular-mat-table-crud/
关键部分在table.ts文件中:
....
addNew(issue: Issue) {
const dialogRef = this.dialog.open(AddDialogComponent, {
data: {issue: issue }
});
dialogRef.afterClosed().subscribe(result => {
if (result === 1) {
this.exampleDatabase.dataChange.value.push(this.dataService.getDialogData());
this.refreshTable();
}
});
}
startEdit(i: number, id: number, title: string, state: string, url: string, created_at: string, updated_at: string) {
this.index = i;
this.id2 = id;
console.log(this.index);
const dialogRef = this.dialog.open(EditDialogComponent, {
data: {id: id, title: title, state: state, url: url, created_at: created_at, updated_at: updated_at}
});
dialogRef.afterClosed().subscribe(result => {
if (result === 1) {
// Part where we do frontend update, first you need to find record using id
const foundIndex = this.exampleDatabase.dataChange.value.findIndex(x => x.id === this.id2);
// Then you update that record using dialogData
this.exampleDatabase.dataChange.value[foundIndex] = this.dataService.getDialogData();
// And lastly refresh table
this.refreshTable();
}
});
}
deleteItem(i: number, id: number, title: string, state: string, url: string) {
this.index = i;
this.id2 = id;
const dialogRef = this.dialog.open(DeleteDialogComponent, {
data: {id: id, title: title, state: state, url: url}
});
dialogRef.afterClosed().subscribe(result => {
if (result === 1) {
const foundIndex = this.exampleDatabase.dataChange.value.findIndex(x => x.id === this.id2);
this.exampleDatabase.dataChange.value.splice(foundIndex, 1);
this.refreshTable();
}
});
}
private refreshTable() {
// If there's no data in filter we do update using pagination, next page or previous page
if (this.dataSource._filterChange.getValue() === '') {
if (this.dataSource._paginator.pageIndex === 0) {
this.dataSource._paginator.nextPage();
this.dataSource._paginator.previousPage();
} else {
this.dataSource._paginator.previousPage();
this.dataSource._paginator.nextPage();
}
// If there's something in filter, we reset it to 0 and then put back old value
} else {
this.dataSource.filter = '';
this.dataSource.filter = this.filter.nativeElement.value;
}
}
....
Run Code Online (Sandbox Code Playgroud)
正如我从您的代码中看到您正在使用分页,您可以在crud操作后执行以下操作:
this.dataSource.paginator = this.paginator;
Run Code Online (Sandbox Code Playgroud)
这将刷新当前页面.并且,很高兴来自克罗地亚的人正在使用角形材料
这是我的代码中的重要部分:
dialogRef.afterClosed().subscribe(result => {
if (result === null) { return; }
switch (mode) { // add new
case 'C': {
data.push(result.vendor);
this.refreshTable();
break;
}
case 'U': { // update
const index = data.findIndex((item) => item.buFmisVendorId === result.vendor.buFmisVendorId);
if (index > -1) {
data[index] = vendor;
this.refreshTable();
}
break;
}
}
});
private refreshTable() {
this.dataSource.paginator = this.paginator;
}
Run Code Online (Sandbox Code Playgroud)
我有一些解决方法,可以在不使用模式窗口的情况下编辑表中的数据。
您可以看看我的Angular 6和Material的CRUD实现
数据服务
import {Injectable} from '@angular/core';
import {HttpClient, HttpParams, HttpHeaders} from '@angular/common/http';
import {User} from './user';
@Injectable()
export class UserService{
private url = "http://localhost:51120";
constructor(private http: HttpClient){ }
getUsers(){
let getUrl = this.url + "/api/all/";
return this.http.get(getUrl);
}
createUser(user: User){
let saveUrl = this.url + "/api/Users";
return this.http.post(saveUrl, user);
}
updateUser(id: number, user: User) {
const urlParams = new HttpParams().set("id", id.toString());
return this.http.post(this.url + "/api/update", user);
}
deleteUser(id: number){
const urlParams = new HttpParams().set("id", id.toString());
return this.http.delete(this.url + "/api/delete/" + id);
}
}
Run Code Online (Sandbox Code Playgroud)
零件
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [UserService]
})
export class AppComponent implements OnInit {
@ViewChild(MatPaginator) paginator: MatPaginator;
addNewUser: User[] = [
{ Id: 0, Name: null, Age: null, Email: null, Surname: null }
];
users: Array<User>;
showTable: boolean;
statusMessage: string;
isLoaded: boolean = true;
displayedColumnsUsers: string[] = ['Id', 'Name', 'Surname', 'Age', 'Email', 'Change', 'Delete'];
displayedColumnsAddUser: string[] = ['Name', 'Surname', 'Age', 'Email', 'Save', 'Cancel'];
dataSourceUsers: any;
dataSourceAddUser: any;
newUser : User;
constructor(private serv: UserService, public dialog: MatDialog, public snackBar: MatSnackBar) {
this.users = new Array<User>();
}
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
this.loadUsers();
this.dataSourceAddUser = new MatTableDataSource();
}
applyFilter(filterValue: string) {
this.dataSourceUsers.filter = filterValue.trim().toLowerCase();
if (this.dataSourceUsers.paginator) {
this.dataSourceUsers.paginator.firstPage();
}
}
private loadUsers() {
this.isLoaded = true;
this.serv.getUsers().subscribe((data: User[]) => {
this.users = data;
this.users.sort(function (obj1, obj2) {
// Descending: first id less than the previous
return obj2.Id - obj1.Id;
});
this.isLoaded = false;
this.dataSourceUsers = new MatTableDataSource(this.users);
this.dataSourceAddUser = new MatTableDataSource(this.addNewUser);
this.dataSourceUsers.sort = this.sort;
this.dataSourceUsers.paginator = this.paginator;
},
error => {
alert("Error: " + error.name);
this.isLoaded = false;
}
);
}
deleteUserForDialog(user: User) {
this.serv.deleteUser(user.Id).subscribe(data => {
this.statusMessage = 'User ' + user.Name + ' is deleted',
this.openSnackBar(this.statusMessage, "Success");
this.loadUsers();
})
}
editUser(user: User) {
this.serv.updateUser(user.Id, user).subscribe(data => {
this.statusMessage = 'User ' + user.Name + ' is updated',
this.openSnackBar(this.statusMessage, "Success");
this.loadUsers();
},
error => {
this.openSnackBar(error.statusText, "Error");
}
);
}
saveUser(user: User) {
if (user.Age != null && user.Name != null && user.Name != "" && user.Age != 0) {
this.serv.createUser(user).subscribe(data => {
this.statusMessage = 'User ' + user.Name + ' is added',
this.showTable = false;
this.openSnackBar(this.statusMessage, "Success");
this.loadUsers();
},
error => {
this.showTable = false;
this.openSnackBar(error.statusText, "Error");
}
);
}
else {
this.openSnackBar("Please enter correct data", "Error")
}
}
show() {
this.showTable = true;
this.addNewUser = [{ Id: 0, Name: null, Age: null, Email: null, Surname: null }];
}
cancel() {
this.showTable = false;
}
//snackBar
openSnackBar(message: string, action: string) {
this.snackBar.open(message, action, {
duration: 3000,
});
}
//material dialog
openDialog(element): void {
const dialogRef = this.dialog.open(DialogOverviewExampleDialogComponent,
{
width: '250px',
data: element,
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
if (result == "Confirm") {
this.deleteUserForDialog(element);
}
});
}
// Form field with error messages
name = new FormControl('', [Validators.required]);
getErrorMessage() {
return this.name.hasError('required') ? 'You must enter a value' :
this.name.hasError('name') ? 'Not a valid name' : '';
}
age = new FormControl('', [Validators.required]);
email = new FormControl('', [Validators.required, Validators.email]);
surnameFormControl= new FormControl('', [Validators.required]);
emailGetErrorMessage() {
return this.email.hasError('required') ? 'You must enter a value' :
this.email.hasError('email') ? 'Not a valid email' :
'';
}
onSubmit(newUser:User){
this.newUser = new User(0,"",0,"","");
}
}
Run Code Online (Sandbox Code Playgroud)
https://github.com/AleksandrChuikov/Angular6MaterialCRUD
这是演示的链接:https : //crud-angular6.azurewebsites.net
更新到Angular 8
该解决方案使用我现有的删除代码,但更新代码相同。关键问题是找到已编辑或删除的项目的数组索引。请注意,一旦结果成功,我就会调用成功模式来通知用户,然后调用函数从数据表中删除该行。或者,您可以使用一些不同的代码更新该行中的数据,例如将数据推送到对象数组中。这样我们就不必再次下载所有数据。
public deleteMember(memberId) {
// Call the confirm dialog component
this.confirmService.confirm('Confirm Delete', 'This action is final. Gone forever!')
.switchMap(res => {if (res === true) {
return this.appService.deleteItem(this.dbTable, memberId);
}})
.subscribe(
result => {
this.success();
// Refresh DataTable to remove row.
this.updateDataTable (memberId);
},
(err: HttpErrorResponse) => {
console.log(err.error);
console.log(err.message);
this.messagesService.openDialog('Error', 'Delete did not happen.');
}
);
}
Run Code Online (Sandbox Code Playgroud)
现在让我们删除或更新已删除或编辑的行。
private dsData: any;
// Remove the deleted row from the data table. Need to remove from the downloaded data first.
private updateDataTable (itemId) {
this.dsData = this.dataSource.data;
if (this.dsData.length > 0) {
for (let i = 0; i < this.dsData.length; i++ ) {
if (this.dsData[i].member_id === itemId) {
this.dataSource.data.splice(i, 1);
}
}
}
this.dataSource.paginator = this.paginator;
}
Run Code Online (Sandbox Code Playgroud)
实际上,如果您有以下 HTML,则编辑后您无需刷新表格:
<mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="userName">
<mat-header-cell mat-sort-header> UserName </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.userName}} </mat-cell>
</ng-container>
<ng-container matColumnDef="actions">
<mat-cell *matCellDef="let user">
<button mat-icon-button matTooltip="Edit" (click)="editUser(user)">
<mat-icon>edit</mat-icon>
</button>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;">
</mat-row>
</mat-table>
Run Code Online (Sandbox Code Playgroud)
而且,在 .ts 你有:
private editUser(user?: User) {
let userTest: User = user;
userTest.userName = "user123";
}
Run Code Online (Sandbox Code Playgroud)
您可以在按下编辑用户名更改时自动看到该行(在本例中为“user123”)
归档时间: |
|
查看次数: |
32735 次 |
最近记录: |