Ari*_*ael 7 angular2-forms angular2-template angular
我创建了一个自定义控件,我以编程方式为其提供值,因为它是一个基于cropper.js 的图像编辑器,用户通过普通文件输入“上传”图像,然后我使用文件 API 将图像分配给我的自定义控件.
这是代码(为了可读性,我删除了一些cropper.js特定的代码)
import {
Component,
OnInit,
ViewChild,
ElementRef,
ViewEncapsulation,
forwardRef
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import * as Cropper from 'cropperjs';
import { Photo } from '../entities/photo';
@Component({
selector: 'image-edit',
templateUrl: 'image-edit.component.html',
styleUrls: [
'image-edit.component.scss',
'../../../node_modules/cropperjs/dist/cropper.min.css'
],
encapsulation: ViewEncapsulation.None,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ImageEditComponent),
multi: true
}
]
})
export class ImageEditComponent implements OnInit, ControlValueAccessor {
get value() {
return this.cropperImage.nativeElement.src;
}
set value(v: string) {
this.cropperImage.nativeElement.src = v;
}
public onTouch: () => void;
public onChange: (_: any) => void;
@ViewChild('cropperImage')
private cropperImage: ElementRef;
private isDisabled: boolean;
// cropper.js
private cropper: Cropper;
private cropperOptions: Cropper.CropperOptions = {};
public ngOnInit(): void {
// init cropper.js
}
public writeValue(obj: any): void {
if (obj) {
this.value = obj;
this.initializeCropperOrReplaceImage();
}
}
public registerOnChange(fn: any): void {
this.onChange = fn;
}
public registerOnTouched(fn: any): void {
this.onTouch = fn;
}
public setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
}
private initializeCropperOrReplaceImage(): void {
if (!this.isCropperInitialized) {
this.cropper = new Cropper(this.cropperImage.nativeElement, this.cropperOptions);
this.isCropperInitialized = true;
}
else {
this.cropper.replace(this.cropperImage.nativeElement.src);
}
URL.revokeObjectURL(this.cropperImage.nativeElement.src);
}
}
Run Code Online (Sandbox Code Playgroud)
这是模板
<image-edit [hidden]="!photo.data" #photoData="ngModel" name="photoData" [(ngModel)]="photo.data" validateMinImageDimensions minWidth="300" minHeight="400">
</image-edit>
Run Code Online (Sandbox Code Playgroud)
不幸的是,我的控制从来没有脏过或接触过。我试图扩展 AbstractForm 并自己设置脏,但它没有用。它仍然不脏,没有受到影响。
任何想法我做错了什么?
编辑
我删除了对onTouch和onChangein的调用,writeValue因为根据@n00dl3 的回答和评论(参见那里),这不是一个好的解决方案。
您永远不会调用this.onTouch()您的组件,因此您的输入不能被标记为未触碰或脏....
所以澄清一下,this.onTouch()当您认为数据已被用户(而不是模型)更改时,您需要手动调用,因此您应该避免onTouch在writeValue方法内部调用。
相反,您应该监听您的用户在处理(不一定更改)您正在处理的值(可能只是在关注常规input元素之后)时可能触发的最终事件。
我想有一种方法可以知道用户在初始化选项中Cropper像传递complete回调一样裁剪了库中的图像。您需要onTouch从此回调中调用该方法,或者在您认为应将输入标记为已触摸时调用该方法(可能单击图像,甚至只是将其悬停)。