mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-2859] fixes for the conditional visibility and disabled states (#3465)
* fixes for the conditional visibility and disabled states * update docs * cleanup code * remove unused code
This commit is contained in:
committed by
Eugenio Romano
parent
1d69f5c407
commit
6f2cbdf697
@@ -279,13 +279,13 @@
|
||||
</data-columns>
|
||||
|
||||
<content-actions>
|
||||
<!-- Conditional actions demo -->
|
||||
<content-action
|
||||
target="all"
|
||||
title="Action for 'custom' node"
|
||||
[disabled]="isCustomActionDisabled"
|
||||
(execute)="runCustomAction($event)">
|
||||
</content-action>
|
||||
<!-- Conditional actions demo -->
|
||||
<content-action
|
||||
icon="get_app"
|
||||
title="Download this file now!"
|
||||
@@ -298,12 +298,6 @@
|
||||
handler="download"
|
||||
[visible]="false">
|
||||
</content-action>
|
||||
<content-action
|
||||
icon="get_app"
|
||||
title="This can be toggled"
|
||||
handler="download"
|
||||
[visible]="showCustomDownloadAction">
|
||||
</content-action>
|
||||
<!-- common actions -->
|
||||
<content-action
|
||||
icon="get_app"
|
||||
@@ -448,12 +442,6 @@
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle color="primary" [(ngModel)]="showCustomDownloadAction">
|
||||
Toggle custom download action
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<mat-slide-toggle [color]="'primary'" [(ngModel)]="multiselect">{{'DOCUMENT_LIST.MULTISELECT_CHECKBOXES' |
|
||||
translate}}
|
||||
|
@@ -170,9 +170,6 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
|
||||
@ViewChild(InfinitePaginationComponent)
|
||||
infinitePaginationComponent: InfinitePaginationComponent;
|
||||
|
||||
@Input()
|
||||
showCustomDownloadAction = false;
|
||||
|
||||
permissionsStyle: PermissionStyleModel[] = [];
|
||||
infiniteScrolling: boolean;
|
||||
supportedPages: number[];
|
||||
@@ -514,7 +511,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
canDownloadNode = (node: MinimalNodeEntity): boolean => {
|
||||
if (node && node.entry && node.entry.name === 'For Sale.docx') {
|
||||
if (node && node.entry && node.entry.name === 'custom') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@@ -324,12 +324,10 @@ allow the item being copied/moved to be the destination if it is itself a folder
|
||||
|
||||
### Conditional visibility
|
||||
|
||||
The Content-action component allows you to control visibility with the help of the `visible`
|
||||
property which can receive its value in three main ways:
|
||||
The `<content-action>` component allows you to control visibility with the help of the `visible` property and supports the following scenarios:
|
||||
|
||||
- direct `boolean` value
|
||||
- binding to a `boolean` property
|
||||
- binding to a `Function` property that evaluates the condition and returns a `boolean` value
|
||||
- direct value of `boolean` type
|
||||
- binding to a property of the `Function` type that evaluates condition and returns `boolean` value
|
||||
|
||||
#### Using direct boolean value
|
||||
|
||||
@@ -342,30 +340,7 @@ property which can receive its value in three main ways:
|
||||
</content-action>
|
||||
```
|
||||
|
||||
#### Binding to a boolean property
|
||||
|
||||
```html
|
||||
<content-action
|
||||
icon="get_app"
|
||||
title="This can be toggled"
|
||||
handler="download"
|
||||
[visible]="showCustomDownloadAction">
|
||||
</content-action>
|
||||
```
|
||||
|
||||
The markup above relies on the `showCustomDownloadAction` property declared in your
|
||||
component class:
|
||||
|
||||
```ts
|
||||
export class MyComponent {
|
||||
|
||||
@Input()
|
||||
showCustomDownloadAction = true;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### Binding to a Function property
|
||||
#### Using a property of the Function type
|
||||
|
||||
```html
|
||||
<content-action
|
||||
@@ -409,7 +384,6 @@ funcName = (parameters): boolean => {
|
||||
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
|
||||
@@ -423,28 +397,6 @@ Similar to `visible` property, it is possible to control the `disabled` state wi
|
||||
</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
|
||||
|
@@ -42,4 +42,15 @@ export class ContentActionListComponent {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unregisterAction(action: ContentActionModel): boolean {
|
||||
if (this.documentList && action) {
|
||||
const idx = this.documentList.actions.indexOf(action);
|
||||
if (idx >= 0) {
|
||||
this.documentList.actions.splice(idx, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -132,9 +132,16 @@ export class ContentActionComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||
this.subscriptions = [];
|
||||
|
||||
if (this.documentActionModel) {
|
||||
this.unregister(this.documentActionModel);
|
||||
this.documentActionModel = null;
|
||||
}
|
||||
|
||||
if (this.folderActionModel) {
|
||||
this.unregister(this.folderActionModel);
|
||||
this.folderActionModel = null;
|
||||
}
|
||||
}
|
||||
|
||||
register(model: ContentActionModel): boolean {
|
||||
if (this.list) {
|
||||
@@ -143,6 +150,13 @@ export class ContentActionComponent implements OnInit, OnChanges, OnDestroy {
|
||||
return false;
|
||||
}
|
||||
|
||||
unregister(model: ContentActionModel): boolean {
|
||||
if (this.list) {
|
||||
return this.list.unregisterAction(model);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private generateAction(target: string): ContentActionModel {
|
||||
const model = new ContentActionModel({
|
||||
title: this.title,
|
||||
|
@@ -13,6 +13,7 @@
|
||||
[display]="display"
|
||||
[noPermission]="noPermission"
|
||||
[showHeader]="!isEmpty() && showHeader"
|
||||
[rowMenuCacheEnabled]="false"
|
||||
(showRowContextMenu)="onShowRowContextMenu($event)"
|
||||
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||
(executeRowAction)="onExecuteRowAction($event)"
|
||||
|
@@ -236,6 +236,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
private _pagination: BehaviorSubject<PaginationModel>;
|
||||
private layoutPresets = {};
|
||||
private subscriptions: Subscription[] = [];
|
||||
private rowMenuCache: { [key: string]: ContentActionModel[] } = {};
|
||||
|
||||
constructor(private documentListService: DocumentListService,
|
||||
private ngZone: NgZone,
|
||||
@@ -333,6 +334,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.rowMenuCache = {};
|
||||
this.loadLayoutPresets();
|
||||
this.data = new ShareDataTableAdapter(this.documentListService, this.thumbnailService, null, this.getDefaultSorting(), this.sortingMode);
|
||||
this.data.thumbnails = this.thumbnails;
|
||||
@@ -444,9 +446,10 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
}
|
||||
|
||||
getNodeActions(node: MinimalNodeEntity | any): ContentActionModel[] {
|
||||
let target = null;
|
||||
|
||||
if (node && node.entry) {
|
||||
let target = null;
|
||||
|
||||
if (node.entry.isFile) {
|
||||
target = 'document';
|
||||
} else if (node.entry.isFolder) {
|
||||
@@ -454,6 +457,14 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
}
|
||||
|
||||
if (target) {
|
||||
const actions = this.rowMenuCache[node.entry.id];
|
||||
if (actions) {
|
||||
actions.forEach(action => {
|
||||
this.refreshAction(action, node);
|
||||
});
|
||||
return actions;
|
||||
}
|
||||
|
||||
let actionsByTarget = this.actions
|
||||
.filter(entry => {
|
||||
const isVisible = (typeof entry.visible === 'function')
|
||||
@@ -465,9 +476,10 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
.map(action => new ContentActionModel(action));
|
||||
|
||||
actionsByTarget.forEach((action) => {
|
||||
action.disabled = this.isActionDisabled(action, node);
|
||||
this.refreshAction(action, node);
|
||||
});
|
||||
|
||||
this.rowMenuCache[node.entry.id] = actionsByTarget;
|
||||
return actionsByTarget;
|
||||
}
|
||||
}
|
||||
@@ -475,6 +487,19 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
return [];
|
||||
}
|
||||
|
||||
private refreshAction(action: ContentActionModel, node: MinimalNodeEntity) {
|
||||
action.disabled = this.isActionDisabled(action, node);
|
||||
action.visible = this.isActionVisible(action, node);
|
||||
}
|
||||
|
||||
private isActionVisible(action: ContentActionModel, node: MinimalNodeEntity): boolean {
|
||||
if (typeof action.visible === 'function') {
|
||||
return action.visible(node);
|
||||
}
|
||||
|
||||
return action.visible;
|
||||
}
|
||||
|
||||
private isActionDisabled(action: ContentActionModel, node: MinimalNodeEntity): boolean {
|
||||
if (typeof action.disabled === 'function') {
|
||||
return action.disabled(node);
|
||||
@@ -484,7 +509,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return action.disabled;
|
||||
}
|
||||
|
||||
@HostListener('contextmenu', ['$event'])
|
||||
|
@@ -29,13 +29,15 @@ import { ContextMenuService } from './context-menu.service';
|
||||
template: `
|
||||
<button mat-button [matMenuTriggerFor]="contextMenu"></button>
|
||||
<mat-menu #contextMenu="matMenu" class="context-menu">
|
||||
<button *ngFor="let link of links"
|
||||
<ng-container *ngFor="let link of links">
|
||||
<button *ngIf="link.model?.visible"
|
||||
mat-menu-item
|
||||
[disabled]="link.model?.disabled"
|
||||
(click)="onMenuItemClick($event, link)">
|
||||
<mat-icon *ngIf="showIcons && link.model?.icon">{{ link.model.icon }}</mat-icon>
|
||||
{{ (link.title || link.model?.title) | translate }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</mat-menu>
|
||||
`
|
||||
})
|
||||
|
@@ -155,6 +155,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
||||
@Input()
|
||||
noPermission: boolean = false;
|
||||
|
||||
@Input()
|
||||
rowMenuCacheEnabled = true;
|
||||
|
||||
noContentTemplate: TemplateRef<any>;
|
||||
noPermissionTemplate: TemplateRef<any>;
|
||||
loadingTemplate: TemplateRef<any>;
|
||||
@@ -166,6 +169,8 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
||||
private click$: Observable<DataRowEvent>;
|
||||
|
||||
private differ: any;
|
||||
private rowMenuCache: object = {};
|
||||
|
||||
private subscriptions: Subscription[] = [];
|
||||
private singleClickStreamSub: Subscription;
|
||||
private multiClickStreamSub: Subscription;
|
||||
@@ -297,6 +302,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
||||
private initTable() {
|
||||
this.data = new ObjectDataTableAdapter(this.rows, this.columns);
|
||||
this.setupData(this.data);
|
||||
this.rowMenuCache = {};
|
||||
}
|
||||
|
||||
private setupData(adapter: DataTableAdapter) {
|
||||
@@ -553,10 +559,19 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
||||
}
|
||||
|
||||
getRowActions(row: DataRow, col: DataColumn): any[] {
|
||||
const id = row.getValue('id');
|
||||
|
||||
if (!this.rowMenuCache[id]) {
|
||||
let event = new DataCellEvent(row, col, []);
|
||||
this.showRowActionsMenu.emit(event);
|
||||
if (!this.rowMenuCacheEnabled) {
|
||||
return event.value.actions;
|
||||
}
|
||||
this.rowMenuCache[id] = event.value.actions;
|
||||
}
|
||||
|
||||
return this.rowMenuCache[id];
|
||||
}
|
||||
|
||||
onExecuteRowAction(row: DataRow, action: any) {
|
||||
if (action.disabled || action.disabled) {
|
||||
|
Reference in New Issue
Block a user