角度验证器:我可以根据其验证器在样式元素中添加样式吗? [英] Angular Validators: Can I add styling to form elements based on their validators?

查看:86
本文介绍了角度验证器:我可以根据其验证器在样式元素中添加样式吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将Angular与Forms版本4.1.0和Material版本2.0.0-beta.8一起使用.我有一些字段需要根据存储在数据库表中的配置标记为必填字段,因此所需的特定字段可以根据该配置进行更改,并且在开发时未知.我正在根据该配置在表单控件上动态设置Validators.required,并且一切正常(例如,如果您在访问它们后将其留空,则相应的字段将变为红色).

I'm using Angular with Forms version 4.1.0 and Material version 2.0.0-beta.8. I have fields that need to be marked as required based on a configuration stored in a database table, so the specific fields that are required can change depending on that configuration and are not known at development time. I am dynamically setting Validators.required on my form controls based on that configuration, and that is all working fine (i.e. the appropriate fields are turning red if you leave them blank after visiting them).

但是,我还要求在所有必填字段的标签后加上星号.我有CSS可以基于HTML的"required"属性来执行此操作,但是不幸的是,Angular不会仅基于已将Validator.required应用于该字段的情况下将此属性(或我可以看到的任何类)应用于字段.验证器在无效时在其上放置ng-invalid类,但在有效或未被修改时不会保留任何东西.

However, I also have a requirement to mark all required fields with an asterisk after their labels. I have the CSS to do this based on the HTML "required" attribute, but unfortunately, Angular does not apply this attribute (or any class that I can see) to a field simply based on it having Validator.required applied to it. The validator puts an ng-invalid class on it while it's invalid, but nothing that persists when it's either valid or untouched.

有什么方法可以使验证器自动应用属性或类?也许通过扩展Validators.required或以其他方式创建自定义验证器?出于绝望,我求助于在控制器中创建一个isRequired(fieldName)方法,并用[required]="isRequired('fieldName')标记每个字段,以防万一在将来的配置中需要它并且可以使用,但是它确实笨拙并且易于随着新屏幕的开发不断被遗忘.

Is there any way to have the validator apply an attribute or class automatically? Maybe by extending Validators.required or otherwise creating a custom validator? Out of desperation, I've resorted to creating an isRequired(fieldName) method in my controller and marking every single field with [required]="isRequired('fieldName') just in case it becomes required in a future configuration, and it works, but it's really unwieldy and prone to being forgotten as development of new screens continues.

我对Angular还是很陌生,所以我以前从未创建过自定义验证器.实际上,我怀疑这很普遍,以至于将:: after CSS包含在Angular的样式中是一个简单的调整.任何指导将不胜感激!

I'm fairly new to Angular, so I've never created a custom validator before. In fact I suspect that this is common enough that it's some simple tweak to include the ::after CSS in Angular's styling. Any guidance would be greatly appreciated!

已编辑以提供我所拥有的示例:

Edited to provide an example of what I have:

<div>
  <form [formGroup]="formGroup">
    <md-input-container>
      <input mdInput type="text" placeholder="name" formControlName="name">
    <md-input-container>
    <!-- more inputs here -->
  </form>
</div>

在我的控制器中:

generateValidators(formGroup: FormGroup) {
  // Go get the database configuration for which fields should have
  // validators, then apply appropriate validators
  Object.keys(this.formGroup.controls).forEach(fieldName) => {
    let validators = [];
    if(database configuration indicates this field is required) {
      validators.push(Validators.required);
    }
    if(database configuration indicates this field has a max length) {
      validators.push(Validators.maxLength(length));
    }
    // etc.
    formGroup.controls[fieldName].setValidators(validators);
  }
}

所有这些都成功地将Validators.required应用于数据库中标记为必填的字段,并且当用户未能填写时,它们的行为与预期的一样.但这不会添加HTML的"required"属性,即如何使用CSS将星号添加到标签.我需要以某种方式标记添加有Validators.required的字段,以便可以通过添加"required"属性或添加可以在CSS中使用的已知类来使用CSS应用星号.像这样:

All of this successfully applies Validators.required to the fields marked as required in the database, and they behave as expected when the user fails to fill them in. But that doesn't add the HTML "required" attribute, which is how I'm adding the asterisk to the label with CSS. I need to somehow mark the fields that get a Validators.required attached to them so that I can use the CSS to apply the asterisk, either by adding the "required" attribute or by adding a known class that I can use in my CSS. Something like this:

.required:after { content:" *"; }

作为一种解决方法,我在控制器中创建了isRequired(string)方法,以按字段名称查找数据库配置,并按如下方式更新我的HTML:

As a workaround, I've created an isRequired(string) method in my controller to go look up the database configuration by field name, and updated my HTML like this:

<input mdInput type="text" placeholder="name" formControlName="name" 
       [required]="isRequired('name')">

它可以工作,但不是很干净,需要所有其他开发人员都遵守;而添加验证器的代码位于所有组件都已经看到并使用它的公共位置.我还可以更新generateValidators()方法,以在将Validators.required推送到验证器列表的同时添加一个类或属性(如果有人知道如何执行此操作).我愿意接受建议.

It works, but it's not very clean and requires all the other developers to adhere to this; whereas the code that adds the validators is in a common location where all components already see and use it. I could also update the generateValidators() method to add a class or attribute at the same time it pushes Validators.required onto the validators list, if someone knows how to do that. I'm open to suggestions.

推荐答案

建议您创建一个知道您的逻辑并将其应用于标签的指令.该指令可以添加或删除星号.我在项目中做过相同类型的事情,并且效果很好.

Suggest you create a directive that knows your logic and apply that to the label. That directive can add or remove the asterisk. I did the same type of thing in my project and it works well.

    private addRequiredIndicator(): void {
        // <span id="xxx">
        //     <sup class="requiredIndicator">*</sup>
        // </span>

        const sup = this.renderer.createElement('sup') as HTMLElement
        sup.className = "requiredIndicator"

        const star = this.renderer.createText('*')
        this.renderer.appendChild(sup, star)

        const span = this.renderer.createElement('span') as HTMLSpanElement
        span.id = this.id

        const nbsp = this.renderer.createText(' ')
        this.renderer.appendChild(span, nbsp)

        this.renderer.appendChild(span, sup)

        const me = this.el.nativeElement as HTMLElement

        this.renderer.insertBefore(this.el.nativeElement, span, me.firstChild)
    }

    private removeRequiredIndicator(): void {
        const me = this.el.nativeElement as HTMLElement
        if (!me) {
            return
        }

        const elem = me.querySelector(`[id='${this.id}']`)
        if (elem) {
            me.removeChild(elem)
        }
    }

这篇关于角度验证器:我可以根据其验证器在样式元素中添加样式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆