Reputation: 9230
I'm having a bit of trouble I cant seem to figure out why my @ViewChild
isnt working..
Basically I want to call a function in one component from another component so in my sidebar
component I have a function called sendData()
and I want to be able to call that from a button click in my header
component so what Ive done is..
Sidebar component
import { Component, OnInit, Input, OnChanges, SimpleChanges, AfterViewInit } from '@angular/core';
import * as _ from 'lodash';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss']
})
export class SidebarComponent implements OnInit, OnChanges {
constructor(
private contenfulService: ContentfulService,
private userService: UserService
) { }
ngOnInit() {
}
sendData(){
...do something
}
}
header.component.ts
import { Component, OnInit, Input, ViewChild, EventEmitter } from '@angular/core';
import { UserService } from '../../../user.service';
import { SidebarComponent } from '../sidebar/sidebar.component';
@Component({
selector: 'app-program-header',
templateUrl: './program-header.component.html',
styleUrls: ['./program-header.component.scss']
})
export class ProgramHeaderComponent implements OnInit {
@ViewChild(SidebarComponent) sidebar;
constructor() { }
ngOnInit() {
}
}
header.component.html
<div (click)="sidebar.sendData()"></div>
but it isnt working Im getting this error in the console...
ERROR TypeError: Cannot read property 'sendData' of undefined
I have removed code for brevity, so please let me know if there is more information you need
Im not sure what the problem is?
EDIT
Or if anyone knows another way to call a function from a seperate component let me know
Any help would be appreciated!
Thanks!
Upvotes: 1
Views: 19290
Reputation: 71
You can always name the component using a # symbol.
HTML template:
<app-sidebar #sidebar1></app-sidebar>
TS code:
@ViewChild('sidebar1') sidebar: any;
You can import the type of your component instead of 'any'.
Hope this helps ;-)
Upvotes: 0
Reputation: 109
In my case - it was the import from "@shared"
which has caused this issue. You have to pay attention, that the component you are using the @ViewChild
component reference is not in the same module with same shorthand path. If it is, import the @ViewChild
component from
'shared/components/sidebar/sidebar.component'
and not from '@shared'
Upvotes: 0
Reputation: 1131
Just as an addition to this conversation, I have been squirreled off on a couple of occasions chasing what seemed to be the lack of a functioning @ViewChild
when the cause was the @ViewChild
referencing a component in a module that was not being imported. The "cannot read property of undefined" can become extremely misleading and may not be related to @ViewChild
at all; be sure to check your imports first.
Upvotes: 2
Reputation: 38171
ViewChild
is expected to be used to get target element from current component's view(template) which matches the selector.
But according to your comment above, it seems there is no app-sidebar
placed in your header.component.html
, so ViewChild
is not able to get a valid element which results in your current error.
The solution should be place app-sidebar
at least once.
<app-sidebar></app-sidebar>
<div (click)="sidebar.sendData()"></div>
Upvotes: 2
Reputation: 1448
If header and sidebar components are siblings, you can not pass data between them directly. Take a look at ‘Output’ and ‘Input’ from angular. Alternatively, you can use a Service to pass data between components. Check out services and observables.
<parent>
<app-program-header>
</app-program-header>
<app-sidebar>
</app-sidebar>
</parent>
Upvotes: 2