Angualr cdk 学习之 Stepper

2019-01-05  本文已影响37人  tuacy

       cdk Stepper 让我们能够更好的处理类似于工作流的情况(任务分为多个步骤,上一步操作完成之后进入下一步的操作,比如咱们休假申请单要经过多个领导的审批的情况)。

       还是和之前cdk 里面其他功能模块一样,要使用Stepper 需provider CdkStepperModule的。

import {CdkStepperModule} from '@angular/cdk/stepper';

       cdk Stepper看起来复杂其实里面的东西不是很多。整个Stepper都是围绕一个组件CdkStep(cdk-step)和6个指令(CdkStepper、CdkStepLabel、CdkStepperNext、CdkStepperPrevious、CdkStepHeader)来展开的。咱们上面不是说了么,cdk Stepper一般用来处理多个步骤任务。这里每个任务的内容用CdkStep组件来表示,所以有多少个步骤就会 有多少个CdkStep组件。CdkStepper指令呢则是用来管理这些组件比如跳到下一步,上一步,完成等等(所以cdk Stepper使用的时候我们需要另外定义一个组件继承自CdkStepper指令,我们可以把他当做是工作流组件)。CdkStepperNext、CdkStepperPrevious两个指令正好对应上一步下一步,一般会添加在button上面包含在CdkStep组件里面,因为每个步骤都可能有上一步,下一步这样的。CdkStepLabel指令则是对每一个步骤的描述你也可以认为是每个步骤的标题。CdkStepHeader指令一般则是用来表示当前进行到哪一步了。一般也是会自定义一个组件继承CdkStepHeader实现。

一 CdkStep

       CdkStep其实是一个组件来着。表示每个步骤的内容。所以任务有多少步就会有多少个CdkStep。比如如下代码有两个步骤所以有两个CdkStep(cdk-step):

<h1>cdk stepper</h1>
<yx-stepper>
    <cdk-step [stepControl]="frmStep1" #step1="cdkStep">
        <ng-template cdkStepLabel>第一步</ng-template>
        <form #frmStep1="ngForm">
            <input type="text" name="a" value="a"/>
        </form>
        <button style="margin: 8px" cdkStepperNext type="button">下一步</button>
    </cdk-step>
    <cdk-step cdkStep #step2="cdkStep">
        <ng-template cdkStepLabel>第二步</ng-template>
        <form #frmStep2="ngForm">
            <input type="text" name="b" value="b"/>
        </form>
        <button cdkStepperPrevious type="button">上一步</button>
        <button style="margin: 8px" cdkStepperNext type="button">完成</button>
    </cdk-step>
</yx-stepper>

       每个CdkStep组件里面的内容对应每个步骤的内容。

       Selector: cdk-step

       Exported as: cdkStep

1.1 CdkStep组件属性

属性 内容 解释
ariaLabel: string @Input('aria-label') 添加aria-label属性
ariaLabelledby: string @Input('aria-labelledby') 添加aria-labelledby属性
completed: boolean @Input() 当前步骤是否标记为完成状态
editable: boolean @Input() 当前步骤标记为完成之后,是否还可以回到该步骤
errorMessage: string @Input() 错误信息
hasError: boolean @Input() 是否有错误
label: string @Input() 当前步骤对应的label,和cdkStepLabel指令的作用是一样的(可以简单的把他认为是步骤的标题)
optional: boolean @Input() 当前步骤是否是可选的
state: StepState @Input() 当前步骤的状态
stepControl: AbstractControl @Input() 用于验证当前步骤的合法性
content: TemplateRef<any> 当前步骤 试图元素内容
interacted: false 用户是否看到当前步骤内容
stepLabel: CdkStepLabel 当前步骤label内容

1.2 CdkStep组件方法

export declare class CdkStep implements OnChanges {
    ...
    /** 选中当前步骤(select哪个步骤则选中那个步骤) */
    select(): void;
    /** 设置当前步骤到无效状态 */
    reset(): void;
    ...
}

CdkStep组件里面大部分的方法都需要配合我们下面要讲的CdkStepper指令来使用

二 CdkStepper

       CdkStepper是一个指令,用来管理所有的步骤,即CdkStepper是用来管理CdkStep组件的。一般的做法是自定义一个组件继承CdkStepper指令。并且CdkStep组件是这个组件的子组件。比如如下的代码我们定义一个StepperComponent组件继承CdkStepper指令:

import {
    AfterContentInit,
    ChangeDetectionStrategy,
    Component,
    ContentChildren,
    EventEmitter,
    Output,
    QueryList,
    ViewEncapsulation
} from '@angular/core';
import {AnimationEvent} from '@angular/animations';
import {CdkStep, CdkStepper, StepContentPositionState} from '@angular/cdk/stepper';
import {Subject} from 'rxjs';
import {distinctUntilChanged, takeUntil} from 'rxjs/operators';
import {yxStepperAnimations} from './stepper-animations';

@Component({
    selector: 'yx-stepper',
    templateUrl: './stepper.component.html',
    styleUrls: ['./stepper.component.less'],
    providers: [{provide: CdkStepper, useExisting: StepperComponent}],
    animations: [yxStepperAnimations.horizontalStepTransition],
    encapsulation: ViewEncapsulation.None,
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StepperComponent extends CdkStepper implements AfterContentInit {

    /** Steps that the stepper holds. */
    @ContentChildren(CdkStep) _steps: QueryList<CdkStep>;

    /** Event emitted when the current step is done transitioning in. */
    @Output() readonly animationDone: EventEmitter<void> = new EventEmitter<void>();

    _animationDone = new Subject<AnimationEvent>();

    ngAfterContentInit() {

        // Mark the component for change detection whenever the content children query changes
        this._steps.changes.pipe(takeUntil(this._destroyed)).subscribe(() => this._stateChanged());

        this._animationDone.pipe(
            // This needs a `distinctUntilChanged` in order to avoid emitting the same event twice due
            // to a bug in animations where the `.done` callback gets invoked twice on some browsers.
            // See https://github.com/angular/angular/issues/24084
            distinctUntilChanged((x, y) => x.fromState === y.fromState && x.toState === y.toState),
            takeUntil(this._destroyed)
        ).subscribe(event => {
            if ((event.toState as StepContentPositionState) === 'current') {
                this.animationDone.emit();
            }
        });
    }
}

       Selector: [cdkStepper]

       Exported as: cdkStepper

2.1 CdkStepper属性

属性 类型 解释
linear: boolean @Input() 任务流是否是线性的,前一个任务完成才能进行下一个任务
selected: CdkStep @Input() 当前选中的任务
selectedIndex: number @Input() 当前选中任务的index
selectionChange: EventEmitter<StepperSelectionEvent> @Output() 选中任务改变时候的回调函数

2.2 CdkStepper方法

export declare class CdkStepper implements AfterViewInit, OnDestroy {
    ...
    /** 切换到下一个任务 */
    next(): void;
    /** 切换到上一个任务 */
    previous(): void;
    /** 重置所有的任务 */
    reset(): void;
    ...
}

关于CdkStepper的使用更加详细的任务可以参考下下文中代码链接。

三 CdkStepLabel

       指令,每个步骤需要显示的label内容,比如如下代码<ng-template cdkStepLabel>第一步</ng-template>部分就是某个任务的label。

    <cdk-step [stepControl]="frmStep1" #step1="cdkStep">
        <ng-template cdkStepLabel>第一步</ng-template>
        <form #frmStep1="ngForm">
            <input type="text" name="a" value="a"/>
        </form>
        <button style="margin: 8px" cdkStepperNext type="button">下一步</button>
    </cdk-step>

       Selector: [cdkStepLabel]

四 CdkStepperNext

       添加在button上的指令,跳到下一个任务。

       Selector: button[cdkStepperNext]

五 CdkStepperPrevious

       添加在button上的指令,跳到上一个任务。

       Selector: button[cdkStepperPrevious]

六 CdkStepHeader

       指令,每个任务的头部信息,任务指示器。


       关于cdk Stepper部分的内容好像也没啥讲的,关键点就在咱们继承CdkStepper的组件怎么来写了,怎么来管理这些workflow里面的任务。所以最最重要的在代码实现部分。为了能让大家更加直观的知道cdk Stepper怎么使用,这里我就直接写了一个非常简单的例子。有兴趣的大家可以看看例子里面是怎么做到的 https://github.com/tuacy/angular-cdk-study cdk stepper部分内容在workflow-stepper文件下面。实现效果图如下:

stepper.gif
上一篇下一篇

猜你喜欢

热点阅读