
本文介绍如何在 angular 中使用 material 组件构建一个带不可编辑前缀的输入框,使默认值(如 ####)始终保留、不可删除,而用户只能在其后输入或修改后续内容,适用于标识符、编码模板等场景。
本文介绍如何在 angular 中使用 material 组件构建一个带不可编辑前缀的输入框,使默认值(如 ####)始终保留、不可删除,而用户只能在其后输入或修改后续内容,适用于标识符、编码模板等场景。
在 Angular 应用中,有时需要为输入框设置一个“只读前缀”——例如系统生成的编号模板(如 DASH-001)、固定前缀标识符(如 USR- 或 ####),该前缀必须始终存在,用户无法删除,但可在其后自由输入或编辑后续内容。原生 <input> 的 readonly 或 disabled 属性无法满足此需求(前者阻止所有输入,后者不参与表单校验且样式灰化),而 value 绑定配合事件拦截又易导致光标跳动、体验不佳。
推荐方案是视觉分离 + CSS 定位模拟前缀:将固定前缀以 <span> 形式置于 mat-form-field 内部,通过绝对定位与 padding-left 配合,使输入框内容区域自然“避开”前缀区域,从而实现语义与交互上的分离——前缀不可编辑、不参与表单控制,用户输入内容则完全由 formControlName 管理,保持响应式表单完整性。
✅ 实现步骤
- HTML 结构优化:在 mat-form-field 内添加带 class="prefix" 的 <span> 作为静态前缀,并确保 mat-label 和 input[matInput] 位置正确;
- CSS 样式定制:为前缀添加绝对定位,同时为输入框设置左内边距,避免文字重叠;
- 表单集成:formControlName 仅绑定用户可编辑部分(即实际输入值),前缀不纳入表单模型。
<mat-form-field appearance="outline" class="col-30 placeholder-prefix" id="mat-identifier">
<span class="prefix">{{ selectedIdentifier?.standardIdentifier || '####' }}</span>
<mat-label>
{{ 'columns.dashboard.identifier' | translate }}
<span *ngIf="selectedIdentifier?.mandatorieIdentifier">*</span>
</mat-label>
<input matInput
formControlName="identifier"
maxlength="255"
(input)="limitcarateres('identifier', 255, $event)">
<mat-hint *ngIf="showPackage !== true && selectedIdentifier && selectedIdentifier.tag !== 'OTHERS'">
{{ selectedIdentifier?.standardIdentifier }}{{ dataCorrespondenceForm.get('identifier').value || '' }}
</mat-hint>
</mat-form-field>? 关键 CSS(适配 Angular Material v17+ MDC 主题)
.placeholder-prefix {
.mat-mdc-form-field-input-control {
padding-left: 56px; // 为前缀预留空间,需根据字体大小微调
}
.prefix {
position: absolute;
left: 12px;
top: 29px;
font-size: 14px;
color: rgba(0, 0, 0, 0.6); // 与 label 一致的浅色
pointer-events: none; // 确保不拦截鼠标事件
z-index: 1;
}
// 聚焦时 label 上移,前缀同步上移对齐
.mat-focused & .prefix {
top: 22px;
font-size: 12px;
}
// 兼容 label 悬浮状态下的垂直对齐
.mat-mdc-form-field-infix {
display: flex;
}
}⚠️ 注意事项:
- 前缀文本(如 ####)不参与表单验证与提交,若需后端拼接完整值(如 ####123),应在提交前手动组合:
const prefix = this.selectedIdentifier?.standardIdentifier || ''; const userPart = this.dataCorrespondenceForm.get('identifier')?.value || ''; const fullValue = prefix + userPart;- 避免使用 disabled 或 readonly 属性于 <input>,否则会破坏 formControl 的响应式行为及校验链路;
- 若需支持清空按钮(<button matSuffix>),请确保点击逻辑仅清空 formControl 值,不影响前缀显示;
- 在不同屏幕尺寸下建议测试 top/left 值,必要时使用 @media 调整定位偏移。
该方案轻量、无侵入性,兼容 Angular Reactive Forms 全流程,且无需监听键盘事件或劫持输入逻辑,规避了光标错位、撤销异常等常见陷阱,是 Material 设计体系下实现“不可清除默认前缀”的推荐实践。

















