div内ng-select必填校验红色高亮样式不生效问题
ng-select指定容器内校验样式不生效问题
需求说明
- 实现ng-select组件的必填校验交互,对齐mat-form-field的校验行为
- 触发校验错误(输入框被触碰且未选有效值、mat-error展示)时,给对应div内的ng-select添加红色底部边框,同时将占位符、下拉箭头改为红色
- 要求样式仅作用于指定id为
div1的容器内部元素,不影响全局其他ng-select
问题复现代码
HTML模板
<form (fromgroup)="form"> <div id="div1"> <ng-select formcontrolName="gender" [(ng-model)]=names required > <ng-template let-items="$items"> <input type=checkbox select All /> </ng-template> </ng-select> <mat-error class="ng-select-error ng-select-required" *ngif="!form.controls["gender"].valid&& form.controls["gender"].touched" > </mat-error> </div> </form>
SCSS样式
.ng-select-required{ #div1 .ng-select-container {border-bottom: solid 1px red } #div1 .ng-placeholder {color:red} #div1 .ng-arrow {color:red} } .ng-select-error{ font-size:12px }
样式不生效原因
- 选择器逻辑写反:当前样式逻辑是查找
.ng-select-required元素后代里#div1下的ng-select相关元素,但.ng-select-required是加在mat-error上的,mat-error本身是ng-select的兄弟节点,#div1是它的父元素,选择器路径完全不成立,匹配不到目标节点 - Angular样式隔离限制:默认视图封装模式下,组件样式只能作用于当前组件自身模板的原生节点,ng-select是第三方组件,其内部生成的容器、占位符、箭头节点属于子组件内部元素,普通选择器无法穿透组件封装边界命中这些节点
- 模板语法错误:模板存在多处Angular语法写法问题,会直接导致表单绑定、结构指令解析失败:
- 表单组绑定写法错误:
(fromgroup)="form"是事件绑定写法,响应式表单应该用属性绑定[formGroup]="form" - 表单控件名写法错误:
formcontrolName不符合小驼峰规范,正确写法为formControlName - 双向绑定写法错误:
[(ng-model)]是AngularJS的旧写法,Angular中正确写法为[(ngModel)],且和响应式表单formControlName同时使用时会造成重复绑定冲突 - 结构指令写法错误:
*ngif不符合小驼峰规范,正确写法为*ngIf - 属性值引号嵌套错误:
*ngIf判断条件内直接用双引号嵌套双引号,会导致模板解析截断报错,内部引号应该改用单引号
- 表单组绑定写法错误:
- 类名挂载逻辑错误:错误状态类
.ng-select-required直接加在了mat-error上,没有和校验状态联动挂载到ng-select的共同父容器上,无法稳定联动控制ng-select的错误样式
修复方案
- 修正所有模板语法错误,将错误状态类动态绑定到外层
div1上,仅当校验不通过且控件被触碰时才添加错误类<form [formGroup]="form"> <div id="div1" [class.ng-select-error]="!form.controls['gender'].valid && form.controls['gender'].touched"> <ng-select formControlName="gender" required > <ng-template let-items="$items"> <input type="checkbox" selectAll /> </ng-template> </ng-select> <mat-error *ngIf="!form.controls['gender'].valid && form.controls['gender'].touched"> 请选择性别 </mat-error> </div> </form> - 修正SCSS选择器逻辑,使用
::ng-deep穿透第三方组件样式隔离,配合:host将样式限制在当前组件内,避免污染全局样式:host { .ng-select-error { font-size: 12px; ::ng-deep { .ng-select-container { border-bottom: solid 1px red; } .ng-placeholder { color: red; } .ng-arrow { color: red; } } } }
注意:
::ng-deep虽然在Angular当前版本被标记为废弃,但依然是穿透第三方组件样式最通用的方案,只要配合:host控制作用域就不会造成全局样式污染
内容的提问来源于stack exchange,提问作者AMDI
相关产品推荐
相关产品推荐

