core/wizard/wizard.component.ts
A generic component that is intended to serve as the building block of more wizards.
Example
<button
title="Add application"
class="btn btn-primary"
(click)="addApplication()"
>
Add application
</button>
import { Component } from '@angular/core';
import { WizardConfig, WizardService, Wizard } from '@c8y/ngx-components';
import { ModalOptions } from 'ngx-bootstrap/modal';
@Component({
selector: 'c8y-add-application-wizard',
templateUrl: './templatePath'
})
export class AddApplicationWizardComponent {
constructor(private wizardService: WizardService) {}
addApplication() {
const wizardConfig: WizardConfig = {
headerText: 'Add Application',
headerIcon: 'c8y-icon-modules',
bodyHeaderText: 'Select methods',
bodyHeaderIcon: 'c8y-icon-modules'
};
const initialState: Wizard = {
wizardConfig,
id: 'uploadApplication'
};
const modalOptions: ModalOptions = { initialState };
this.wizardService.show(modalOptions);
}
}
selector | c8y-wizard |
templateUrl | ./wizard.component.html |
Properties |
|
Methods |
Inputs |
Outputs |
constructor(wizardService: WizardService, bsModalRef: BsModalRef)
|
|||||||||
Parameters :
|
id |
Type : string
|
The id parameter identifies the particular wizard and can be used to refer to it when hooking wizard entries. Example: "wizardId". |
wizardConfig |
Type : WizardConfig
|
Default value : {}
|
A configuration object that allows you to set header values, both text and icon. |
onClose |
Type : EventEmitter<any>
|
The event that is emitted when the wizard is closed. |
onReset |
Type : EventEmitter<any>
|
The event that is emitted when the wizard is reseted. |
onSelect |
Type : EventEmitter<WizardEntry>
|
The event that is emitted when the wizard entry is clicked. |
close | ||||||||
close(result?: any)
|
||||||||
Closes the wizard.
Parameters :
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
onPath |
onPath()
|
Returns :
void
|
reset | ||||||||
reset(result?: any)
|
||||||||
Resets the wizard.
Parameters :
Returns :
void
|
body |
Type : TemplateRef<any>
|
Decorators :
@ViewChild('bodyRef', {static: true})
|
Readonly bodyTemplate$ |
Default value : this.wizardService.bodyTemplate$.pipe(
filter(body => body.wizardId === this.id)
)
|
Public bsModalRef |
Type : BsModalRef
|
componentInitialState |
Type : Partial<T>
|
Default value : {}
|
A state that will be assigned to the actual component contained by the wizard. |
footer |
Type : TemplateRef<any>
|
Decorators :
@ViewChild('footerRef', {static: true})
|
Readonly footerTemplate$ |
Default value : this.wizardService.footerTemplate$.pipe(
filter(footer => footer.wizardId === this.id)
)
|
header |
Type : TemplateRef<any>
|
Decorators :
@ViewChild('headerRef', {static: true})
|
Readonly headerTemplate$ |
Default value : this.wizardService.headerTemplate$.pipe(
filter(header => header.wizardId === this.id)
)
|
outlet |
Type : WizardOutletComponent
|
Decorators :
@ViewChild(WizardOutletComponent)
|
Public wizardService |
Type : WizardService
|
This is a generic component serving as a base block for building custom wizards. It provides many possibilities for composing custom wizards, all of these methods will be described below.
The main responsibility of a generic wizard is to present the available options to the user, and then respond to the user's choice. On this basis, the user will be redirected to a specific component under the given path, or that component will be rendered in the wizard.
By using the wizard configuration object (represented by WizardConfig interface), you can provide the content that will be displayed in the header and in the body header section.
The id
parameter determines the display type of the wizard.
import { Component } from '@angular/core';
import { WizardConfig, WizardModalService } from '@c8y/ngx-components';
import { ModalOptions } from 'ngx-bootstrap/modal';
@Component({
selector: 'wizard-demo'
})
export class WizardDemoComponent {
constructor(private c8yWizardModalService: WizardModalService) {}
addApplication() {
const wizardConfig: WizardConfig = {
headerText: 'Add Application',
headerIcon: 'c8y-icon-modules',
bodyHeaderText: 'Select methods',
bodyHeaderIcon: 'c8y-icon-modules'
};
const initialState = {
id: 'wizardId',
wizardConfig
};
const modalOptions: ModalOptions = { initialState };
this.c8yWizardModalService.show(modalOptions);
}
}
You can use BsModalService
directly from ngx-bootstrap/modal
to show the wizard.
import { Component } from '@angular/core';
import { WizardConfig, WizardComponent } from '@c8y/ngx-components';
import { ModalOptions } from 'ngx-bootstrap/modal';
@Component({
selector: 'wizard-demo'
})
export class WizardDemoComponent {
constructor(private bsModalService: BsModalService) {}
addApplication() {
const wizardConfig: WizardConfig = {
headerText: 'Add Application',
headerIcon: 'c8y-icon-modules',
bodyHeaderText: 'Select methods',
bodyHeaderIcon: 'c8y-icon-modules'
};
// Configure the initial state of the wizard.
const initialState = {
id: 'wizardId',
wizardConfig
};
const modalOptions: ModalOptions = { initialState };
// Configure modal options.
const options = {
class: 'modal-sm',
backdrop: 'static',
...modalOptions
} as ModalOptions<WizardComponent>;
this.bsModalService.show<WizardComponent>(WizardComponent, options);
}
}
We've added a new hook that adds an entry to the wizard's menu. This menu entry will lead to a "ContainerComponent" created below.
If the wizard contains only one entry without a path, the list will be skipped.
import { NgModule } from '@angular/core';
import { HOOK_WIZARD } from '@c8y/ngx-components';
import { ContainerComponent } from 'pathToYourContainerComponent';
@NgModule({
declarations: [ContainerComponent],
entryComponents: [ContainerComponent],
providers: [
{
provide: HOOK_WIZARD,
useValue: {
// The id of a wizard to which the entry should be hooked.
wizardId: 'wizardId',
// The container component is responsible for handling subsequent steps in the wizard.
component: ContainerComponent,
// Menu entry name
name: 'Upload application',
// Menu entry icon
c8yIcon: 'upload'
},
multi: true
}
]
})
export class YourModule {}
Component responsible for handling subsequent steps in the wizard.
Use c8y-wizard-header, c8y-wizard-body and c8y-wizard-footer in your custom component to maintain the correct layout.
import { Component } from '@angular/core';
import { WizardComponent } from '@c8y/ngx-components';
@Component({
selector: 'container-component',
template: `
<c8y-wizard-header>
New header content
</div>
</c8y-wizard-header>
<c8y-wizard-body>
New body content
</c8y-wizard-body>
<c8y-wizard-footer>
<button
(click)="back()"
>
Back
</button>
<button
(click)="cancel()"
>
Cancel
</button>
</c8y-wizard-footer>
`
})
export class ContainerComponent {
attributeToBePassed: string;
constructor(private wizardComponent: WizardComponent) {}
back() {
const result: any = 'dataToBeEmittedOnReset';
this.wizardComponent.reset(result);
}
cancel() {
const result: any = 'dataToBeEmittedOnClose';
this.wizardComponent.close(result);
}
}
The wizard component provides outputs that allow you to handle the selected menu entry, reset and close events.
component-with-wizard.component.ts
import { Component } from '@angular/core';
import { WizardEntry, WizardConfig, Wizard, WizardModalService } from '@c8y/ngx-components';
import { CustomComponent } from './custom.component.ts';
import { takeUntil } from 'rxjs/operators';
import { ModalOptions } from 'ngx-bootstrap/modal';
@Component({
selector: 'wizard-demo'
})
export class WizardDemoComponent {
destroy$: Subject<boolean> = new Subject<boolean>();
constructor(private c8yWizardModalService: WizardModalService) {}
onButtonClick() {
const wizardConfig: WizardConfig = {
headerIcon: 'c8y-icon-modules',
headerText: 'Wizard header',
bodyHeaderText: 'Body section header'
};
const initialState: Wizard<ContainerComponent> = {
id: 'wizardId',
wizardConfig,
componentState: {
attributeToBePassed: 'Some sample text'
}
};
const modalOptions: ModalOptions = { initialState };
const modalRef = this.c8yWizardModalService.show(modalOptions);
modalRef.content.onSelect.pipe(takeUntil(this.destroy$)).subscribe(menuEntry => {
// handle menu entry
});
modalRef.content.onClose.pipe(takeUntil(this.destroy$)).subscribe(result => {
// handle result
});
modalRef.content.onReset.pipe(takeUntil(this.destroy$)).subscribe(result => {
// handle result
});
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe();
}
}
<div class="viewport-modal animated fadeIn">
<ng-template *ngTemplateOutlet="(headerTemplate$ | async)?.template"></ng-template>
<ng-template #headerRef>
<div class="modal-header dialog-header animated fadeIn">
<h1 [c8yIcon]="wizardConfig.headerIcon"></h1>
<h4>{{ wizardConfig.headerText | translate }}</h4>
</div>
</ng-template>
<ng-template *ngTemplateOutlet="(bodyTemplate$ | async)?.template"></ng-template>
<ng-template #bodyRef>
<div class="p-16 p-t-8 text-center" *ngIf="wizardConfig.bodyHeaderText">
<div class="c8y-wizard-nav">
<i [c8yIcon]="wizardConfig.bodyHeaderIcon"></i>
<span>{{ wizardConfig.bodyHeaderText | translate }}</span>
</div>
</div>
</ng-template>
<c8y-wizard-outlet
[initialState]="componentInitialState"
[id]="id"
(onSelect)="onSelect.emit($event)"
(onPath)="onPath()"
></c8y-wizard-outlet>
<ng-template *ngTemplateOutlet="(footerTemplate$ | async)?.template"></ng-template>
<ng-template #footerRef>
<div class="modal-footer animated fadeIn">
<button
(click)="close()"
type="button"
class="btn btn-default"
title="{{ 'Cancel' | translate }}"
>
<span translate>Cancel</span>
</button>
</div>
</ng-template>
</div>