安装(文档参考版本12.1.1)
ng add @angular/cdk
添加css
@import '~@angular/cdk/overlay-prebuilt.css';
执行两个方法
<button (click)="add();add1()">Click</button>
获取焦点失去焦点
css
.box .cdk-focused{
background-color: red;
}
html
<div class="box">
<button cdkMonitorSubtreeFocus (cdkFocusChange)="add($event)">Click</button>
</div>
ts
add(e: any) { // 点击的 mouse|touch
console.log(e);
}
点击的时候焦点
添加的时候class不一样
html点击的时候添加的参数不一样, 或者class不一样
'touch' | 'mouse' | 'keyboard' | 'program' | null;
<button (click)="focusMonitor.focusVia(aaa,'mouse')">click1</button>
<div class="box">
<button #aaa>我是box</button>
</div>
ts
export class ThreeComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('aaa') aaa!: ElementRef<HTMLElement>;
constructor(
public focusMonitor: FocusMonitor,
) {
}
ngAfterViewInit() {
this.focusMonitor.monitor(this.aaa).subscribe(origin => {
console.log(origin);
})
}
ngOnDestroy() {
this.focusMonitor.stopMonitoring(this.aaa)
}
}
复制剪贴板
1
<button [cdkCopyToClipboard]="text1">复制到剪贴板</button>
text1='我是复制的内容'
2
<button (click)="copyHome()">复制到剪贴板</button>
constructor(
private clip: Clipboard
) {}
copyHome() {
this.clip.copy('我是复制的文本')
}
输入框的实用api
coerceBooleanProperty
输入的值undefined/null/'false'/false 都为 false
export function coerceBooleanProperty(value: any): boolean {
return value != null && `${value}` !== 'false';
}
undefined/null/'false'/false 都为 false
官网的案例
[disabled]="" 会传递的值就行分析
@Input()
get disabled() { return this._disabled; }
set disabled(value: any) {
this._disabled = coerceBooleanProperty(value);
}
private _disabled = false;
CoerceNumberProperty
输入数字的限制
源码
export function coerceNumberProperty(value: any): number;
export function coerceNumberProperty<D>(value: any, fallback: D): number | D;
export function coerceNumberProperty(value: any, fallbackValue = 0) {
return _isNumberValue(value) ? Number(value) : fallbackValue;
}
export function _isNumberValue(value: any): boolean {
return !isNaN(parseFloat(value as any)) && !isNaN(Number(value));
}
// 当输入不是数字,尝试parseFloat转换,然后判断isNaN检验,
// 如果不是使用默认值
CoerceNumberProperty('1.s',2)
NumberInput
export type BooleanInput = string | boolean | null | undefined;
BooleanInput
export type BooleanInput = string | boolean | null | undefined;
coerceElement
将ElementRef或Element强制转换为element。
export function coerceElement<T>(elementOrRef: ElementRef<T> | T): T {
return elementOrRef instanceof ElementRef ? elementOrRef.nativeElement : elementOrRef;
}
使用
@ViewChild('aaa') aaa!: ElementRef<HTMLElement>;
// 结果一样
ngAfterViewInit() {
console.log(this.aaa.nativeElement);
console.log(coerceElement(this.aaa));
}
SelectionModel
多选或者取消
<!-- hasValue 是否有值-->
<label nz-checkbox [nzChecked]="selection.hasValue() &&isAll()"
[nzIndeterminate]="selection.hasValue()&&!isAll()" (nzCheckedChange)="allToggle()">全选</label>
<div *ngFor="let item of dataArr">
<label nz-checkbox [(ngModel)]="item.checked" (ngModelChange)="selection.toggle(item.id)">{{item.id}}</label>
</div>
<button (click)="getArr()">查询状态</button>
export class ThreeComponent implements OnInit, OnDestroy {
// 多选框
selection = new SelectionModel<Element>(true, [])
// 数据
// 全选或者不全选
numBool = false;
indeterminate = false;
dataArr: Array<any> = [
{id: 1, checked: false},
{id: 2, checked: false},
{id: 3, checked: false},
{id: 4, checked: false},
]
// 全选
isAll() {
const numSelected = this.selection.selected.length;
const DateNum = this.dataArr.length;
return numSelected === DateNum;
}
// 切换点击全选的
allToggle(): void {
if (this.isAll()) {
this.selection.clear()
this.dataArr.forEach(row => {
row.checked = false;
})
} else {
this.dataArr.forEach(row => {
row.checked = true;
this.selection.select(row.id)
})
}
}
getArr() {
// 拿到查询数组
console.log(this.selection.selected);
}
}
cdkDrag 拖拽
demo1, 单个数组拖拽
<ul cdkDropList (cdkDropListDropped)="dropClick($event)">
<li *ngFor="let item of textArr" cdkDrag>{{item.text}}</li>
</ul>
========================
textArr = [
{text: '11111111111111'},
{text: '22222222222222'},
{text: '33333333333333'},
{text: '44444444444444'},
{text: '55555555555555'},
]
dropClick($event: any) {
moveItemInArray(this.textArr, $event.previousIndex, $event.currentIndex)
}
自定义拖动预览(cdkDragPreview)
<div cdkDropList (cdkDropListDropped)="drop($event)">
<div *ngFor="let movie of movies" cdkDrag>
{{movie.title}}
<img *cdkDragPreview [src]="movie.poster" [alt]="movie.title">
</div>
</div>
movies = [
{
title: 'Episode V - The Empire Strikes Back',
poster: 'https://upload.wikimedia.org/wikipedia/en/3/3c/SW_-_Empire_Strikes_Back.jpg'
},
{
title: 'Episode VI - Return of the Jedi',
poster: 'https://upload.wikimedia.org/wikipedia/en/b/b2/ReturnOfTheJediPoster1983.jpg'
},
{
title: 'Episode VII - The Force Awakens',
poster: 'https://upload.wikimedia.org/wikipedia/en/a/a2/Star_Wars_The_Force_Awakens_Theatrical_Poster.jpg'
},
{
title: 'Episode VIII - The Last Jedi',
poster: 'https://upload.wikimedia.org/wikipedia/en/7/7f/Star_Wars_The_Last_Jedi.jpg'
},
{
title: 'Episode IX – The Rise of Skywalker',
poster: 'https://upload.wikimedia.org/wikipedia/en/a/af/Star_Wars_The_Rise_of_Skywalker_poster.jpg'
}
];
drop(event: CdkDragDrop<{title: string, poster: string}[]>) {
moveItemInArray(this.movies, event.previousIndex, event.currentIndex);
}
自定义拖动占位符(*cdkDragPlaceholder)
<div cdkDropList (cdkDropListDropped)="drop($event)">
<div *ngFor="let movie of movies" cdkDrag>
<div *cdkDragPlaceholder style="20px;height: 20px;"></div>
{{movie.title}}
<!-- <img *cdkDragPreview [src]="movie.poster" [alt]="movie.title">-->
</div>
</div>
设置方向
水平 垂直
type DropListOrientation = 'horizontal' | 'vertical';
<div cdkDropList (cdkDropListDropped)="drop($event)" cdkDropListOrientation="horizontal" style="display: flex">
<div *ngFor="let movie of movies" cdkDrag style=" 200px;">
<div *cdkDragPlaceholder style="200px;"></div>
{{movie.title}}
</div>
</div>
限制范围(cdkDragBoundary)
限制反向(cdkDragLockAxis)
<div class="aaa">
<div class="bbb" cdkDrag cdkDragBoundary=".aaa" cdkDragLockAxis = "x"></div>
</div>
demo2, 两个数组拖拽
<ul cdkDropList
#aa="cdkDropList"
[cdkDropListData]="textArr"
[cdkDropListConnectedTo]="[bb]"
(cdkDropListDropped)="dropClick($event)">
<li *ngFor="let item of textArr" cdkDrag>{{item.text}}</li>
</ul>
<hr>
<ul cdkDropList
#bb="cdkDropList"
[cdkDropListData]="textArrTwo"
[cdkDropListConnectedTo]="[aa]"
(cdkDropListDropped)="dropClick($event)">
<li *ngFor="let item of textArrTwo" cdkDrag>{{item.text}}</li>
</ul>
textArr = [
{text: '11111111111111'},
{text: '22222222222222'},
{text: '33333333333333'},
{text: '44444444444444'},
{text: '55555555555555'},
]
textArrTwo = [
{text: 'aaaaaaaaaaaaaa'},
{text: 'bbbbbbbbbbbbbb'},
{text: 'cccccccccccccc'},
{text: 'eeeeeeeeeeeeee'},
{text: 'ffffffffffffff'},
]
dropClick(event: CdkDragDrop<any[]>) {
if (event.previousContainer === event.container) {
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
} else {
transferArrayItem(event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex);
}
}
上面那种形式, 可以进行简化
<div cdkDropListGroup>
<ul cdkDropList
[cdkDropListData]="textArr"
(cdkDropListDropped)="dropClick($event)">
<li *ngFor="let item of textArr" cdkDrag>{{item.text}}</li>
</ul>
<hr>
<ul cdkDropList
[cdkDropListData]="textArrTwo"
(cdkDropListDropped)="dropClick($event)">
<li *ngFor="let item of textArrTwo" cdkDrag>{{item.text}}</li>
</ul>
</div>
手柄自定义拖动区域
<div class="aaa" cdkDrag>
<div class="bbb" cdkDragHandle>点我</div>
</div>
.aaa{
200px;
height: 200px;
background-color: #783ce8;
.bbb{
40px;
height: 40px;
background-color: #af0b0b;
}
}
检测屏幕的变化
export class ThreeComponent implements OnInit, OnDestroy {
destroyed = new Subject<void>();
constructor(private breakpoint:BreakpointObserver) {
breakpoint.observe([
// (max- 599.98px)
Breakpoints.XSmall,
// (min- 600px) and (max- 959.98px)
Breakpoints.Small,
// (min- 960px) and (max- 1279.98px)
Breakpoints.Medium,
// (min- 1280px) and (max- 1919.98px)
Breakpoints.Large,
// (min- 1920px)
Breakpoints.XLarge,
]).pipe(takeUntil(this.destroyed)).subscribe(result=>{
for (let [key,value] of Object.entries(result.breakpoints)){
if(value){
console.log(key);
}
}
})
}
ngOnDestroy() {
this.destroyed.next()
}
}
检查当前视口的大小
breakpointObserver.isMatched('(max- 599px)')
检测ng-content 的内容发生变化
添加模块
import {ObserversModule} from '@angular/cdk/observers';
上一个小案例
父
<button (click)="clickNum()">Click++</button>
<app-six>
<h1>{{num}}</h1>
</app-six>
num=1;
clickNum(){
++this.num
}
子
<div (cdkObserveContent)="clickChanged()">
<ng-content></ng-content>
</div>
clickChanged() {
console.log('执行了');
}
弹框
demo1
<button (click)=" isOpen=!isOpen" cdkOverlayOrigin #box="cdkOverlayOrigin">Click 1</button>
<ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]="box" [cdkConnectedOverlayOpen]="isOpen">
<div>我是一个div</div>
</ng-template>
isOpen = false;
使用添加弹框组件的形式
<button (click)="open1()">点击我</button>
export class ThreeComponent implements OnInit, OnDestroy {
overlayRef!: OverlayRef;
fileComponent!: ComponentPortal<SixComponent>;
constructor(public overlay: Overlay,) {
}
isOpen = false;
ngOnInit(): void {
// 容器
this.overlayRef = this.overlay.create()
// 添加容器的组件
this.fileComponent = new ComponentPortal(SixComponent);
//添加最外层的class
this.overlayRef.addPanelClass("aaaa");
}
open1() {
this.isOpen = !this.isOpen;
if (this.isOpen) {
this.overlayRef.attach(this.fileComponent);
} else {
this.overlayRef.detach()
}
}
ngOnDestroy() {
this.overlayRef.dispose()
}
}
可以用发布订阅的形式传递数据