4
votes

I'm using Angular 4. I'm trying to access one component's template element inside another component. The only thing I've found that works (illustrated below) is not very 'Angular'.

Component #1 (which contains the template):

  @Component({
    template: `...<input type="text" id="txtUserName" />`

Component #2 (which is getting the above component's template element value in a click event):

  (<HTMLInputElement>document.getElementById('txtUserName')).value;

I've found countless snippets on ElementRef, ViewChild, etc., but none of them actually work for getting the template element's value. Does anyone know of an Angular 4 approach that accomplishes the same thing I'm doing above?

3

3 Answers

2
votes

Is there any relation between Component #1 and Component #2.

if both have parent and child relation ship you can access using @ViewChild() or @input

if there is no relation ship than try to access using shared service More info https://angular.io/docs/ts/latest/cookbook/component-communication.html

1
votes

You can do this with FormGroups in Angular 4.

Component A

FormGroups allow you to define the form elements as features of the form, and then attach that description to a form.

Inside the Component A constructor

 public constructor(build: FormBuilder) {
     this.form = build.group({
         username: build.control('')
     });
 }

You can now use that form group in your template.

<form [formGroup]="form">
    <component-b></component-b>
</form>

If you place your child component inside a <form> that is using the FormGroup you can then access the control via dependency injection.

Component B

You can access the FormGroup via the directive in the constructor like this.

public constructor(public formGroupDir: FormGroupDirective) {
}

You have to wait until your component is ready to access the username control.

public ngAfterContentInit(): void {
    let formGroup = this.formGroupDir.form;
    this.control = formGroup.get('username');
}

In the child template you can now bind the input to the form group control.

<input type="text" [formControl]="control"/>

You are all set now. Component A will receive form change notifications from the child component via the FormGroup events.

1
votes

Simplest working example would be

import { Component, OnInit, ViewChild, TemplateRef, Input  } from '@angular/core';

@Component({
  selector: 'template-component',
  template: `
<ng-template #templateX>
  <div>This is templateX with text: {{myText}}</div>
</ng-template>  
  `
})
export class TemplateComponent {
  @ViewChild('templateX')
  templateXRef: TemplateRef<any>;

  @Input()
  myText: string;
}


@Component({
  selector: 'my-component',
  template: `
  <template-component #link myText="John Smith">
  </template-component>

  <div>Hello there.</div>

  <ng-container *ngTemplateOutlet="link.templateXRef"></ng-container>  
  `
})
export class MyComponent {
}

See more complex example on stackblitz.