一.概述
如果希望实现一个DOM元素,双击可编辑,失去焦点不可编辑,常用的方式,是绑定dblclick事件,当事件触发,将文本内容替换为表单元素,失去焦点,再替换为文本,这种做法固然简单,但如果要操作的dom元素太多,既要添加表单元素,还要监听dblclick、blur事件,代码不可避免会变得非常繁琐
所以我采取的做法是,抽象出一个指令,将指令注册为表单控件,实现双向绑定,结合DOM的contentEditable属性,只要在DOM元素上添加该指令即可具备该能力
使用
1 | <div appCanEdit [(ngModel)]="item.value"></div> |
效果
二.实现步骤
1. 创建指令,实现 ControlValueAccessor接口
ControlValueAccessor是一个连接表单模型和视图(DOM元素)的接口,自定义的表单控件必须实现这个接口,它的作用是把 form 模型中值映射到视图中,当视图发生变化时,通知 form directives 或 form controls
1 | ({ |
2. 注册成为表单控件,将控件本身注册到DI框架成为一个可以让表单访问其值的控件
1 | ({ |
3. 通过@HostListener 为组件添加事件绑定,通过@HostBinding实现元素innerText随value而变化
当元素处于可编辑状态时,添加content-editable类样式,以便灵活控制样式
1 |
|
三.完整代码
1 | <div appCanEdit [(ngModel)]="item.value"></div> |
1 | import { Component, OnInit, Input, EventEmitter, Directive, HostListener, HostBinding, Renderer2, forwardRef } from '@angular/core'; |