2

Note: since the problem is a little complex, the code is abstracted for readability

We've a <parent-component> like this:

<child-component></child-component>
<button (click)="doSomeClick()"> Do Some Click </button>

The template of the <child-component> is:

<textarea #childComponentElement #someField="ngModel" name="someName" [(ngModel)]="someModel"></textarea>

We're trying to access the value of this element inside the parent-component.component.ts like this:

export class ParentComponent implements AfterViewInit {
    @ViewChild('childComponentElement') el:ElementRef;

    ngAfterViewInit() {
        console.log(this.el.nativeElement.value);
    }
    doSomeClick(){

    }
}

However it throws this error:

Cannot read property 'nativeElement' of undefined

What have we tried so far:

Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219
  • have you tried the method from here: https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#afterview ? – Edwin Jun 01 '17 at 09:45
  • 1
    @Edwin `ngAfterViewInit` is correct in this usage. It's just that he's trying to access the templateRef from a parent component that the template does not belong to. – borislemke Jun 01 '17 at 09:47

2 Answers2

4

There's no easy way to this with a nested component, you'll have to create an EventEmitter that emits the ElementRef of the element you are trying to get access to:

child.component.ts

class ChildComponent implements AfterViewInit {

    @Output()
    templateLoaded: EventEmitter<ElementRef> = new EventEmitter()

    @ViewChild('childComponentElement') el: ElementRef

    ngAfterViewInit(): void {
        this.templateLoaded.emit(this.el)
    }
}

parent.component.html

<child-component (templateLoaded)="templateLoaded($event)"

parent.component.ts

class ParentComponent {

    templateLoaded(template: ElementRef): void {
        // do stuff with the `template`
    }
}

Original Answer

Try using the read property in the 2nd parameter of ViewChild

@ViewChild('childComponentElement', {read: ElementRef}) el: ElementRef

If you are wondering about the second parameter, this answer gives a very good explanation: What is the read parameter in @ViewChild for

borislemke
  • 8,446
  • 5
  • 41
  • 54
  • After using the `read` property, the `this.el` is still undefined. – Zameer Ansari Jun 01 '17 at 09:44
  • 1
    @xameeramir Ahh, are you trying to access the `ElementRef` from the parent component which does not have that html as the template? – borislemke Jun 01 '17 at 09:46
  • Yes, we're accessing ` – Zameer Ansari Jun 01 '17 at 09:48
  • How do I I trigger `templateLoaded` inside `ParentComponent` to do the verification? When I reload the page, it doesn't hits into it neither by `console.log` or `debugger` – Zameer Ansari Jun 01 '17 at 10:16
  • 1
    @xameeramir the `templateLoaded` function will be triggered by the event binding on the `child-component` element: ` – borislemke Jun 01 '17 at 10:17
1

Use the @Output decorator or a service instead of trying hopelessly to access the textarea directly from the parent component

child template

<textarea #childComponentElement #someField="ngModel" name="someName" [(ngModel)]="someModel"></textarea>

child component

@ViewChild('childComponentElement') el:ElementRef;
@Output() textarea = new EventEmitter();
constructor(){
this.textarea.emit(this.el.nativeElement.value);
}

parent template

<child-component (change)="getdata($event)"></child-component>

parent component

export class ParentComponent {
    getdata(e) {
        console.log(e);
    }
}
Hamed Baatour
  • 6,664
  • 3
  • 35
  • 47