Ngx Mask与Ngx Formly设置初始值后标签不浮动问题
问题描述
我有一个基于Angular独立API的应用,使用ngx-formly构建表单,目前正在集成ngx-mask实现输入掩码功能。我创建了名为masked-input的自定义ngx-formly组件类型,该组件基于mat-form-field,包含mat-label和使用MatInput类的输入元素。
所有功能正常,直到通过defaultValue设置初始值时,出现标签与输入值重叠的问题(示例效果:标签覆盖在输入值上方,点击输入框后标签会恢复到正常的浮动位置)。
已尝试方案
变更检测调整:
最初怀疑是变更检测问题,尝试将组件变更检测策略改为OnPush无明显效果;在组件生命周期多个阶段调用markForCheck()和detectChanges()也无效。仅在ngOnInit()中用setTimeout包裹markForCheck()(延迟0秒)能解决问题,但这是临时方案,不适用于正式发布。输入属性调整:
测试发现添加mask属性后问题出现;给输入框设置value=" "(空格)也能解决问题,但同样属于临时方案。动画配置调整:
在可复现示例中,移除bootstrapApplication()中的provideAnimations()调用后标签显示正常,但控制台会出现大量错误,这可能是排查线索。
代码与环境
依赖版本
"@angular-architects/module-federation": "^16.0.4", "@angular/animations": "^16.2.0", "@angular/common": "^16.2.0", "@angular/compiler": "^16.2.0", "@angular/core": "^16.2.0", "@angular/forms": "^16.2.0", "@angular/material": "^16.0.0", "@angular/platform-browser": "^16.2.0", "@angular/platform-browser-dynamic": "^16.2.0", "@angular/router": "^16.2.0", "@ngx-formly/core": "^6.1.8", "@ngx-formly/material": "^6.2.2", "ngx-mask": "^16.4.2", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.13.0"
使用更新版本也能复现该问题。
系统流程
- 客户端向后端请求组件配置
- 客户端通过自定义库根据配置创建表单组件、填充数据并应用掩码
Formly组件类型配置
{ name: 'masked-input', component: MaskedInputTypeComponent, wrappers: ['form-field'] }
组件代码示例
@Component({ selector: 'masked-input', standalone: true, imports: [ MatInputModule, NgxMaskDirective, ReactiveFormsModule, FormlyModule, CommonModule ], changeDetection: ChangeDetectionStrategy.OnPush, template: ` <input matInput [formControl]="formControl" [formlyAttributes]="field" mask="{{this.mask}}" [patterns]="this.patterns ?? null" thousandSeparator="{{this.thousandSeparator ?? ' '}}" prefix="{{this.prefix ?? null}}" suffix="{{this.suffix ?? null}}" separatorLimit="{{this.separatorLimit ?? null}}" [hiddenInput]="this.hiddenInput ? this.hiddenInput : undefined" [dropSpecialCharacters]="this.dropSpecialCharacters ?? true" [showMaskTyped]="this.showMaskTyped ?? false" [allowNegativeNumbers]="this.allowNegativeNumbers ?? false" [placeHolderCharacter]="this.placeHolderCharacter ?? '_'" [clearIfNotMatch]="this.clearIfNotMatch ?? false" [leadZero]="this.leadZero ?? false" [leadZeroDateTime]="this.leadZeroDateTime ?? false" [specialCharacters]="this.specialCharacters ?? ['-','/','(',')','.',':',' ','+',',','@','[',']']" > ` }) export class MaskedInputTypeComponent extends FieldType<FieldTypeConfig> implements OnInit { label: string; mask: string | undefined; specialCharacters: string[] | undefined; dropSpecialCharacters: boolean | undefined; prefix: string | undefined; suffix: string | undefined; showMaskTyped: boolean | undefined; allowNegativeNumbers: boolean | undefined; placeHolderCharacter: string | undefined; clearIfNotMatch: boolean | undefined; thousandSeparator: string | undefined; leadZero: boolean | undefined; leadZeroDateTime: boolean | undefined; separatorLimit: number | undefined; hiddenInput: boolean | undefined; patterns: IMaskPatterns | undefined; ngOnInit(): void { const maskConfig: IMaskConfig | undefined = this.props['maskConfig'] as IMaskConfig | undefined; if (maskConfig) { this.mask = maskConfig.mask; this.specialCharacters = maskConfig.specialCharacters; this.dropSpecialCharacters = maskConfig.dropSpecialCharacters; this.prefix = maskConfig.prefix; this.suffix = maskConfig.suffix; this.showMaskTyped = maskConfig.showMaskTyped; this.allowNegativeNumbers = maskConfig.allowNegativeNumbers; this.placeHolderCharacter = maskConfig.placeHolderCharacter; this.clearIfNotMatch = maskConfig.clearIfNotMatch; this.thousandSeparator = maskConfig.thousandSeparator; this.leadZero = maskConfig.leadZero; this.leadZeroDateTime = maskConfig.leadZeroDateTime; this.separatorLimit = maskConfig.separatorLimit this.hiddenInput = maskConfig.hiddenInput; this.patterns = maskConfig.patterns as IMaskPatterns; } this.label = this.props['label'] as string; } }
更新说明
已创建可复现该问题的示例。
内容的提问来源于stack exchange,提问作者Jonathan McDonnell
相关产品推荐
相关产品推荐

