Ngx-admin: wizard

Created on 22 Feb 2017  路  4Comments  路  Source: akveo/ngx-admin

How do I create Form Wizard ng2-admin?

Most helpful comment

It'll take a bit of setup, but In the Theme's component folder, I created a folder called "baWizzard", which has the following folder structure:

/baWizzard/

  1. baWizzard.component.ts
  2. baWizzard.html
  3. baWizzard.scss
  4. baWizzardStep.component.ts
  5. baWizzardStep.html
  6. index.ts

Here is how you put them all together:

baWizzard.component.ts

import { Component, OnInit, Output, EventEmitter, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
import { baWizzardStepComponent } from './baWizzardStep.component';

@Component({
  selector: 'baWizzard',
  styleUrls: ['./baWizzard.scss'],
  templateUrl: './baWizzard.html'
})
export class baWizzardComponent implements OnInit, AfterContentInit  {

  @ContentChildren(baWizzardStepComponent) wizardSteps: QueryList<baWizzardStepComponent>;
  private _steps: Array<baWizzardStepComponent> = [];
  private _isCompleted: boolean = false;

  @Output() onStepChanged: EventEmitter<baWizzardStepComponent> = new EventEmitter<baWizzardStepComponent>();

  constructor() { }

  ngOnInit() {
  }

  ngAfterContentInit() {
    this.wizardSteps.forEach(step => this._steps.push(step));
    this._steps[0].isActive = true;
  }

  private get steps(): Array<baWizzardStepComponent> {
    return this._steps;
  }

  private get isCompleted(): boolean {
    return this._isCompleted;
  }

  private get activeStep(): baWizzardStepComponent {
    return this._steps.find(step => step.isActive);
  }

  private set activeStep(step: baWizzardStepComponent) {
    if (step !== this.activeStep && !step.isDisabled) {
      this.activeStep.isActive = false;
      step.isActive = true;
      this.onStepChanged.emit(step);
    }
  }

  private get activeStepIndex(): number {
    return this._steps.indexOf(this.activeStep);
  }

  private get hasNextStep(): boolean {
    return this.activeStepIndex < this._steps.length - 1;
  }

  private get hasPrevStep(): boolean {
    return this.activeStepIndex > 0;
  }

  goToStep(step: baWizzardStepComponent) {
    this.activeStep = step;
  }

  next() {
    if (this.hasNextStep) {
      let nextStep: baWizzardStepComponent = this._steps[this.activeStepIndex + 1];
      this.activeStep.onNext.emit();
      nextStep.isDisabled = false;
      this.activeStep = nextStep;
    }
  }

  previous() {
    if (this.hasPrevStep) {
      let prevStep: baWizzardStepComponent = this._steps[this.activeStepIndex - 1];
      this.activeStep.onPrev.emit();
      prevStep.isDisabled = false;
      this.activeStep = prevStep;
    }
  }

  complete() {
    this._isCompleted = true;
  }

}

baWizzard.html

<div class="row">
<ul class="nav nav-justified">
    <li  class="nav-item col-md-{{12/steps.length}}" *ngFor="let step of steps"  [ngClass]="{'active': step.isActive, 'enabled': !step.isDisabled, 'disabled': step.isDisabled}">
      <a (click)="goToStep(step)">{{step.title}}</a>
    </li>
  </ul>
</div>
<div class="card-block">
  <ng-content></ng-content><br>
  <div class="" [hidden]="isCompleted">
    <button type="button" class="btn btn-secondary float-left" style="float:left" (click)="previous()" [hidden]="!hasPrevStep || !activeStep.showPrev">Previous</button>
    <button type="button" class="btn btn-secondary float-right" style="float:right" (click)="next()" [disabled]="!activeStep.isValid" [hidden]="!hasNextStep || !activeStep.showNext">Next</button>
    <button type="button" class="btn btn-secondary float-right" style="float:right" (click)="complete()" [disabled]="!activeStep.isValid" [hidden]="hasNextStep" [routerLink]="['/pages/control-center']" >Done</button>
</div>
</div>

baWizzardStep.component.ts

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'baWizzardStep',
  templateUrl: './baWizzardStep.html'
})
export class baWizzardStepComponent implements OnInit {
  @Input() title: string;
  @Input() isValid: boolean = true;
  @Input() showNext: boolean = true;
  @Input() showPrev: boolean = true;

  @Output() onNext: EventEmitter<any> = new EventEmitter();
  @Output() onPrev: EventEmitter<any> = new EventEmitter();
  @Output() onComplete: EventEmitter<any> = new EventEmitter();

  private _isActive: boolean = false;
  isDisabled: boolean = true;

  constructor() { }

  ngOnInit() {
  }

  @Input('isActive') set isActive(isActive: boolean) {
    this._isActive = isActive;
    this.isDisabled = false;
  }

  get isActive(): boolean {
    return this._isActive;
  }

}

baWizzardStep.html

<div [hidden]="!isActive">
  <ng-content></ng-content>
</div>

index.ts

export * from './baWizzard.component';
export * from './baWizzardStep.component'

Then declare baWizzard and baWizzardStep in the module that you want to use it in, and then mark up your HTML correctly like so:
<baWizzard> <baWizzardStep [title]="'FirstFormStep'"> <!-- Custom Form Shit goes here. --> </baWizzardStep </baWizzard>

And repeat the baWizzardStep tags for however many steps you want your wizard to have.

All 4 comments

It'll take a bit of setup, but In the Theme's component folder, I created a folder called "baWizzard", which has the following folder structure:

/baWizzard/

  1. baWizzard.component.ts
  2. baWizzard.html
  3. baWizzard.scss
  4. baWizzardStep.component.ts
  5. baWizzardStep.html
  6. index.ts

Here is how you put them all together:

baWizzard.component.ts

import { Component, OnInit, Output, EventEmitter, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
import { baWizzardStepComponent } from './baWizzardStep.component';

@Component({
  selector: 'baWizzard',
  styleUrls: ['./baWizzard.scss'],
  templateUrl: './baWizzard.html'
})
export class baWizzardComponent implements OnInit, AfterContentInit  {

  @ContentChildren(baWizzardStepComponent) wizardSteps: QueryList<baWizzardStepComponent>;
  private _steps: Array<baWizzardStepComponent> = [];
  private _isCompleted: boolean = false;

  @Output() onStepChanged: EventEmitter<baWizzardStepComponent> = new EventEmitter<baWizzardStepComponent>();

  constructor() { }

  ngOnInit() {
  }

  ngAfterContentInit() {
    this.wizardSteps.forEach(step => this._steps.push(step));
    this._steps[0].isActive = true;
  }

  private get steps(): Array<baWizzardStepComponent> {
    return this._steps;
  }

  private get isCompleted(): boolean {
    return this._isCompleted;
  }

  private get activeStep(): baWizzardStepComponent {
    return this._steps.find(step => step.isActive);
  }

  private set activeStep(step: baWizzardStepComponent) {
    if (step !== this.activeStep && !step.isDisabled) {
      this.activeStep.isActive = false;
      step.isActive = true;
      this.onStepChanged.emit(step);
    }
  }

  private get activeStepIndex(): number {
    return this._steps.indexOf(this.activeStep);
  }

  private get hasNextStep(): boolean {
    return this.activeStepIndex < this._steps.length - 1;
  }

  private get hasPrevStep(): boolean {
    return this.activeStepIndex > 0;
  }

  goToStep(step: baWizzardStepComponent) {
    this.activeStep = step;
  }

  next() {
    if (this.hasNextStep) {
      let nextStep: baWizzardStepComponent = this._steps[this.activeStepIndex + 1];
      this.activeStep.onNext.emit();
      nextStep.isDisabled = false;
      this.activeStep = nextStep;
    }
  }

  previous() {
    if (this.hasPrevStep) {
      let prevStep: baWizzardStepComponent = this._steps[this.activeStepIndex - 1];
      this.activeStep.onPrev.emit();
      prevStep.isDisabled = false;
      this.activeStep = prevStep;
    }
  }

  complete() {
    this._isCompleted = true;
  }

}

baWizzard.html

<div class="row">
<ul class="nav nav-justified">
    <li  class="nav-item col-md-{{12/steps.length}}" *ngFor="let step of steps"  [ngClass]="{'active': step.isActive, 'enabled': !step.isDisabled, 'disabled': step.isDisabled}">
      <a (click)="goToStep(step)">{{step.title}}</a>
    </li>
  </ul>
</div>
<div class="card-block">
  <ng-content></ng-content><br>
  <div class="" [hidden]="isCompleted">
    <button type="button" class="btn btn-secondary float-left" style="float:left" (click)="previous()" [hidden]="!hasPrevStep || !activeStep.showPrev">Previous</button>
    <button type="button" class="btn btn-secondary float-right" style="float:right" (click)="next()" [disabled]="!activeStep.isValid" [hidden]="!hasNextStep || !activeStep.showNext">Next</button>
    <button type="button" class="btn btn-secondary float-right" style="float:right" (click)="complete()" [disabled]="!activeStep.isValid" [hidden]="hasNextStep" [routerLink]="['/pages/control-center']" >Done</button>
</div>
</div>

baWizzardStep.component.ts

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'baWizzardStep',
  templateUrl: './baWizzardStep.html'
})
export class baWizzardStepComponent implements OnInit {
  @Input() title: string;
  @Input() isValid: boolean = true;
  @Input() showNext: boolean = true;
  @Input() showPrev: boolean = true;

  @Output() onNext: EventEmitter<any> = new EventEmitter();
  @Output() onPrev: EventEmitter<any> = new EventEmitter();
  @Output() onComplete: EventEmitter<any> = new EventEmitter();

  private _isActive: boolean = false;
  isDisabled: boolean = true;

  constructor() { }

  ngOnInit() {
  }

  @Input('isActive') set isActive(isActive: boolean) {
    this._isActive = isActive;
    this.isDisabled = false;
  }

  get isActive(): boolean {
    return this._isActive;
  }

}

baWizzardStep.html

<div [hidden]="!isActive">
  <ng-content></ng-content>
</div>

index.ts

export * from './baWizzard.component';
export * from './baWizzardStep.component'

Then declare baWizzard and baWizzardStep in the module that you want to use it in, and then mark up your HTML correctly like so:
<baWizzard> <baWizzardStep [title]="'FirstFormStep'"> <!-- Custom Form Shit goes here. --> </baWizzardStep </baWizzard>

And repeat the baWizzardStep tags for however many steps you want your wizard to have.

@Bengejd please add code baWizzard.scss

Per requested heres the baWizzard.scss. Edit it as you like, I just made it so that it would be functional for the time being, will probably change the colors a little bit.
.card-block { overflow-y: auto; }; .card-footer { background-color: #fff; border-top: 0 none; }; .nav-item { padding: 1rem 0rem; border-bottom: 0.5rem solid #ccc; }; .active { font-weight: bold; color: black; border-bottom-color: #1976D2 !important; }; .enabled { border-bottom-color: rgb(88, 162, 234); }; .disabled { color: #ccc; };

@Bengejd how to dynamically add steps?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PatrickHuetter picture PatrickHuetter  路  3Comments

tal-shahar picture tal-shahar  路  3Comments

lopn picture lopn  路  4Comments

queirozfcom picture queirozfcom  路  4Comments

nfdavenport picture nfdavenport  路  3Comments