组件是一种带模版的指令。指令是超级。
结构型指令(改变布局)和属性型指令(改变外观和行为)。
Renderer2和ElementRef
Angular不提倡直接操作DOM
对于DOM的操作应该通过Renderer2进行。
ElementRef是指向DOM元素的引用
拖拽指令实例
1、新建directive module
$ ng g m directive
CREATE src/app/directive/directive.module.ts (193 bytes)
2, 在指令文件夹下的drag-drop文件夹里新建一个drag和一个drop
$ ng g d directive/drag-drop/drag
$ ng g d directive/drag-drop/drop
3,改一下selector
selector: '[appDrag]'改为
selector: '[app-draggable]'
selector: '[appDrop]'改为
selector: '[app-droppable]'
4,在SharedModule中导入DirectiveModule
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { MaterialModule } from "../material/material.module";
import { ConfirmDialogComponent } from "./confirm-dialog/confirm-dialog.component";
import { DirectiveModule } from '../directive/directive.module';
@NgModule({
imports: [CommonModule, MaterialModule, DirectiveModule],
exports: [CommonModule, MaterialModule, DirectiveModule],
declarations: [ConfirmDialogComponent],
entryComponents: [ConfirmDialogComponent]
})
export class SharedModule { }
5,把DirectiveModule中多余的CommonDodule删掉,然后把Drag和Drop两个指令导出
import { NgModule } from '@angular/core';
import { DragDirective } from './drag-drop/drag.directive';
import { DropDirective } from './drag-drop/drop.directive';
@NgModule({
declarations: [DragDirective, DropDirective],
exports: [DragDirective, DropDirective],
})
export class DirectiveModule { }
6,drag指令
使用@HostListener监听dragstart事件和dragend事件。
使用ElementRef获取元素。
使用Renderer2修改样式。
draggedClass是一个输入型参数。所以selector 为selector: '[app-draggable][draggedClass]'。
app-draggable设置为true就可以拖拽,为false不可拖拽。
private _isDraggble = false; set isDraggable(value){ this._isDraggble=value; } get isDraggable(){ return this._isDraggble; }
给set方法加上@Input(app-draggable)。 这样在调用app-draggable= "true"的时候会调用set方法。
import { Directive, HostListener, Host, ElementRef, Renderer2, Input } from '@angular/core';
@Directive({
selector: '[app-draggable][draggedClass]'
})
export class DragDirective {
private _isDraggble = false;
@Input('app-draggable')
set isDraggable(value:boolean){
this._isDraggble=value;
this.rd.setAttribute(this.el.nativeElement,'draggable',`${value}`);
}
get isDraggable(){
return this._isDraggble;
}
@Input()
draggedClass:string;
constructor(private el:ElementRef, private rd:Renderer2) { }
@HostListener('dragstart', ['$event'])
ondragstart(ev:Event){
//判断drag元素是不是指令应用的元素发起的
if(this.el.nativeElement===ev.target){
this.rd.addClass(this.el.nativeElement, this.draggedClass);//往el上增加一个class
}
}
@HostListener('dragend', ['$event'])
ondragend(ev:Event){
if(this.el.nativeElement===ev.target){
this.rd.removeClass(this.el.nativeElement, this.draggedClass);
}
}
}
在task-item组件中使用
//红色dash虚线半透明
.drag-start { opacity: 0.5; border: #ff525b dashed 2px; }
<mat-list-item class="container" [@item]="widerPriority" [ngClass]="{ 'priority-normal':item.priority===3, 'priority-important':item.priority===2, 'priority-emergency':item.priority===1 }" [app-draggable]="true" [draggedClass]=" 'drag-start' " (click)="onItemClick()"> ...... </mat-list-item>
7,drop指令
drop要监听dragenter,dragover,dragleave,drop四个事件。
需要改变自己的css。即拖放区域的css。变暗。
import { Directive, HostListener, ElementRef, Renderer2, Input } from '@angular/core';
@Directive({
selector: '[app-droppable][dragEnterClass]'
})
export class DropDirective {
@Input()
dragEnterClass:string;
constructor(private el:ElementRef, private rd:Renderer2) { }
@HostListener('dragenter', ['$event'])
onDragEnter(ev:Event){
//判断drag元素是不是指令应用的元素发起的
if(this.el.nativeElement===ev.target){
this.rd.addClass(this.el.nativeElement, this.dragEnterClass);//往el上增加一个class
}
}
@HostListener('dragover', ['$event'])
onDragOver(ev:Event){
//判断drag元素是不是指令应用的元素发起的
if(this.el.nativeElement===ev.target){
}
}
@HostListener('dragleave', ['$event'])
onDragLeave(ev:Event){
//判断drag元素是不是指令应用的元素发起的
if(this.el.nativeElement===ev.target){
this.rd.removeClass(this.el.nativeElement, this.dragEnterClass);//往el上增加一个class
}
}
@HostListener('drop', ['$event'])
onDrop(ev:Event){
//判断drag元素是不是指令应用的元素发起的
if(this.el.nativeElement===ev.target){
this.rd.removeClass(this.el.nativeElement, this.dragEnterClass);//往el上增加一个class
}
}
}