* ngIf阻止表单验证

时间:2017-06-27 08:30:21

标签: angular conditional-statements

你好我在这个问题上被封了几天

我向你解释我有一个输入或我根据某些条件应用一条消息但是我有另一个条件,如果它是一个多线文本使用textarea如果它是内联使用输入

当我在输入中设置条件* ngIf =“!multiline”时出现问题我收到错误消息:

无法读取未完成的属性“错误”

我已经应用了一些东西,我已经在div中封装了我的输入,包括我的条件,因此我添加了myModel&& myModel.error以便初始化对象

没有效果

如果有人有我感兴趣的解决方案

这是我的代码:

import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ElementRef,
  forwardRef,
  Input,
  OnInit,
  ViewChild
} from '@angular/core'
import {
  ControlValueAccessor,
  NG_VALUE_ACCESSOR
} from '@angular/forms'
@Component({
  selector: 'mae-input',
  templateUrl: './input.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => InputComponent),
      multi: true
    }
  ],
  host: {
    class: 'input-form'
  }
})
export class InputComponent implements OnInit, ControlValueAccessor {

  @Input() theme: string = 'material' // 'material' or 'block' or 'inline'
  @Input() minlength: number
  @Input() maxlength: number
  @Input() min: number
  @Input() max: number
  @Input() pattern: string
  // tslint:disable-next-line:no-reserved-keywords
  @Input() type: string
  @Input() autocomplete: string
  @Input() required
  @Input() disabled
  @Input() readonly
  @Input() multiline: boolean
  @Input() withCharCount: boolean
  @Input() label: string
  @Input() name: string
  @Input() placeholder: string
  @Input() help: string
  @Input() hint: string
  @Input() bg: string
  @Input() color: string
  @Input() borderColor: string
  @Input() labelColor: string
  @Input() myModel: any

  ValidationHints = {

    required: ' Please fill out this field.',
    minlength: ' Field must be at least 3 characters long.',
    maxlength: ' Field cannot be more than 24 characters long.',
    pattern: ' Please match the requested format.'
  }
  focus: boolean = false

  @ViewChild('inputField')

  private _inputField: ElementRef

  @ViewChild('inputFieldMultiline')

  private _inputFieldMultiline: ElementRef

  private _model: string

  constructor(private cd: ChangeDetectorRef) {
  }

  // tslint:disable-next-line:no-empty
  onChange: any = () => {
  }

  // tslint:disable-next-line:no-empty
  onTouched: any = () => {
  }

  ngOnInit() {
    this.required = this.required !== undefined && this.required !== false
    this.disabled = this.disabled !== undefined && this.disabled !== false
    this.readonly = this.readonly !== undefined && this.readonly !== false
    this.myModel = ''
  }

  get model() {
    return this._model
  }

  set model(val: string) {
    if (val === this._model) {
      return
    }
    this._model = val
    this.onChange(val)
  }

  writeValue(value: any) {
    this._model = value
    this.cd.markForCheck()
  }

  registerOnChange(fn: any): void {
    this.onChange = fn
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn
  }

  onFocus() {
    if (this.readonly || this.disabled) {
      return
    }
    this.focus = true
  }

  onBlur() {
    if (this.readonly || this.disabled) {
      return
    }
    this.focus = false
    this.onTouched()
  }

  _focusInputField() {
    if(!this.readonly && !this.disabled) {
      if (this.multiline) {
        this._inputFieldMultiline.nativeElement.focus()
      } else {
        this._inputField.nativeElement.focus()
      }
    }
  }
}
 <div *ngIf="!multiline">
      <input
        #inputField
        class="input-container__input"
        *ngIf="!multiline"
        (focus)="onFocus()"
        (blur)="onBlur()"
        placeholder="{{placeholder}}"
        name="{{name}}"
        type="{{type || 'text'}}"
        pattern="{{pattern}}"
        minlength="{{minlength}}"
        maxlength="{{maxlength}}"
        min="{{min}}"
        max="{{max}}"
        [required]="required"
        autocomplete="{{autocomplete}}"
        [disabled]="disabled"
        [readonly]="readonly"
        [(ngModel)]="model"
        #myModel="ngModel"
      />
    </div>
    <ng-container *ngTemplateOutlet="inputContent"></ng-container>

    <div *ngIf="multiline" class="input-container__multiline">
      <div class="input-container__input input-container__multiline__place-holder">{{model}}</div>
      <textarea
        #inputFieldMultiline
        class="input-container__input input-container__multiline__input"
        [(ngModel)]="model"
        (focus)="onFocus()"
        (blur)="onBlur()"
        placeholder="{{placeholder}}"
        name="{{name}}"
        minlength="{{minlength}}"
        maxlength="{{maxlength}}"
        [required]="required"
        [disabled]="disabled"
        [readonly]="readonly"
        #myModel="ngModel"
      ></textarea>
    </div>
  </div>
  <ng-container *ngTemplateOutlet="inputContent"></ng-container>
  {{hint}}
</div>

<ng-template #inputContent>
  <div class="input-container__hints" *ngIf="this.theme !== 'inline'">
    <div class="input-container__hints--left">
      <div *ngIf="myModel && myModel.errors && myModel.touched" class="alert-error">
        <div [hidden]="!myModel.errors.required">
          <i class="mi mi-warning"></i>
          {{ValidationHints.required}}
        </div>
        <div [hidden]="!myModel.errors.minlength">
          <i class="mi mi-warning"></i>
          {{ValidationHints.minlength}}
        </div>
        <div [hidden]="!myModel.errors.maxlength">
          <i class="mi mi-warning"></i>
          {{ValidationHints.maxlength}}
        </div>
        <div [hidden]="!myModel.errors.pattern">
          <i class="mi mi-warning"></i>
          {{ValidationHints.pattern}}
        </div>
      </div>
    </div>
    <div class="input-container__hints--right" *ngIf="withCharCount">
      {{(model?.length || 0) + (maxlength ? ('/' + maxlength) : '')}}
    </div>
  </div>
</ng-template>

1 个答案:

答案 0 :(得分:0)

请注意,您已将multiline定义为@Input(),这意味着您将multiline从另一个组件传递到InputComponent

只要从父组件注入或更新OnChanges的值,就使用生命周期钩子multiline来检测更改。像这样修改你的代码 -

添加此导入语句:

import {OnChanges, SimpleChanges} from '@angular/core';

将此行添加到InputComponent

export class InputComponent implements OnInit, ControlValueAccesso, OnChanges {

 // other code goes here

 public multiline: boolean = false;   <--- define an initial value

 ngOnChanges(changes:SimpleChanges){
    if('multiline' in changes){       <---- detect changes and update
      this.multiline = changes['multiline'].currentValue;
   }
 }
}

如果要为使用@Input()定义的其他属性设置类似的错误,请考虑为它们实现上述模式。

希望它有所帮助。