mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-04-23 22:30:37 +00:00
feat: enable tab navigation buttons
This commit is contained in:
@@ -15,13 +15,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component, DestroyRef, inject, Injector, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { NgClass, NgForOf, NgIf, NgStyle, NgTemplateOutlet } from '@angular/common';
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
DestroyRef,
|
||||
inject,
|
||||
Injector,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
signal,
|
||||
ViewChild,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { filter } from 'rxjs';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { MatTabGroup, MatTabsModule } from '@angular/material/tabs';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { FormRulesManager, formRulesManagerFactory } from '../models/form-rules.model';
|
||||
import { FormService } from '../services/form.service';
|
||||
@@ -71,7 +84,7 @@ import { FormLayoutColumn, getFormLayoutColumnWidth } from './helpers/column-wid
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class FormRendererComponent<T> implements OnInit, OnDestroy {
|
||||
export class FormRendererComponent<T> implements OnInit, OnDestroy, AfterViewInit {
|
||||
private readonly middlewareServices = inject<FormFieldModelRenderMiddleware[]>(FORM_FIELD_MODEL_RENDER_MIDDLEWARE, { optional: true }) ?? [];
|
||||
|
||||
public readonly formService = inject(FormService);
|
||||
@@ -87,6 +100,22 @@ export class FormRendererComponent<T> implements OnInit, OnDestroy {
|
||||
@Input()
|
||||
readOnly = false;
|
||||
|
||||
@ViewChild(MatTabGroup) tabGroup!: MatTabGroup;
|
||||
|
||||
private readonly currentTabIndex = signal(0);
|
||||
|
||||
get canNavigateNext(): boolean {
|
||||
return this.currentTabIndex() < this.visibleTabCount - 1;
|
||||
}
|
||||
|
||||
get canNavigatePrevious(): boolean {
|
||||
return this.currentTabIndex() > 0;
|
||||
}
|
||||
|
||||
get visibleTabCount(): number {
|
||||
return this.visibleTabs().length;
|
||||
}
|
||||
|
||||
debugMode: boolean;
|
||||
|
||||
fields: FormFieldModel[];
|
||||
@@ -105,6 +134,12 @@ export class FormRendererComponent<T> implements OnInit, OnDestroy {
|
||||
.subscribe(() => this.visibilityService.refreshVisibility(this.formDefinition));
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
if (this.tabGroup) {
|
||||
this.tabGroup.selectedIndexChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((index) => this.currentTabIndex.set(index));
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.formRulesManager.destroy();
|
||||
}
|
||||
@@ -117,6 +152,18 @@ export class FormRendererComponent<T> implements OnInit, OnDestroy {
|
||||
return this.formDefinition.tabs.filter((tab) => tab.isVisible);
|
||||
}
|
||||
|
||||
navigateToNextTab(): void {
|
||||
if (this.tabGroup && this.canNavigateNext) {
|
||||
this.tabGroup.selectedIndex = this.tabGroup.selectedIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
navigateToPreviousTab(): void {
|
||||
if (this.tabGroup && this.canNavigatePrevious) {
|
||||
this.tabGroup.selectedIndex = this.tabGroup.selectedIndex - 1;
|
||||
}
|
||||
}
|
||||
|
||||
getNumberOfColumns(content: ContainerModel): number {
|
||||
return (content.json?.numberOfColumns || 1) > (content.columns?.length || 1)
|
||||
? content.json?.numberOfColumns || 1
|
||||
|
||||
@@ -87,6 +87,10 @@
|
||||
"NO_LABEL": "Cancel"
|
||||
}
|
||||
},
|
||||
"BUTTON": {
|
||||
"PREVIOUS_TAB": "Previous",
|
||||
"NEXT_TAB": "Next"
|
||||
},
|
||||
"FIELD_STYLE": {
|
||||
"FONT_SIZE": "Font size",
|
||||
"FONT_WEIGHT": "Font weight",
|
||||
|
||||
@@ -1,107 +1,141 @@
|
||||
<div *ngIf="!hasForm()">
|
||||
<ng-content select="[empty-form]" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
*ngIf="hasForm()"
|
||||
class="adf-cloud-form-container adf-cloud-form-{{ displayConfiguration?.options?.fullscreen ? 'fullscreen' : 'inline' }}-container"
|
||||
[style]="formStyle"
|
||||
>
|
||||
<div
|
||||
class="adf-cloud-form-content"
|
||||
[class.adf-cloud-form-content-standalone-fullscreen]="displayMode === 'standalone' && displayConfiguration?.options?.fullscreen"
|
||||
[class.adf-cloud-form-content-toolbar]="!!displayConfiguration?.options?.displayToolbar"
|
||||
[cdkTrapFocus]="displayConfiguration?.options?.trapFocus"
|
||||
cdkTrapFocusAutoCapture>
|
||||
<adf-toolbar class="adf-cloud-form-toolbar" *ngIf="displayConfiguration?.options?.displayToolbar">
|
||||
<div class="adf-cloud-form__form-title">
|
||||
<span class="adf-cloud-form__display-name" [title]="form.taskName">
|
||||
{{ form.taskName }}
|
||||
<ng-container *ngIf="!form.taskName">
|
||||
{{ 'FORM.FORM_RENDERER.NAMELESS_TASK' | translate }}
|
||||
</ng-container>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<adf-toolbar-divider *ngIf="displayConfiguration?.options?.displayCloseButton" />
|
||||
<button
|
||||
*ngIf="displayConfiguration?.options?.displayCloseButton"
|
||||
class="adf-cloud-form-close-button"
|
||||
data-automation-id="adf-toolbar-right-back"
|
||||
[attr.aria-label]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
|
||||
[attr.data-automation-id]="'adf-cloud-form-close-button'"
|
||||
[title]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
|
||||
mat-icon-button
|
||||
title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}"
|
||||
(click)="switchToDisplayMode()"
|
||||
>
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
</adf-toolbar>
|
||||
|
||||
<mat-card
|
||||
appearance="outlined"
|
||||
class="adf-cloud-form-content-card"
|
||||
[class.adf-cloud-form-content-card-fullscreen]="displayMode === 'fullScreen'"
|
||||
[class.adf-cloud-form-content-card-fullscreen-toolbar]="displayMode === 'fullScreen' && displayConfiguration?.options?.displayToolbar"
|
||||
>
|
||||
<div class="adf-cloud-form-content-card-container">
|
||||
<mat-card-header *ngIf="showTitle || showRefreshButton || showValidationIcon">
|
||||
<mat-card-title>
|
||||
<h4>
|
||||
<div *ngIf="showValidationIcon" class="adf-form-validation-button">
|
||||
<i id="adf-valid-form-icon" class="material-icons" *ngIf="form.isValid; else no_valid_form">check_circle</i>
|
||||
<ng-template #no_valid_form>
|
||||
<i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="!displayConfiguration?.options?.fullscreen && findDisplayConfiguration('fullScreen')"
|
||||
class="adf-cloud-form-fullscreen-button"
|
||||
>
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="switchToDisplayMode('fullScreen')"
|
||||
[attr.data-automation-id]="'adf-cloud-form-fullscreen-button'"
|
||||
>
|
||||
<mat-icon adf-icon="fullscreen" />
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="showRefreshButton" class="adf-cloud-form-reload-button" [title]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
|
||||
<button mat-icon-button (click)="onRefreshClicked()" [attr.aria-label]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
|
||||
<mat-icon adf-icon="refresh" />
|
||||
</button>
|
||||
</div>
|
||||
<span *ngIf="isTitleEnabled()" class="adf-cloud-form-title" [title]="form.taskName"
|
||||
>{{ form.taskName }}
|
||||
<ng-container *ngIf="!form.taskName">
|
||||
{{ 'FORM.FORM_RENDERER.NAMELESS_TASK' | translate }}
|
||||
</ng-container>
|
||||
</span>
|
||||
</h4>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="adf-form-container-card-content">
|
||||
<adf-form-renderer [formDefinition]="form" [readOnly]="readOnly" />
|
||||
</mat-card-content>
|
||||
<mat-card-actions *ngIf="form.hasOutcomes()" class="adf-cloud-form-content-card-actions" align="end">
|
||||
<ng-content select="adf-cloud-form-custom-outcomes" />
|
||||
<ng-container *ngFor="let outcome of form.outcomes">
|
||||
<button
|
||||
*ngIf="outcome.isVisible"
|
||||
[id]="'adf-form-' + outcome.name | formatSpace"
|
||||
[color]="getColorForOutcome(outcome.name)"
|
||||
mat-button
|
||||
[disabled]="!isOutcomeButtonEnabled(outcome)"
|
||||
[class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
|
||||
class="adf-cloud-form-custom-outcome-button"
|
||||
(click)="onOutcomeClicked(outcome)"
|
||||
>
|
||||
{{ getCustomOutcomeButtonText(outcome) || (outcome.name | translate | uppercase) }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</mat-card-actions>
|
||||
</div>
|
||||
</mat-card>
|
||||
@if (!hasForm()) {
|
||||
<div>
|
||||
<ng-content select="[empty-form]" />
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div
|
||||
class="adf-cloud-form-container adf-cloud-form-{{ displayConfiguration?.options?.fullscreen ? 'fullscreen' : 'inline' }}-container"
|
||||
[style]="formStyle"
|
||||
>
|
||||
<div
|
||||
class="adf-cloud-form-content"
|
||||
[class.adf-cloud-form-content-standalone-fullscreen]="displayMode === 'standalone' && displayConfiguration?.options?.fullscreen"
|
||||
[class.adf-cloud-form-content-toolbar]="!!displayConfiguration?.options?.displayToolbar"
|
||||
[cdkTrapFocus]="displayConfiguration?.options?.trapFocus"
|
||||
cdkTrapFocusAutoCapture>
|
||||
@if (displayConfiguration?.options?.displayToolbar) {
|
||||
<adf-toolbar class="adf-cloud-form-toolbar">
|
||||
<div class="adf-cloud-form__form-title">
|
||||
<span class="adf-cloud-form__display-name" [title]="form.taskName">
|
||||
{{ form.taskName }}
|
||||
@if (!form.taskName) {
|
||||
{{ 'FORM.FORM_RENDERER.NAMELESS_TASK' | translate }}
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@if (displayConfiguration?.options?.displayCloseButton) {
|
||||
<adf-toolbar-divider />
|
||||
<button
|
||||
class="adf-cloud-form-close-button"
|
||||
data-automation-id="adf-toolbar-right-back"
|
||||
[attr.aria-label]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
|
||||
[attr.data-automation-id]="'adf-cloud-form-close-button'"
|
||||
[title]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
|
||||
mat-icon-button
|
||||
(click)="switchToDisplayMode()"
|
||||
>
|
||||
<mat-icon adf-icon="close" />
|
||||
</button>
|
||||
}
|
||||
</adf-toolbar>
|
||||
}
|
||||
|
||||
<mat-card
|
||||
appearance="outlined"
|
||||
class="adf-cloud-form-content-card"
|
||||
[class.adf-cloud-form-content-card-fullscreen]="displayMode === 'fullScreen'"
|
||||
[class.adf-cloud-form-content-card-fullscreen-toolbar]="displayMode === 'fullScreen' && displayConfiguration?.options?.displayToolbar"
|
||||
>
|
||||
<div class="adf-cloud-form-content-card-container">
|
||||
@if (showTitle || showRefreshButton || showValidationIcon) {
|
||||
<mat-card-header>
|
||||
<mat-card-title>
|
||||
<h4>
|
||||
@if (showValidationIcon) {
|
||||
<div class="adf-form-validation-button">
|
||||
@if (form.isValid) {
|
||||
<i id="adf-valid-form-icon" class="material-icons">check_circle</i>
|
||||
} @else {
|
||||
<i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (!displayConfiguration?.options?.fullscreen && findDisplayConfiguration('fullScreen')) {
|
||||
<div class="adf-cloud-form-fullscreen-button">
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="switchToDisplayMode('fullScreen')"
|
||||
[attr.data-automation-id]="'adf-cloud-form-fullscreen-button'"
|
||||
>
|
||||
<mat-icon adf-icon="fullscreen" />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@if (showRefreshButton) {
|
||||
<div class="adf-cloud-form-reload-button" [title]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
|
||||
<button mat-icon-button (click)="onRefreshClicked()" [attr.aria-label]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
|
||||
<mat-icon adf-icon="refresh" />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@if (isTitleEnabled()) {
|
||||
<span class="adf-cloud-form-title" [title]="form.taskName">
|
||||
{{ form.taskName }}
|
||||
@if (!form.taskName) {
|
||||
{{ 'FORM.FORM_RENDERER.NAMELESS_TASK' | translate }}
|
||||
}
|
||||
</span>
|
||||
}
|
||||
</h4>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
}
|
||||
<mat-card-content class="adf-form-container-card-content">
|
||||
<adf-form-renderer [formDefinition]="form" [readOnly]="readOnly" />
|
||||
</mat-card-content>
|
||||
@if (shouldShowTabNavigation) {
|
||||
<div class="adf-tab-navigation-buttons">
|
||||
<button
|
||||
mat-button
|
||||
[disabled]="!formRenderer.canNavigatePrevious"
|
||||
(click)="formRenderer.navigateToPreviousTab()"
|
||||
data-automation-id="tab-nav-previous-button">
|
||||
<mat-icon adf-icon="keyboard_arrow_left" />
|
||||
{{ 'FORM.BUTTON.PREVIOUS_TAB' | translate }}
|
||||
</button>
|
||||
<button
|
||||
mat-button
|
||||
[disabled]="!formRenderer.canNavigateNext"
|
||||
(click)="formRenderer.navigateToNextTab()"
|
||||
data-automation-id="tab-nav-next-button">
|
||||
{{ 'FORM.BUTTON.NEXT_TAB' | translate }}
|
||||
<mat-icon adf-icon="keyboard_arrow_right" />
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@if (form.hasOutcomes()) {
|
||||
<mat-card-actions class="adf-cloud-form-content-card-actions" align="end">
|
||||
<ng-content select="adf-cloud-form-custom-outcomes" />
|
||||
@for (outcome of form.outcomes; track outcome.name) {
|
||||
@if (outcome.isVisible) {
|
||||
<button
|
||||
[id]="'adf-form-' + outcome.name | formatSpace"
|
||||
[color]="getColorForOutcome(outcome.name)"
|
||||
mat-button
|
||||
[disabled]="!isOutcomeButtonEnabled(outcome)"
|
||||
[class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
|
||||
class="adf-cloud-form-custom-outcome-button"
|
||||
(click)="onOutcomeClicked(outcome)"
|
||||
>
|
||||
{{ getCustomOutcomeButtonText(outcome) || (outcome.name | translate | uppercase) }}
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</mat-card-actions>
|
||||
}
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -137,4 +137,22 @@
|
||||
.adf-label {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.adf-tab-navigation-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 24px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
@media (width <= 600px) {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ import {
|
||||
OnChanges,
|
||||
OnInit,
|
||||
Output,
|
||||
SimpleChanges
|
||||
SimpleChanges,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { forkJoin, Observable, of, Subscription } from 'rxjs';
|
||||
import { filter, map, switchMap } from 'rxjs/operators';
|
||||
@@ -60,7 +61,7 @@ import { FormCloudDisplayMode, FormCloudDisplayModeConfiguration } from '../../s
|
||||
import { FormCloudSpinnerService } from '../services/spinner/form-cloud-spinner.service';
|
||||
import { DisplayModeService } from '../services/display-mode.service';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { UpperCasePipe } from '@angular/common';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
@@ -71,7 +72,7 @@ export const FORM_CLOUD_FIELD_VALIDATORS_TOKEN = new InjectionToken<FormFieldVal
|
||||
@Component({
|
||||
selector: 'adf-cloud-form',
|
||||
imports: [
|
||||
CommonModule,
|
||||
UpperCasePipe,
|
||||
TranslatePipe,
|
||||
FormatSpacePipe,
|
||||
MatButtonModule,
|
||||
@@ -140,6 +141,10 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
||||
@Input()
|
||||
enableParentVisibilityCheck: boolean = false;
|
||||
|
||||
/** Toggle rendering of the tab navigation buttons (Previous/Next). */
|
||||
@Input()
|
||||
showTabNavigationButtons = false;
|
||||
|
||||
/** Emitted when the form is submitted with the `Save` or custom outcomes. */
|
||||
@Output()
|
||||
formSaved = new EventEmitter<FormModel>();
|
||||
@@ -178,6 +183,13 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
|
||||
displayConfiguration: FormCloudDisplayModeConfiguration = DisplayModeService.DEFAULT_DISPLAY_MODE_CONFIGURATIONS[0];
|
||||
style: string = '';
|
||||
|
||||
@ViewChild(FormRendererComponent)
|
||||
formRenderer!: FormRendererComponent<any>;
|
||||
|
||||
get shouldShowTabNavigation(): boolean {
|
||||
return this.showTabNavigationButtons && this.form?.json?.showTabNavigation === true && this.formRenderer?.visibleTabs().length > 1;
|
||||
}
|
||||
|
||||
protected formCloudService = inject(FormCloudService);
|
||||
protected formService = inject(FormService);
|
||||
protected visibilityService = inject(WidgetVisibilityService);
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
[formId]="processDefinitionCurrent.formKey"
|
||||
[displayModeConfigurations]="displayModeConfigurations"
|
||||
[enableParentVisibilityCheck]="enableParentVisibilityCheck"
|
||||
[showTabNavigationButtons]="showTabNavigationButtons"
|
||||
[showSaveButton]="showSaveButton"
|
||||
[showCompleteButton]="showCompleteButton"
|
||||
[showRefreshButton]="false"
|
||||
|
||||
@@ -151,6 +151,10 @@ export class StartProcessCloudComponent implements OnChanges, OnInit {
|
||||
@Input()
|
||||
enableParentVisibilityCheck: boolean = false;
|
||||
|
||||
/** Toggle rendering of the tab navigation buttons (Previous/Next). */
|
||||
@Input()
|
||||
showTabNavigationButtons = false;
|
||||
|
||||
/** Emitted when the process is successfully started. */
|
||||
@Output()
|
||||
success = new EventEmitter<ProcessInstanceCloud>();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
[customCompleteButtonText]="customCompleteButtonText"
|
||||
[displayModeConfigurations]="displayModeConfigurations"
|
||||
[enableParentVisibilityCheck]="enableParentVisibilityCheck"
|
||||
[showTabNavigationButtons]="showTabNavigationButtons"
|
||||
(formLoaded)="onFormLoaded($event)"
|
||||
(formSaved)="onFormSaved($event)"
|
||||
(formCompleted)="onFormCompleted($event)"
|
||||
|
||||
@@ -117,6 +117,10 @@ export class TaskFormCloudComponent {
|
||||
@Input()
|
||||
enableParentVisibilityCheck: boolean = false;
|
||||
|
||||
/** Toggle rendering of the tab navigation buttons (Previous/Next). */
|
||||
@Input()
|
||||
showTabNavigationButtons = false;
|
||||
|
||||
/** Task details. */
|
||||
@Input()
|
||||
taskDetails: TaskDetailsCloudModel;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[candidateGroups]="candidateGroups"
|
||||
[displayModeConfigurations]="displayModeConfigurations"
|
||||
[enableParentVisibilityCheck]="enableParentVisibilityCheck"
|
||||
[showTabNavigationButtons]="showTabNavigationButtons"
|
||||
[showValidationIcon]="showValidationIcon"
|
||||
[showTitle]="showTitle"
|
||||
[taskId]="taskId"
|
||||
|
||||
@@ -74,6 +74,10 @@ export class UserTaskCloudComponent implements OnInit, OnChanges {
|
||||
@Input()
|
||||
enableParentVisibilityCheck: boolean = false;
|
||||
|
||||
/** Toggle rendering of the tab navigation buttons (Previous/Next). */
|
||||
@Input()
|
||||
showTabNavigationButtons = false;
|
||||
|
||||
/** Toggle readonly state of the task. */
|
||||
@Input()
|
||||
readOnly = false;
|
||||
|
||||
Reference in New Issue
Block a user