Mr.X
Mr.X

Reputation: 31275

Unable to get hold of child DOM element

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:

Upvotes: 2

Views: 818

Answers (2)

borislemke
borislemke

Reputation: 9136

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

Upvotes: 4

Hamed Baatour
Hamed Baatour

Reputation: 6942

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);
    }
}

Upvotes: 1

Related Questions