从指令中检索主机组件的FormGroup变量,而不将其作为属性

时间:2017-01-28 12:06:06

标签: angular angular2-forms angular2-directives

我有以下组件:

@Component({
  templateUrl: './signup.component.html'
})
export class SignupComponent implements OnInit {

  signupForm: FormGroup; //Notice the FormGroup instance variable
  submitted = false; //Also notice the submitted variable
  ...

使用自定义feedbackClasses指令,如下所示(来自SignupComponent模板):

<div class="form-group" [feedbackClasses]="signupForm" [control]="'firstName'" [submitted]="submitted">

以下是该指令的定义:

import {Directive, ElementRef, Input, Renderer, DoCheck} from '@angular/core';
import {AbstractControl, FormGroup} from '@angular/forms';

@Directive({selector: '[feedbackClasses]'})
export class FeedbackClassesDirective implements DoCheck {

  @Input('feedbackClasses') formGroup: FormGroup;
  @Input('control') controlPath: string; //I would like to avoid passing this as an attribute
  @Input('submitted') submitted: boolean;//Same thing here

  constructor(private el: ElementRef, private renderer: Renderer) {
  }

  ngDoCheck() {
    const control: AbstractControl = this.formGroup.get(this.controlPath);
    if (control && this.submitted) {
      this.applyClasses(control.invalid);
    }
  }

  private applyClasses(inError: boolean) {
    this.renderer.setElementClass(this.el.nativeElement, 'has-success', !inError);
    this.renderer.setElementClass(this.el.nativeElement, 'has-danger', inError);
  }

}

我遇到的问题是,每次我想使用此指令时,我都必须传入相应的FormGroupboolean,表明表单是否已提交。

有没有办法直接从指令中检索FormGroupboolean而不使用属性?如果是这样的话?

1 个答案:

答案 0 :(得分:1)

您可以注入应用指令的组件。 为此,该指令只能应用于一种类型的组件。

@Directive({selector: '[feedbackClasses]'})
export class FeedbackClassesDirective implements DoCheck {

  @Input('feedbackClasses') formGroup: FormGroup;
  @Input('control') controlPath: string; //I would like to avoid passing this as an attribute
  @Input('submitted') submitted: boolean;//Same thing here

  constructor(private el: ElementRef, 
              private renderer: Renderer, 
              private signUpComponent: SignupComponent) {
  }

  ngOnInit() {
    console.log(this.signUpComponent.signUpForm);
    console.log(signUpComponent.submitted); // probably not set yet
  }
}

或者您可以在应该支持该指令的组件上提供共享服务并将其注入

@Injectable()
export class FormStatusService {
  signupForm: FormGroup;
  submitted = false; // better use an BehaviorSubject
}
@Component({
  templateUrl: './signup.component.html':
  providers: [FormStatusService]
})
export class SignupComponent implements OnInit {

  //signupForm: FormGroup; //Notice the FormGroup instance variable
  //submitted = false; //Also notice the submitted variable

  constructor(private formStatus:FormStatusService) {
    // access shared service to read and write values
  }
  ...
}
@Directive({selector: '[feedbackClasses]'})
export class FeedbackClassesDirective implements DoCheck {

//  @Input('feedbackClasses') formGroup: FormGroup;
//  @Input('control') controlPath: string; //I would like to avoid passing this as an attribute
  // @Input('submitted') submitted: boolean;//Same thing here

  constructor(private el: ElementRef, 
              private renderer: Renderer,
              private signUpComponent: FormStatusService) {
    // access shared service to read and write values
  }
}

另见https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service