2

I have two components FormComponent and Test1Component.

Test1Component uses ng-content to display FormComponent

FormComponent.ts

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-form',
  template:`
      <div class="panel panel-default fcs-form">
        <div class="panel-header form-header">
                {{headerTitle}}
        </div>

        <div class="panel-body form-body">
            <ng-content select="[form-body]"></ng-content>
        </div>
        <div class="panel-footer text-center form-footer">
                <button class="btn btn-primary">{{resetBtnText}}</button>
            <button class="btn btn-primary" (click)="saveForm()"> {{saveBtnText}} </button>
            <button class="btn btn-primary">{{addBtnText}}</button>
        </div>
      </div>
  `
})
export class FormComponent{
  @Input() headerTitle:string = "Header Title";
  @Input() saveBtnText:string = "Save";
  @Input() resetBtnText:string = "Reset";
  @Input() addBtnText:string = "Add";
  @Output() save:EventEmitter<any> = new EventEmitter();

  constructor(){}

  saveForm(e: any){
    this.save.emit("save");
    console.log("FormComponent save");
  }
}

Test1Component.ts

import { Component, Inject, OnInit, ContentChild } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { FormComponent } from './form.component';

@Component({
  selector: 'app-test1',
  template: `
    <app-form headerTitle="my header" (save)="saveForm(complexForm.value, $event)">
        <div form-body>

            <div class="jumbotron">
                <form [formGroup]="complexForm" (ngSubmit)="submitForm(complexForm.value)">

                    <div class="form-group">
                        <label>First Name:</label>
                        <input class="form-control" type="text" placeholder="John" [formControl]="complexForm.controls['firstName']">
                    </div>

                </form>
            </div>

        </div>
    </app-form>
  `
})
export class Test1Component {
    @ContentChild(FormComponent) contentChildForm: FormComponent;

  complexForm : FormGroup;

  constructor(private fb: FormBuilder){
    this.complexForm = fb.group({
        'firstName' : "",
        'lastName': "",
        'gender' : "Female",
        'hiking' : false,
        'running' : false,
        'swimming' : false
    });
  }

  saveForm(){
    console.log(this.contentChildForm);
    debugger;
    console.log("Test1Component save");
    return true;
  }
}

Why is Test1Component.saveForm() is logging this.contentChildForm as undefined ?

How to fix it ?

This is the plunker I made https://plnkr.co/edit/xbTgRuSd7nBIrOWsE1zO , please open console to see logs.

Flying Gambit
  • 1,238
  • 1
  • 15
  • 32

1 Answers1

5

I would use @ViewChild in your case because i don't see any projectable nodes with type FormComponent in your Test1Component

Modified Plunker

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • 2
    Indeed I think is the right answer. This could be useful to know when to use `@ViewChild` and `@ContentChild`: http://stackoverflow.com/questions/34326745/whats-the-difference-between-viewchild-and-contentchild – SrAxi Apr 07 '17 at 13:13
  • 1
    @SrAxi That made things conceptually clear and easy to follow – Flying Gambit Apr 07 '17 at 13:48
  • @yurzui Would it be wise to use ViewChild reference to pass data to the child ? or use Input decorator? – Flying Gambit Apr 07 '17 at 13:49
  • After reading some articles, I am getting the impression that Parent should use Input to pass data to Child, and child should use events to pass data to Parent – Flying Gambit Apr 07 '17 at 13:52
  • @FlyingGambit I suggest you to read this: https://angular.io/docs/ts/latest/cookbook/component-communication.html . It will help you a lot. Btw, if you are planning on passing the same data to other components go for `shared service`. Cheers! – SrAxi Apr 07 '17 at 13:54