属性

2017-01-28 18 views
1

としてそれを渡さずに、私は次のコンポーネントがあります。属性

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

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

SignupComponentテンプレートから)次のようにカスタムfeedbackClassesディレクティブを使用しています。

<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を渡す必要があります。これは、フォームが送信されたかどうかを示します。

FormGroupと属性を使用せずにディレクティブから直接booleanを取得する方法はありますか?もしそうなら、どのように?

答えて

1

ディレクティブが適用される場所にコンポーネントを挿入できます。 ディレクティブは、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 
} 
@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

+0

おかげGünteを注入しなければならない部品の共有サービスを提供することができますr、なぜBehaviorSubjectが助けになるのか説明できますか?また、 'FormStatusService'をディレクティブのコンストラクタ内に挿入することを忘れましたか? – balteo

+0

ヒントのおかげで、コンストラクタにサービスを追加しました(気を散らしました;-))。 「Subject」または「Observable」は、ポーリングの代わりにプッシュ通知を可能にします。 'BehaviorSubject'は最後に発行された値を直ちに新しい加入者に送ります。これは、例えば、2つのクラスが次々と作成され、コンストラクタ内でイベントを発行し、もう1つのクラスがまだ作成されておらず、値が発行された後にサブスクライブするだけなので、その初期イベントを見逃す場合に、 (便利な場所の1つの例)。 –

+0

Ummm ...私はまだ指示に何を注入するか不明です:あなたは、(多くのコンポーネントで使用される)ディレクティブとサインアップコンポーネントとの間の結合を作成する 'signupComponent'を注入しました。 'FormStatusService'を指示文に挿入することを意味しましたか? – balteo