mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-2859] conditional evaluation of disabled state for content actions (#3450)
* react on [disabled] binding changes * [disabled] binding updates for context menu items * evaluating disabled state with a function * unit test * restore original description * remove irrelevant test * fix tests
This commit is contained in:
committed by
Eugenio Romano
parent
08fd49c4e3
commit
cb88a22a76
@@ -279,6 +279,12 @@
|
|||||||
</data-columns>
|
</data-columns>
|
||||||
|
|
||||||
<content-actions>
|
<content-actions>
|
||||||
|
<content-action
|
||||||
|
target="all"
|
||||||
|
title="Action for 'custom' node"
|
||||||
|
[disabled]="isCustomActionDisabled"
|
||||||
|
(execute)="runCustomAction($event)">
|
||||||
|
</content-action>
|
||||||
<!-- Conditional actions demo -->
|
<!-- Conditional actions demo -->
|
||||||
<content-action
|
<content-action
|
||||||
icon="get_app"
|
icon="get_app"
|
||||||
|
@@ -542,4 +542,15 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isCustomActionDisabled = (node: MinimalNodeEntity): boolean => {
|
||||||
|
if (node && node.entry && node.entry.name === 'custom') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
runCustomAction(event) {
|
||||||
|
console.log(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -87,11 +87,11 @@ export class MyView {
|
|||||||
| Name | Type | Default value | Description |
|
| Name | Type | Default value | Description |
|
||||||
| -- | -- | -- | -- |
|
| -- | -- | -- | -- |
|
||||||
| disableWithNoPermission | `boolean` | | Should this action be disabled in the menu if the user doesn't have permission for it? |
|
| disableWithNoPermission | `boolean` | | Should this action be disabled in the menu if the user doesn't have permission for it? |
|
||||||
| disabled | `boolean` | false | Is the menu item disabled? |
|
| disabled | `boolean \|Function` | false | Is the menu item disabled? |
|
||||||
| handler | `string` | | System actions. Can be "delete", "download", "copy" or "move". |
|
| handler | `string` | | System actions. Can be "delete", "download", "copy" or "move". |
|
||||||
| icon | `string` | | The name of the icon to display next to the menu command (can be left blank). |
|
| icon | `string` | | The name of the icon to display next to the menu command (can be left blank). |
|
||||||
| permission | `string` | | The permission type. |
|
| permission | `string` | | The permission type. |
|
||||||
| target | `string` | [`ContentActionTarget`](../../lib/content-services/document-list/models/content-action.model.ts).All | Type of item that the action appies to. Can be "document" or "folder" |
|
| target | `string` | [`ContentActionTarget`](../../lib/content-services/document-list/models/content-action.model.ts).All | Type of item that the action applies to. Can be "document" or "folder" |
|
||||||
| title | `string` | "Action" | The title of the action as shown in the menu. |
|
| title | `string` | "Action" | The title of the action as shown in the menu. |
|
||||||
| visible | `boolean \| Function` | true | Visibility state (see examples). |
|
| visible | `boolean \| Function` | true | Visibility state (see examples). |
|
||||||
|
|
||||||
@@ -393,7 +393,85 @@ Please note that if you want to preserve `this` context within the evaluator fun
|
|||||||
its property should be declared as a lambda one:
|
its property should be declared as a lambda one:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
functionName = (parameters): boolean => {
|
funcName = (parameters): boolean => {
|
||||||
|
// implementation
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conditional disabled state
|
||||||
|
|
||||||
|
Similar to `visible` property, it is possible to control the `disabled` state with the following scenarios:
|
||||||
|
|
||||||
|
- direct value of `boolean` type
|
||||||
|
- binding to a property of the `boolean` type
|
||||||
|
- binding to a property of the `Function` type that evaluates condition and returns `boolean` value
|
||||||
|
|
||||||
|
#### Using direct value of boolean type
|
||||||
|
|
||||||
|
```html
|
||||||
|
<content-action
|
||||||
|
target="all"
|
||||||
|
title="Action for 'custom' node"
|
||||||
|
[disabled]="true"
|
||||||
|
(execute)="runCustomAction($event)">
|
||||||
|
</content-action>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using a property of the boolean type
|
||||||
|
|
||||||
|
```html
|
||||||
|
<content-action
|
||||||
|
target="all"
|
||||||
|
title="Action for 'custom' node"
|
||||||
|
[disabled]="shouldDisableAction"
|
||||||
|
(execute)="runCustomAction($event)">
|
||||||
|
</content-action>
|
||||||
|
```
|
||||||
|
|
||||||
|
The markup above relies on the `shouldDisableAction` property declared at your component class level:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export class MyComponent {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
shouldDisableAction = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using a property of the Function type
|
||||||
|
|
||||||
|
```html
|
||||||
|
<content-action
|
||||||
|
target="all"
|
||||||
|
title="Action for 'custom' node"
|
||||||
|
[disabled]="isCustomActionDisabled"
|
||||||
|
(execute)="runCustomAction($event)">
|
||||||
|
</content-action>
|
||||||
|
```
|
||||||
|
|
||||||
|
The code above relies on the `isCustomActionDisabled` property of a `Function` type declared at your component class level:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export class MyComponent {
|
||||||
|
|
||||||
|
isCustomActionDisabled = (node: MinimalNodeEntity): boolean => {
|
||||||
|
if (node && node.entry && node.entry.name === 'custom') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Code above checks the node name, and evaluates to `true` only if corresponding node is called "custom".
|
||||||
|
|
||||||
|
Please note that if you want to preserve `this` context within the evaluator function,
|
||||||
|
its property should be declared as a lambda one:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
funcName = (parameters): boolean => {
|
||||||
// implementation
|
// implementation
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -66,7 +66,7 @@ export class ContentActionComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
/** Is the menu item disabled? */
|
/** Is the menu item disabled? */
|
||||||
@Input()
|
@Input()
|
||||||
disabled: boolean = false;
|
disabled: boolean | Function = false;
|
||||||
|
|
||||||
/** Emitted when the user selects the action from the menu. */
|
/** Emitted when the user selects the action from the menu. */
|
||||||
@Output()
|
@Output()
|
||||||
@@ -117,6 +117,15 @@ export class ContentActionComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.folderActionModel.visible = changes.visible.currentValue;
|
this.folderActionModel.visible = changes.visible.currentValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changes.disabled && !changes.disabled.firstChange) {
|
||||||
|
if (this.documentActionModel) {
|
||||||
|
this.documentActionModel.disabled = changes.disabled.currentValue;
|
||||||
|
}
|
||||||
|
if (this.folderActionModel) {
|
||||||
|
this.folderActionModel.disabled = changes.disabled.currentValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@@ -359,6 +359,28 @@ describe('DocumentList', () => {
|
|||||||
expect(actions[0].title).toBe('Action1');
|
expect(actions[0].title).toBe('Action1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should evaluate conditional disabled state for content action', () => {
|
||||||
|
documentList.actions = [
|
||||||
|
new ContentActionModel({
|
||||||
|
target: 'document',
|
||||||
|
title: 'Action1',
|
||||||
|
disabled: (): boolean => true
|
||||||
|
}),
|
||||||
|
new ContentActionModel({
|
||||||
|
target: 'document',
|
||||||
|
title: 'Action2',
|
||||||
|
disabled: (): boolean => false
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
const nodeFile = { entry: { isFile: true, name: 'xyz' } };
|
||||||
|
const actions = documentList.getNodeActions(nodeFile);
|
||||||
|
|
||||||
|
expect(actions.length).toBe(2);
|
||||||
|
expect(actions[0].disabled).toBeTruthy();
|
||||||
|
expect(actions[1].disabled).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
it('should not disable the action if there is copy permission', () => {
|
it('should not disable the action if there is copy permission', () => {
|
||||||
let documentMenu = new ContentActionModel({
|
let documentMenu = new ContentActionModel({
|
||||||
disableWithNoPermission: true,
|
disableWithNoPermission: true,
|
||||||
@@ -418,7 +440,7 @@ describe('DocumentList', () => {
|
|||||||
let actions = documentList.getNodeActions(nodeFile);
|
let actions = documentList.getNodeActions(nodeFile);
|
||||||
expect(actions.length).toBe(1);
|
expect(actions.length).toBe(1);
|
||||||
expect(actions[0].title).toEqual('FileAction');
|
expect(actions[0].title).toEqual('FileAction');
|
||||||
expect(actions[0].disabled).toBeUndefined();
|
expect(actions[0].disabled).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not disable the action if there is the right permission for the folder', () => {
|
it('should not disable the action if there is the right permission for the folder', () => {
|
||||||
@@ -438,7 +460,7 @@ describe('DocumentList', () => {
|
|||||||
let actions = documentList.getNodeActions(nodeFile);
|
let actions = documentList.getNodeActions(nodeFile);
|
||||||
expect(actions.length).toBe(1);
|
expect(actions.length).toBe(1);
|
||||||
expect(actions[0].title).toEqual('FolderAction');
|
expect(actions[0].title).toEqual('FolderAction');
|
||||||
expect(actions[0].disabled).toBeUndefined();
|
expect(actions[0].disabled).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not disable the action if there are no permissions for the file and disable with no permission is false', () => {
|
it('should not disable the action if there are no permissions for the file and disable with no permission is false', () => {
|
||||||
@@ -458,7 +480,7 @@ describe('DocumentList', () => {
|
|||||||
let actions = documentList.getNodeActions(nodeFile);
|
let actions = documentList.getNodeActions(nodeFile);
|
||||||
expect(actions.length).toBe(1);
|
expect(actions.length).toBe(1);
|
||||||
expect(actions[0].title).toEqual('FileAction');
|
expect(actions[0].title).toEqual('FileAction');
|
||||||
expect(actions[0].disabled).toBeUndefined();
|
expect(actions[0].disabled).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not disable the action if there are no permissions for the folder and disable with no permission is false', () => {
|
it('should not disable the action if there are no permissions for the folder and disable with no permission is false', () => {
|
||||||
@@ -478,7 +500,7 @@ describe('DocumentList', () => {
|
|||||||
let actions = documentList.getNodeActions(nodeFile);
|
let actions = documentList.getNodeActions(nodeFile);
|
||||||
expect(actions.length).toBe(1);
|
expect(actions.length).toBe(1);
|
||||||
expect(actions[0].title).toEqual('FolderAction');
|
expect(actions[0].title).toEqual('FolderAction');
|
||||||
expect(actions[0].disabled).toBeUndefined();
|
expect(actions[0].disabled).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should disable the action if there are no permissions for the file and disable with no permission is true', () => {
|
it('should disable the action if there are no permissions for the file and disable with no permission is true', () => {
|
||||||
|
@@ -465,7 +465,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
|||||||
.map(action => new ContentActionModel(action));
|
.map(action => new ContentActionModel(action));
|
||||||
|
|
||||||
actionsByTarget.forEach((action) => {
|
actionsByTarget.forEach((action) => {
|
||||||
this.disableActionsWithNoPermissions(node, action);
|
action.disabled = this.isActionDisabled(action, node);
|
||||||
});
|
});
|
||||||
|
|
||||||
return actionsByTarget;
|
return actionsByTarget;
|
||||||
@@ -475,10 +475,16 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
disableActionsWithNoPermissions(node: MinimalNodeEntity, action: ContentActionModel) {
|
private isActionDisabled(action: ContentActionModel, node: MinimalNodeEntity): boolean {
|
||||||
if (action.permission && action.disableWithNoPermission && !this.contentService.hasPermission(node.entry, action.permission)) {
|
if (typeof action.disabled === 'function') {
|
||||||
action.disabled = true;
|
return action.disabled(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action.permission && action.disableWithNoPermission && !this.contentService.hasPermission(node.entry, action.permission)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('contextmenu', ['$event'])
|
@HostListener('contextmenu', ['$event'])
|
||||||
|
@@ -23,7 +23,7 @@ export class ContentActionModel {
|
|||||||
target: string;
|
target: string;
|
||||||
permission: string;
|
permission: string;
|
||||||
disableWithNoPermission: boolean = false;
|
disableWithNoPermission: boolean = false;
|
||||||
disabled: boolean = false;
|
disabled: boolean | Function = false;
|
||||||
visible: boolean | Function = true;
|
visible: boolean | Function = true;
|
||||||
|
|
||||||
constructor(obj?: any) {
|
constructor(obj?: any) {
|
||||||
@@ -35,7 +35,10 @@ export class ContentActionModel {
|
|||||||
this.target = obj.target;
|
this.target = obj.target;
|
||||||
this.permission = obj.permission;
|
this.permission = obj.permission;
|
||||||
this.disableWithNoPermission = obj.disableWithNoPermission;
|
this.disableWithNoPermission = obj.disableWithNoPermission;
|
||||||
|
|
||||||
|
if (obj.hasOwnProperty('disabled')) {
|
||||||
this.disabled = obj.disabled;
|
this.disabled = obj.disabled;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj.hasOwnProperty('visible')) {
|
if (obj.hasOwnProperty('visible')) {
|
||||||
this.visible = obj.visible;
|
this.visible = obj.visible;
|
||||||
|
@@ -29,15 +29,12 @@ import { ContextMenuService } from './context-menu.service';
|
|||||||
template: `
|
template: `
|
||||||
<button mat-button [matMenuTriggerFor]="contextMenu"></button>
|
<button mat-button [matMenuTriggerFor]="contextMenu"></button>
|
||||||
<mat-menu #contextMenu="matMenu" class="context-menu">
|
<mat-menu #contextMenu="matMenu" class="context-menu">
|
||||||
<button
|
<button *ngFor="let link of links"
|
||||||
*ngFor="let link of links"
|
|
||||||
mat-menu-item
|
mat-menu-item
|
||||||
(click)="onMenuItemClick($event, link)"
|
[disabled]="link.model?.disabled"
|
||||||
[attr.disabled]="link.model?.disabled || undefined">
|
(click)="onMenuItemClick($event, link)">
|
||||||
<mat-icon *ngIf="showIcons && link.model?.icon">
|
<mat-icon *ngIf="showIcons && link.model?.icon">{{ link.model.icon }}</mat-icon>
|
||||||
{{ link.model?.icon }}
|
{{ (link.title || link.model?.title) | translate }}
|
||||||
</mat-icon>
|
|
||||||
{{ (link.title || link.model?.title) | translate}}
|
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
`
|
`
|
||||||
@@ -47,9 +44,7 @@ export class ContextMenuHolderComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private mouseLocation: { left: number, top: number } = {left: 0, top: 0};
|
private mouseLocation: { left: number, top: number } = {left: 0, top: 0};
|
||||||
private menuElement = null;
|
private menuElement = null;
|
||||||
private openSubscription: Subscription;
|
private subscriptions: Subscription[] = [];
|
||||||
private closeSubscription: Subscription;
|
|
||||||
private contextSubscription: Subscription;
|
|
||||||
private contextMenuListenerFn: () => void;
|
private contextMenuListenerFn: () => void;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
@@ -68,7 +63,7 @@ export class ContextMenuHolderComponent implements OnInit, OnDestroy {
|
|||||||
@HostListener('window:resize', ['$event'])
|
@HostListener('window:resize', ['$event'])
|
||||||
onResize(event) {
|
onResize(event) {
|
||||||
if (this.mdMenuElement) {
|
if (this.mdMenuElement) {
|
||||||
this.setPositionAfterCDKrecalculation();
|
this.updatePosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,9 +75,10 @@ export class ContextMenuHolderComponent implements OnInit, OnDestroy {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.contextSubscription = this.contextMenuService.show.subscribe(e => this.showMenu(e.event, e.obj));
|
this.subscriptions.push(
|
||||||
|
this.contextMenuService.show.subscribe(e => this.showMenu(e.event, e.obj)),
|
||||||
|
|
||||||
this.openSubscription = this.menuTrigger.onMenuOpen.subscribe(() => {
|
this.menuTrigger.onMenuOpen.subscribe(() => {
|
||||||
const container = this.overlayContainer.getContainerElement();
|
const container = this.overlayContainer.getContainerElement();
|
||||||
if (container) {
|
if (container) {
|
||||||
this.contextMenuListenerFn = this.renderer.listen(container, 'contextmenu', (e: Event) => {
|
this.contextMenuListenerFn = this.renderer.listen(container, 'contextmenu', (e: Event) => {
|
||||||
@@ -90,23 +86,25 @@ export class ContextMenuHolderComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.menuElement = this.getContextMenuElement();
|
this.menuElement = this.getContextMenuElement();
|
||||||
});
|
}),
|
||||||
|
|
||||||
this.closeSubscription = this.menuTrigger.onMenuClose.subscribe(() => {
|
this.menuTrigger.onMenuClose.subscribe(() => {
|
||||||
this.menuElement = null;
|
this.menuElement = null;
|
||||||
if (this.contextMenuListenerFn) {
|
if (this.contextMenuListenerFn) {
|
||||||
this.contextMenuListenerFn();
|
this.contextMenuListenerFn();
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
if (this.contextMenuListenerFn) {
|
if (this.contextMenuListenerFn) {
|
||||||
this.contextMenuListenerFn();
|
this.contextMenuListenerFn();
|
||||||
}
|
}
|
||||||
this.contextSubscription.unsubscribe();
|
|
||||||
this.openSubscription.unsubscribe();
|
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||||
this.closeSubscription.unsubscribe();
|
this.subscriptions = [];
|
||||||
|
|
||||||
this.menuElement = null;
|
this.menuElement = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,16 +130,10 @@ export class ContextMenuHolderComponent implements OnInit, OnDestroy {
|
|||||||
this.menuTrigger.openMenu();
|
this.menuTrigger.openMenu();
|
||||||
|
|
||||||
if (this.mdMenuElement) {
|
if (this.mdMenuElement) {
|
||||||
this.setPositionAfterCDKrecalculation();
|
this.updatePosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPositionAfterCDKrecalculation() {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setPosition();
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
get mdMenuElement() {
|
get mdMenuElement() {
|
||||||
return this.menuElement;
|
return this.menuElement;
|
||||||
}
|
}
|
||||||
@@ -153,7 +145,8 @@ export class ContextMenuHolderComponent implements OnInit, OnDestroy {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private setPosition() {
|
private updatePosition() {
|
||||||
|
setTimeout(() => {
|
||||||
if (this.mdMenuElement.clientWidth + this.mouseLocation.left > this.viewport.getViewportRect().width) {
|
if (this.mdMenuElement.clientWidth + this.mouseLocation.left > this.viewport.getViewportRect().width) {
|
||||||
this.menuTrigger.menu.xPosition = 'before';
|
this.menuTrigger.menu.xPosition = 'before';
|
||||||
this.mdMenuElement.parentElement.style.left = this.mouseLocation.left - this.mdMenuElement.clientWidth + 'px';
|
this.mdMenuElement.parentElement.style.left = this.mouseLocation.left - this.mdMenuElement.clientWidth + 'px';
|
||||||
@@ -169,6 +162,7 @@ export class ContextMenuHolderComponent implements OnInit, OnDestroy {
|
|||||||
this.menuTrigger.menu.yPosition = 'below';
|
this.menuTrigger.menu.yPosition = 'below';
|
||||||
this.mdMenuElement.parentElement.style.top = this.locationCss().top;
|
this.mdMenuElement.parentElement.style.top = this.locationCss().top;
|
||||||
}
|
}
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getContextMenuElement() {
|
private getContextMenuElement() {
|
||||||
|
@@ -952,20 +952,6 @@ fdescribe('DataTable', () => {
|
|||||||
expect(dataTable.getCellTooltip(row, col)).toBeNull();
|
expect(dataTable.getCellTooltip(row, col)).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should cache the rows menu', () => {
|
|
||||||
let emitted = 0;
|
|
||||||
dataTable.showRowActionsMenu.subscribe(() => { emitted++; });
|
|
||||||
|
|
||||||
const column = <DataColumn> {};
|
|
||||||
const row = <DataRow> { getValue: function (key: string) { return 'id'; } };
|
|
||||||
|
|
||||||
dataTable.getRowActions(row, column);
|
|
||||||
dataTable.getRowActions(row, column);
|
|
||||||
dataTable.getRowActions(row, column);
|
|
||||||
|
|
||||||
expect(emitted).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reset the menu cache after rows change', () => {
|
it('should reset the menu cache after rows change', () => {
|
||||||
let emitted = 0;
|
let emitted = 0;
|
||||||
dataTable.showRowActionsMenu.subscribe(() => { emitted++; });
|
dataTable.showRowActionsMenu.subscribe(() => { emitted++; });
|
||||||
|
@@ -166,8 +166,6 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
private click$: Observable<DataRowEvent>;
|
private click$: Observable<DataRowEvent>;
|
||||||
|
|
||||||
private differ: any;
|
private differ: any;
|
||||||
private rowMenuCache: object = {};
|
|
||||||
|
|
||||||
private subscriptions: Subscription[] = [];
|
private subscriptions: Subscription[] = [];
|
||||||
private singleClickStreamSub: Subscription;
|
private singleClickStreamSub: Subscription;
|
||||||
private multiClickStreamSub: Subscription;
|
private multiClickStreamSub: Subscription;
|
||||||
@@ -299,7 +297,6 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
private initTable() {
|
private initTable() {
|
||||||
this.data = new ObjectDataTableAdapter(this.rows, this.columns);
|
this.data = new ObjectDataTableAdapter(this.rows, this.columns);
|
||||||
this.setupData(this.data);
|
this.setupData(this.data);
|
||||||
this.rowMenuCache = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupData(adapter: DataTableAdapter) {
|
private setupData(adapter: DataTableAdapter) {
|
||||||
@@ -556,15 +553,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRowActions(row: DataRow, col: DataColumn): any[] {
|
getRowActions(row: DataRow, col: DataColumn): any[] {
|
||||||
const id = row.getValue('id');
|
|
||||||
|
|
||||||
if (!this.rowMenuCache[id]) {
|
|
||||||
let event = new DataCellEvent(row, col, []);
|
let event = new DataCellEvent(row, col, []);
|
||||||
this.showRowActionsMenu.emit(event);
|
this.showRowActionsMenu.emit(event);
|
||||||
this.rowMenuCache[id] = event.value.actions;
|
return event.value.actions;
|
||||||
}
|
|
||||||
|
|
||||||
return this.rowMenuCache[id];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onExecuteRowAction(row: DataRow, action: any) {
|
onExecuteRowAction(row: DataRow, action: any) {
|
||||||
|
Reference in New Issue
Block a user