美文网首页
Angualr cdk 学习之 Stepper

Angualr cdk 学习之 Stepper

作者: tuacy | 来源:发表于2019-01-05 23:18 被阅读37次

           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

    相关文章

      网友评论

          本文标题:Angualr cdk 学习之 Stepper

          本文链接:https://www.haomeiwen.com/subject/wmkjrqtx.html