如何在自定义控件中屏蔽值
Posted
技术标签:
【中文标题】如何在自定义控件中屏蔽值【英文标题】:How to mask value in custom control 【发布时间】:2017-10-05 03:51:28 【问题描述】:如何在输入中显示转换后的值(例如“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
//
【问题讨论】:
【参考方案1】:是的,这是可能的。我为自己的项目做了类似的事情,我想创建一个MoneyFieldComponent
,它返回一个以美分为单位的值,但允许用户以美元和美分输入他们的货币价值。
基本概念是您的组件必须存储原始值,但是,您在文本字段中显示格式化的值。此外,当用户与您的文本字段交互时,您会使用原始值更新组件的“内部值”。
请注意,您不应该使用 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.
【讨论】:
我需要相反的,即用户输入清除数据并使用掩码输入转换该数据 但您仍然存储“清除数据”对吗?如果是这样,这是相同的基本概念 - 在用户键入后,您使用格式化值更新 formField,但您将实际值存储在组件中。如果您仅将 formField 更新为模糊时的格式化值,则更容易实现 - 尝试在每个输入事件上执行此操作似乎并不能提供良好的用户体验 - 但如果您尝试提供输入掩码,那么您别无选择,只能更新输入事件的格式化值。如果您遇到问题,我可以更新示例代码以上是关于如何在自定义控件中屏蔽值的主要内容,如果未能解决你的问题,请参考以下文章
如何让其他控件在自定义控件中看到 DataTables 的集合?