4

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 Answers 3

2

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

Sign up to request clarification or add additional context in comments.

2 Comments

As stated here ... the "Angular-y" approach is that a component should not be accessing another component's template unless there is a specific relationship between the components. You can instead use a service as suggested here. I have an example here: blogs.msmvps.com/deborahk/…
DeborahK, I don't have enough StackOverflow points to upvote you, but your article is exactly what I needed. Now I'm able to retrieve the template elements' values in the other component via the getter. Thank you!
1

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 Comment

Thank you, ThinkingMedia. DeborahK's answer (above) accomplished exactly what I need. Still, I'll give your solution a go, too, because I want to understand the various ways of sharing data between components.
1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.