? ? ? ?cdk Stepper 讓我們能夠更好的處理類似于工作流的情況(任務(wù)分為多個步驟央星,上一步操作完成之后進(jìn)入下一步的操作钦讳,比如咱們休假申請單要經(jīng)過多個領(lǐng)導(dǎo)的審批的情況)。
? ? ? ?還是和之前cdk 里面其他功能模塊一樣,要使用Stepper 需provider CdkStepperModule的侠驯。
import {CdkStepperModule} from '@angular/cdk/stepper';
? ? ? ?cdk Stepper看起來復(fù)雜其實里面的東西不是很多脐恩。整個Stepper都是圍繞一個組件CdkStep(cdk-step)和6個指令(CdkStepper镐侯、CdkStepLabel、CdkStepperNext驶冒、CdkStepperPrevious苟翻、CdkStepHeader)來展開的。咱們上面不是說了么骗污,cdk Stepper一般用來處理多個步驟任務(wù)崇猫。這里每個任務(wù)的內(nèi)容用CdkStep組件來表示,所以有多少個步驟就會 有多少個CdkStep組件需忿。CdkStepper指令呢則是用來管理這些組件比如跳到下一步诅炉,上一步,完成等等(所以cdk Stepper使用的時候我們需要另外定義一個組件繼承自CdkStepper指令屋厘,我們可以把他當(dāng)做是工作流組件)涕烧。CdkStepperNext、CdkStepperPrevious兩個指令正好對應(yīng)上一步下一步汗洒,一般會添加在button上面包含在CdkStep組件里面议纯,因為每個步驟都可能有上一步,下一步這樣的仲翎。CdkStepLabel指令則是對每一個步驟的描述你也可以認(rèn)為是每個步驟的標(biāo)題痹扇。CdkStepHeader指令一般則是用來表示當(dāng)前進(jìn)行到哪一步了铛漓。一般也是會自定義一個組件繼承CdkStepHeader實現(xiàn)。
一 CdkStep
? ? ? ?CdkStep其實是一個組件來著鲫构。表示每個步驟的內(nèi)容浓恶。所以任務(wù)有多少步就會有多少個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組件里面的內(nèi)容對應(yīng)每個步驟的內(nèi)容结笨。
? ? ? ?Selector: cdk-step
? ? ? ?Exported as: cdkStep
1.1 CdkStep組件屬性
屬性 | 內(nèi)容 | 解釋 |
---|---|---|
ariaLabel: string | @Input('aria-label') | 添加aria-label屬性 |
ariaLabelledby: string | @Input('aria-labelledby') | 添加aria-labelledby屬性 |
completed: boolean | @Input() | 當(dāng)前步驟是否標(biāo)記為完成狀態(tài) |
editable: boolean | @Input() | 當(dāng)前步驟標(biāo)記為完成之后包晰,是否還可以回到該步驟 |
errorMessage: string | @Input() | 錯誤信息 |
hasError: boolean | @Input() | 是否有錯誤 |
label: string | @Input() | 當(dāng)前步驟對應(yīng)的label,和cdkStepLabel指令的作用是一樣的(可以簡單的把他認(rèn)為是步驟的標(biāo)題) |
optional: boolean | @Input() | 當(dāng)前步驟是否是可選的 |
state: StepState | @Input() | 當(dāng)前步驟的狀態(tài) |
stepControl: AbstractControl | @Input() | 用于驗證當(dāng)前步驟的合法性 |
content: TemplateRef<any> | 當(dāng)前步驟 試圖元素內(nèi)容 | |
interacted: false | 用戶是否看到當(dāng)前步驟內(nèi)容 | |
stepLabel: CdkStepLabel | 當(dāng)前步驟label內(nèi)容 |
1.2 CdkStep組件方法
export declare class CdkStep implements OnChanges {
...
/** 選中當(dāng)前步驟(select哪個步驟則選中那個步驟) */
select(): void;
/** 設(shè)置當(dāng)前步驟到無效狀態(tài) */
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() | 任務(wù)流是否是線性的树肃,前一個任務(wù)完成才能進(jìn)行下一個任務(wù) |
selected: CdkStep | @Input() | 當(dāng)前選中的任務(wù) |
selectedIndex: number | @Input() | 當(dāng)前選中任務(wù)的index |
selectionChange: EventEmitter<StepperSelectionEvent> | @Output() | 選中任務(wù)改變時候的回調(diào)函數(shù) |
2.2 CdkStepper方法
export declare class CdkStepper implements AfterViewInit, OnDestroy {
...
/** 切換到下一個任務(wù) */
next(): void;
/** 切換到上一個任務(wù) */
previous(): void;
/** 重置所有的任務(wù) */
reset(): void;
...
}
關(guān)于CdkStepper的使用更加詳細(xì)的任務(wù)可以參考下下文中代碼鏈接。
三 CdkStepLabel
? ? ? ?指令瀑罗,每個步驟需要顯示的label內(nèi)容胸嘴,比如如下代碼<ng-template cdkStepLabel>第一步</ng-template>部分就是某個任務(wù)的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上的指令斩祭,跳到下一個任務(wù)劣像。
? ? ? ?Selector: button[cdkStepperNext]
五 CdkStepperPrevious
? ? ? ?添加在button上的指令,跳到上一個任務(wù)摧玫。
? ? ? ?Selector: button[cdkStepperPrevious]
六 CdkStepHeader
? ? ? ?指令耳奕,每個任務(wù)的頭部信息,任務(wù)指示器诬像。
? ? ? ?關(guān)于cdk Stepper部分的內(nèi)容好像也沒啥講的屋群,關(guān)鍵點就在咱們繼承CdkStepper的組件怎么來寫了,怎么來管理這些workflow里面的任務(wù)坏挠。所以最最重要的在代碼實現(xiàn)部分谓晌。為了能讓大家更加直觀的知道cdk Stepper怎么使用,這里我就直接寫了一個非常簡單的例子癞揉。有興趣的大家可以看看例子里面是怎么做到的 https://github.com/tuacy/angular-cdk-study cdk stepper部分內(nèi)容在workflow-stepper文件下面纸肉。實現(xiàn)效果圖如下: