Angular 7 SlickGrid Detail-View: 无法将 EventEmitter 从 Detail-View(child) 组件传递到 SlickGrid (parent) 组件
Angular 7 SlickGrid Detail-View: Can't pass EventEmitter from Detail-View(child) component to SlickGrid (parent) component
我正在使用 Angular SlickGrid 作为 parent 组件和插件 Detail-View 作为 child 组件。在 Detail-View 组件中,我使用几个按钮来完成特定任务。其中之一是按钮删除。问题是单击按钮时,它会触发组件服务通过其 ID 从网格中删除选定的行。 Back-end 完美运行。但!在 front-end 一侧,该行仍然可见,除非我手动重新加载页面。我需要 parent 组件中的那一行在点击时被删除。我尝试使用 EventEmitters,但实际上 SlickGrid 无法识别此功能。如果一切都在一个组件中,我可以轻松使用:this.angularGrid.gridService.deleteItemById(del_id);
但由于 detail-view 数据由 rowDetailView
在 this.gridOptions
中传递,因此没有像 <app-row-detail-view></app-row-detail-view>
这样的组件模板标记
我的 Detail-View 组件 (child):
@Input() del_id: string;
@Output() onDelete = new EventEmitter<string>();
model: {
id: string;
domains: string;
example_site: string;
status: string;
created: string;
image: string;
};
deleteRecipe() {
if (confirm('Are You sure?')) {
console.log("EVENT 1");
this.del_id = this.model.id;
this.onDelete.emit(this.del_id);
console.log(this.del_id);
return this.recipeService.removeRecipe(this.del_id)
.subscribe(u => {
return u;
});
}
}
我的Detail-ViewHTML(child):
<button (click)="deleteRecipe()">DELETE</button>
我的 PARENT 组件 HTML:
<angular-slickgrid
gridId="grid11"
[columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions"
[gridWidth]=1500
[dataset]="dataset"
(onAngularGridCreated)="angularGridReady($event)"
(onDelete)="onDeleted($event)"
>
</angular-slickgrid>
而且我不能在这里使用像 [del_id]="del_id"
这样的东西,因为我在控制台中遇到了很大的错误..
我的Parent组件.ts:
onDeleted(del_id: string) {
console.log("EVENT 2");
console.log(del_id);
this.angularGrid.gridService.deleteItemById(del_id);
}
this.gridOptions = {
enableAsyncPostRender: true,
enableFiltering: true,
enableAutoResize: true,
enableCellNavigation: true,
enableGrouping: false,
enableRowDetailView: true,
enableColumnReorder: false,
rowSelectionOptions: {
selectActiveRow: true
},
rowDetailView: {
process: (item: any) => this.simulateServerAsyncCall(item),
viewComponent: RecipeDetailsComponent,
loadOnce: true,
singleRowExpand: true,
useRowClick: true,
panelRows: this.detailViewRowCount
}
};
simulateServerAsyncCall(item: any) {
return new Promise((resolve) => {
const itemDetail = item;
resolve(itemDetail);
});
}
我已经尝试了很多关于 EventEmitter 的文章,比如:
https://github.com/6pac/SlickGrid/blob/master/plugins/slick.rowdetailview.js#L10,
https://www.infragistics.com/community/blogs/b/infragistics/posts/understanding-output-and-eventemitter-in-angular,
https://github.com/ghiscoding/Angular-Slickgrid/blob/master/src/app/modules/angular-slickgrid/models/rowDetailView.interface.ts.
任何帮助将不胜感激!提前谢谢亲爱的同事们!
请注意,我是 Angular-Slickgrid 的作者。
我同意在以前的版本中执行此操作具有挑战性,因此为了解决这个问题,我添加了对 SlickGrid 的新引用、DataView 引用以及行详细信息扩展的父组件实例,因此您现在可以访问所有这些新引用到您的子组件中。要利用这些新变化,请更新到最新的 Angular-Slickgrid version 2.16.x。
现在有了这些引用,您可以利用它们并将行详细信息子组件更改为以下内容
您可以在更新后的 Row Detail Example and I have also updated the Row Detail Wiki
中看到您的问题(如何从子组件中删除一行)的现场演示
子组件 - 行详细视图
<div class="container-fluid">
<h3>{{model?.title}}</h3>
<button class="btn btn-primary btn-danger btn-sm" (click)="deleteRow(model)" data-test="delete-btn">
Delete Row
</button>
<button class="btn btn-default btn-sm" (click)="callParentMethod(model)" data-test="parent-btn">
Call Parent Method
</button>
</div>
子组件 - 行详细信息组件
import { Component } from '@angular/core';
import { GridRowDetailComponent } from './grid-rowdetail.component';
@Component({
templateUrl: './rowdetail-view.component.html'
})
export class RowDetailViewComponent {
model: {
duration: Date;
percentComplete: number;
reporter: string;
start: Date;
finish: Date;
effortDriven: boolean;
assignee: string;
title: string;
};
// you also have access to the following objects (it must match the exact property names shown below)
addon: any; // row detail addon instance
grid: any;
dataView: any;
// you can also optionally use the Parent Component reference
// NOTE that you MUST provide it through the "parent" property in your "rowDetail" grid options
parent: GridRowDetailComponent;
constructor() { }
alertAssignee(name: string) {
if (typeof name === 'string') {
alert(`Assignee on this task is: ${name.toUpperCase()}`);
} else {
alert('No one is assigned to this task.');
}
}
deleteRow(model) {
if (confirm(`Are you sure that you want to delete ${model.title}?`)) {
// you first need to collapse all rows (via the 3rd party addon instance)
this.addon.collapseAll();
// then you can delete the item from the dataView
this.dataView.deleteItem(model.id);
this.parent.showFlashMessage(`Deleted row with ${model.title}`, 'danger');
}
}
callParentMethod(model) {
this.parent.showFlashMessage(`We just called Parent Method from the Row Detail Child Component on ${model.title}`);
}
}
父组件 - 网格
<div class="container-fluid">
<h2>{{title}}</h2>
<div class="subtitle" [innerHTML]="subTitle"></div>
<div class="alert alert-{{flashAlertType}} col-sm-6" *ngIf="message" data-test="flash-msg">{{message}}</div>
<hr />
<angular-slickgrid gridId="grid21" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
[dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)">
</angular-slickgrid>
</div>
父组件视图
import { Component, OnInit } from '@angular/core';
import {
AngularGridInstance,
Column,
ExtensionName,
FieldType,
Filters,
Formatters,
GridOption
} from './../modules/angular-slickgrid';
import { RowDetailViewComponent } from './rowdetail-view.component';
import { RowDetailPreloadComponent } from './rowdetail-preload.component';
@Component({
templateUrl: './grid-rowdetail.component.html'
})
export class GridRowDetailComponent implements OnInit {
angularGrid: AngularGridInstance;
columnDefinitions: Column[];
gridOptions: GridOption;
dataset: any[];
detailViewRowCount = 9;
message: string;
flashAlertType = 'info';
constructor() { }
angularGridReady(angularGrid: AngularGridInstance) {
this.angularGrid = angularGrid;
}
get rowDetailInstance(): any {
return this.angularGrid && this.angularGrid.extensionService.getSlickgridAddonInstance(ExtensionName.rowDetailView) || {};
}
ngOnInit(): void {
this.defineGrid();
}
/* Define grid Options and Columns */
defineGrid() {
this.columnDefinitions = [ /** ... */ ];
this.gridOptions = {
autoResize: {
containerId: 'demo-container',
sidePadding: 15
},
enableFiltering: true,
enableRowDetailView: true,
rowSelectionOptions: {
selectActiveRow: true
},
rowDetailView: {
// We can load the "process" asynchronously in 2 different ways (httpClient OR even Promise)
process: (item) => this.simulateServerAsyncCall(item),
// process: (item) => this.http.get(`api/item/${item.id}`),
// load only once and reuse the same item detail without calling process method
loadOnce: true,
// limit expanded row to only 1 at a time
singleRowExpand: false,
// false by default, clicking anywhere on the row will open the detail view
// when set to false, only the "+" icon would open the row detail
// if you use editor or cell navigation you would want this flag set to false (default)
useRowClick: true,
// how many grid rows do we want to use for the row detail panel (this is only set once and will be used for all row detail)
// also note that the detail view adds an extra 1 row for padding purposes
// so if you choose 4 panelRows, the display will in fact use 5 rows
panelRows: this.detailViewRowCount,
// you can override the logic for showing (or not) the expand icon
// for example, display the expand icon only on every 2nd row
// expandableOverride: (row: number, dataContext: any, grid: any) => (dataContext.id % 2 === 1),
// Preload View Component
preloadComponent: RowDetailPreloadComponent,
// View Component to load when row detail data is ready
viewComponent: RowDetailViewComponent,
// Optionally pass your Parent Component reference to your Child Component (row detail component)
parent: this
}
};
this.getData();
}
closeAllRowDetail() {
if (this.angularGrid && this.angularGrid.extensionService) {
this.rowDetailInstance.collapseAll();
}
}
showFlashMessage(message: string, alertType = 'info') {
this.message = message;
this.flashAlertType = alertType;
}
}
我正在使用 Angular SlickGrid 作为 parent 组件和插件 Detail-View 作为 child 组件。在 Detail-View 组件中,我使用几个按钮来完成特定任务。其中之一是按钮删除。问题是单击按钮时,它会触发组件服务通过其 ID 从网格中删除选定的行。 Back-end 完美运行。但!在 front-end 一侧,该行仍然可见,除非我手动重新加载页面。我需要 parent 组件中的那一行在点击时被删除。我尝试使用 EventEmitters,但实际上 SlickGrid 无法识别此功能。如果一切都在一个组件中,我可以轻松使用:this.angularGrid.gridService.deleteItemById(del_id);
但由于 detail-view 数据由 rowDetailView
在 this.gridOptions
中传递,因此没有像 <app-row-detail-view></app-row-detail-view>
我的 Detail-View 组件 (child):
@Input() del_id: string;
@Output() onDelete = new EventEmitter<string>();
model: {
id: string;
domains: string;
example_site: string;
status: string;
created: string;
image: string;
};
deleteRecipe() {
if (confirm('Are You sure?')) {
console.log("EVENT 1");
this.del_id = this.model.id;
this.onDelete.emit(this.del_id);
console.log(this.del_id);
return this.recipeService.removeRecipe(this.del_id)
.subscribe(u => {
return u;
});
}
}
我的Detail-ViewHTML(child):
<button (click)="deleteRecipe()">DELETE</button>
我的 PARENT 组件 HTML:
<angular-slickgrid
gridId="grid11"
[columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions"
[gridWidth]=1500
[dataset]="dataset"
(onAngularGridCreated)="angularGridReady($event)"
(onDelete)="onDeleted($event)"
>
</angular-slickgrid>
而且我不能在这里使用像 [del_id]="del_id"
这样的东西,因为我在控制台中遇到了很大的错误..
我的Parent组件.ts:
onDeleted(del_id: string) {
console.log("EVENT 2");
console.log(del_id);
this.angularGrid.gridService.deleteItemById(del_id);
}
this.gridOptions = {
enableAsyncPostRender: true,
enableFiltering: true,
enableAutoResize: true,
enableCellNavigation: true,
enableGrouping: false,
enableRowDetailView: true,
enableColumnReorder: false,
rowSelectionOptions: {
selectActiveRow: true
},
rowDetailView: {
process: (item: any) => this.simulateServerAsyncCall(item),
viewComponent: RecipeDetailsComponent,
loadOnce: true,
singleRowExpand: true,
useRowClick: true,
panelRows: this.detailViewRowCount
}
};
simulateServerAsyncCall(item: any) {
return new Promise((resolve) => {
const itemDetail = item;
resolve(itemDetail);
});
}
我已经尝试了很多关于 EventEmitter 的文章,比如: https://github.com/6pac/SlickGrid/blob/master/plugins/slick.rowdetailview.js#L10, https://www.infragistics.com/community/blogs/b/infragistics/posts/understanding-output-and-eventemitter-in-angular, https://github.com/ghiscoding/Angular-Slickgrid/blob/master/src/app/modules/angular-slickgrid/models/rowDetailView.interface.ts.
任何帮助将不胜感激!提前谢谢亲爱的同事们!
请注意,我是 Angular-Slickgrid 的作者。
我同意在以前的版本中执行此操作具有挑战性,因此为了解决这个问题,我添加了对 SlickGrid 的新引用、DataView 引用以及行详细信息扩展的父组件实例,因此您现在可以访问所有这些新引用到您的子组件中。要利用这些新变化,请更新到最新的 Angular-Slickgrid version 2.16.x。
现在有了这些引用,您可以利用它们并将行详细信息子组件更改为以下内容
您可以在更新后的 Row Detail Example and I have also updated the Row Detail Wiki
中看到您的问题(如何从子组件中删除一行)的现场演示子组件 - 行详细视图
<div class="container-fluid">
<h3>{{model?.title}}</h3>
<button class="btn btn-primary btn-danger btn-sm" (click)="deleteRow(model)" data-test="delete-btn">
Delete Row
</button>
<button class="btn btn-default btn-sm" (click)="callParentMethod(model)" data-test="parent-btn">
Call Parent Method
</button>
</div>
子组件 - 行详细信息组件
import { Component } from '@angular/core';
import { GridRowDetailComponent } from './grid-rowdetail.component';
@Component({
templateUrl: './rowdetail-view.component.html'
})
export class RowDetailViewComponent {
model: {
duration: Date;
percentComplete: number;
reporter: string;
start: Date;
finish: Date;
effortDriven: boolean;
assignee: string;
title: string;
};
// you also have access to the following objects (it must match the exact property names shown below)
addon: any; // row detail addon instance
grid: any;
dataView: any;
// you can also optionally use the Parent Component reference
// NOTE that you MUST provide it through the "parent" property in your "rowDetail" grid options
parent: GridRowDetailComponent;
constructor() { }
alertAssignee(name: string) {
if (typeof name === 'string') {
alert(`Assignee on this task is: ${name.toUpperCase()}`);
} else {
alert('No one is assigned to this task.');
}
}
deleteRow(model) {
if (confirm(`Are you sure that you want to delete ${model.title}?`)) {
// you first need to collapse all rows (via the 3rd party addon instance)
this.addon.collapseAll();
// then you can delete the item from the dataView
this.dataView.deleteItem(model.id);
this.parent.showFlashMessage(`Deleted row with ${model.title}`, 'danger');
}
}
callParentMethod(model) {
this.parent.showFlashMessage(`We just called Parent Method from the Row Detail Child Component on ${model.title}`);
}
}
父组件 - 网格
<div class="container-fluid">
<h2>{{title}}</h2>
<div class="subtitle" [innerHTML]="subTitle"></div>
<div class="alert alert-{{flashAlertType}} col-sm-6" *ngIf="message" data-test="flash-msg">{{message}}</div>
<hr />
<angular-slickgrid gridId="grid21" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
[dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)">
</angular-slickgrid>
</div>
父组件视图
import { Component, OnInit } from '@angular/core';
import {
AngularGridInstance,
Column,
ExtensionName,
FieldType,
Filters,
Formatters,
GridOption
} from './../modules/angular-slickgrid';
import { RowDetailViewComponent } from './rowdetail-view.component';
import { RowDetailPreloadComponent } from './rowdetail-preload.component';
@Component({
templateUrl: './grid-rowdetail.component.html'
})
export class GridRowDetailComponent implements OnInit {
angularGrid: AngularGridInstance;
columnDefinitions: Column[];
gridOptions: GridOption;
dataset: any[];
detailViewRowCount = 9;
message: string;
flashAlertType = 'info';
constructor() { }
angularGridReady(angularGrid: AngularGridInstance) {
this.angularGrid = angularGrid;
}
get rowDetailInstance(): any {
return this.angularGrid && this.angularGrid.extensionService.getSlickgridAddonInstance(ExtensionName.rowDetailView) || {};
}
ngOnInit(): void {
this.defineGrid();
}
/* Define grid Options and Columns */
defineGrid() {
this.columnDefinitions = [ /** ... */ ];
this.gridOptions = {
autoResize: {
containerId: 'demo-container',
sidePadding: 15
},
enableFiltering: true,
enableRowDetailView: true,
rowSelectionOptions: {
selectActiveRow: true
},
rowDetailView: {
// We can load the "process" asynchronously in 2 different ways (httpClient OR even Promise)
process: (item) => this.simulateServerAsyncCall(item),
// process: (item) => this.http.get(`api/item/${item.id}`),
// load only once and reuse the same item detail without calling process method
loadOnce: true,
// limit expanded row to only 1 at a time
singleRowExpand: false,
// false by default, clicking anywhere on the row will open the detail view
// when set to false, only the "+" icon would open the row detail
// if you use editor or cell navigation you would want this flag set to false (default)
useRowClick: true,
// how many grid rows do we want to use for the row detail panel (this is only set once and will be used for all row detail)
// also note that the detail view adds an extra 1 row for padding purposes
// so if you choose 4 panelRows, the display will in fact use 5 rows
panelRows: this.detailViewRowCount,
// you can override the logic for showing (or not) the expand icon
// for example, display the expand icon only on every 2nd row
// expandableOverride: (row: number, dataContext: any, grid: any) => (dataContext.id % 2 === 1),
// Preload View Component
preloadComponent: RowDetailPreloadComponent,
// View Component to load when row detail data is ready
viewComponent: RowDetailViewComponent,
// Optionally pass your Parent Component reference to your Child Component (row detail component)
parent: this
}
};
this.getData();
}
closeAllRowDetail() {
if (this.angularGrid && this.angularGrid.extensionService) {
this.rowDetailInstance.collapseAll();
}
}
showFlashMessage(message: string, alertType = 'info') {
this.message = message;
this.flashAlertType = alertType;
}
}