如何屏蔽自定义控件中的值
How to mask value in custom control
如何在输入中显示转换后的值(例如“1(234)567-890”),而没有转换后的值('1234567890')?
是否可以为 maskInputEl
和 maskInput
设置分隔值?
我有模板:
<input #maskInputEl class="spacer" [type]="type"
[formControl]="maskInput"/>
和自定义组件:
export class MaskInputComponent implements ControlValueAccessor, OnInit, OnDestroy {
@ViewChild('maskInputEl') public maskInputEl: ElementRef;
@Input() public mask: any[];
public maskInput = new FormControl();
private _oldValue: string = '';
public ngOnInit(): void {
this.maskInput.valueChanges
.subscribe((value: string) => {
let valid = this.isValidValueByMask(value, this.mask);
if (valid) {
this._oldValue = value;
} else {
value = this._oldValue;
}
this._onChangeCallback(value);
this.onChange.emit(value);
this.maskInputEl.nativeElement.value = value;
},
(err) => console.warn(err)
);
}
public toggleActive(value) {
//
}
public registerOnChange(fn: any): void {
this._onChangeCallback = fn;
}
public registerOnTouched(fn: any): void {
this._onTouchedCallback = fn;
}
public _onChangeCallback: Function = (_: any) => {
//
}
public _onTouchedCallback: Function = (_: any) => {
//
}
public makeActive() {
this.maskInputEl.nativeElement.focus();
}
public writeValue(value: string): void {
this.maskInput.setValue(value);
}
public ngOnDestroy(): void {
//
}
private isValidValueByMask(value: string, mask: RegExp[]): boolean {
//
}
}
是的,这是可能的。我为我自己的项目做了类似的事情,我想创建一个 MoneyFieldComponent
返回以美分为单位的值,但允许用户以美元和美分输入他们的货币价值。
基本概念是您的组件必须存储原始值,但是,您在文本字段中显示格式化值。此外,当用户与您的文本字段交互时,您会使用原始值更新组件的 'inner value'。
请注意,您不应使用 ngModel 来更新您的文本字段 - ngModel 具有一些在这些情况下会造成严重破坏的异步行为 - 您可以使用原始 javascript(或者在我的情况下,我使用了 FormControl
).
样本:
@Component({
selector: 'ec-money-field',
template: `
<md-input-container *ngIf="editMode">
<input #input mdInput class="value" type="text"
(input)="updateInnerValue(input.value)"
(blur)="formatTextValue()"
[formControl]="control" />
</md-input-container>
`,
providers: [
{provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => MoneyFieldComponent)},
]
})
export class MoneyFieldComponent implements OnInit, ControlValueAccessor {
private valueInCents = 0;
control = new FormControl(0);
private onChange: Function = (_: any) => {};
private onTouch: Function = (_: any) => {};
constructor() { }
@Input()
get value(): number {
return this.valueInCents;
};
// if you update the component by using the value property,
// propagate that change to the text field
set value(newValueInCents: number) {
this.valueInCents = newValueInCents;
this.control.setValue(centsToDollars(newValueInCents));
}
ngOnInit() {
}
// convert the masked value - i.e. what the user types
// into the actual numerical value that will be stored
// You'll have to provide your own conversion function
// to convert the user typing 1(855) 555 1234 to 1865551234
updateInnerValue(dollarValueString: string) {
this.valueInCents = dollarsToCents(dollarValueString);
this.onChange(this.valueInCents);
}
formatTextValue() {
this.value = this.value;
}
writeValue(newValue: number): void {
this.value = newValue;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
}
请注意,以上是该组件的简化版本。 The full version can be found on Github.
如何在输入中显示转换后的值(例如“1(234)567-890”),而没有转换后的值('1234567890')?
是否可以为 maskInputEl
和 maskInput
设置分隔值?
我有模板:
<input #maskInputEl class="spacer" [type]="type"
[formControl]="maskInput"/>
和自定义组件:
export class MaskInputComponent implements ControlValueAccessor, OnInit, OnDestroy {
@ViewChild('maskInputEl') public maskInputEl: ElementRef;
@Input() public mask: any[];
public maskInput = new FormControl();
private _oldValue: string = '';
public ngOnInit(): void {
this.maskInput.valueChanges
.subscribe((value: string) => {
let valid = this.isValidValueByMask(value, this.mask);
if (valid) {
this._oldValue = value;
} else {
value = this._oldValue;
}
this._onChangeCallback(value);
this.onChange.emit(value);
this.maskInputEl.nativeElement.value = value;
},
(err) => console.warn(err)
);
}
public toggleActive(value) {
//
}
public registerOnChange(fn: any): void {
this._onChangeCallback = fn;
}
public registerOnTouched(fn: any): void {
this._onTouchedCallback = fn;
}
public _onChangeCallback: Function = (_: any) => {
//
}
public _onTouchedCallback: Function = (_: any) => {
//
}
public makeActive() {
this.maskInputEl.nativeElement.focus();
}
public writeValue(value: string): void {
this.maskInput.setValue(value);
}
public ngOnDestroy(): void {
//
}
private isValidValueByMask(value: string, mask: RegExp[]): boolean {
//
}
}
是的,这是可能的。我为我自己的项目做了类似的事情,我想创建一个 MoneyFieldComponent
返回以美分为单位的值,但允许用户以美元和美分输入他们的货币价值。
基本概念是您的组件必须存储原始值,但是,您在文本字段中显示格式化值。此外,当用户与您的文本字段交互时,您会使用原始值更新组件的 'inner value'。
请注意,您不应使用 ngModel 来更新您的文本字段 - ngModel 具有一些在这些情况下会造成严重破坏的异步行为 - 您可以使用原始 javascript(或者在我的情况下,我使用了 FormControl
).
样本:
@Component({
selector: 'ec-money-field',
template: `
<md-input-container *ngIf="editMode">
<input #input mdInput class="value" type="text"
(input)="updateInnerValue(input.value)"
(blur)="formatTextValue()"
[formControl]="control" />
</md-input-container>
`,
providers: [
{provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => MoneyFieldComponent)},
]
})
export class MoneyFieldComponent implements OnInit, ControlValueAccessor {
private valueInCents = 0;
control = new FormControl(0);
private onChange: Function = (_: any) => {};
private onTouch: Function = (_: any) => {};
constructor() { }
@Input()
get value(): number {
return this.valueInCents;
};
// if you update the component by using the value property,
// propagate that change to the text field
set value(newValueInCents: number) {
this.valueInCents = newValueInCents;
this.control.setValue(centsToDollars(newValueInCents));
}
ngOnInit() {
}
// convert the masked value - i.e. what the user types
// into the actual numerical value that will be stored
// You'll have to provide your own conversion function
// to convert the user typing 1(855) 555 1234 to 1865551234
updateInnerValue(dollarValueString: string) {
this.valueInCents = dollarsToCents(dollarValueString);
this.onChange(this.valueInCents);
}
formatTextValue() {
this.value = this.value;
}
writeValue(newValue: number): void {
this.value = newValue;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
}
请注意,以上是该组件的简化版本。 The full version can be found on Github.