如何访问在父组件上定义的ViewChild参考-Angular 2 [英] How to access ViewChild reference defined on parent component - Angular 2

查看:55
本文介绍了如何访问在父组件上定义的ViewChild参考-Angular 2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在应用模板(根组件模板)中定义了一个spinner/loader元素,例如

<!--I have it here so that I don't have to paste it in all my templates-->
<div #spinner></div>

在我的子组件中,我尝试使用@ViewChild访问它,但似乎总是返回undefined.我在子组件中访问此代码的代码是

@ViewChild('spinner', { read: ViewContainerRef }) container: ViewContainerRef;  //this is always undefined

但是,当我将#spinner放在子组件的HTML中时,它会被正确拾取.

是否可以将子组件中父组件中定义的元素作为ContainerRef?

我需要视图引用来使用ComponentFactoryResolver在其上动态创建组件.

似乎是类似问题,但找不到解决方法./p>

我现在正在使用可观察的共享服务,但仍然不会在.next上引发事件.

这是我在SpinnerComponent

中的代码

@Component({
    selector: 'spinner',
    styleUrls: ['app/styles/spinner.component.css'],
    template:
    `<div [hidden]="state.visible" class="in modal-backdrop spinner-overlay"></div>
     <div class="spinner-message-container" aria-live="assertive" aria-atomic="true">
        <div class="spinner-message" [ngClass]="spinnerMessageClass">{{ state.message }}</div>
    </div>`
})
export class SpinnerComponent {

    constructor(spinnerService: SpinnerService) {
        spinnerService.spinnerStatus.subscribe(event => {
            console.log('Event: ' + event); <= not getting called
            this.state.visible = event;
        });
    }

    public state = {
        message: 'Please wait...',
        visible: false
    };
}

在SpinnerService中,我有

@Injectable()
export class SpinnerService {
    public events: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

    public get spinnerStatus(): Observable<boolean> {
        return this.events.asObservable();
    }

    public showSpinner() {
        this.events.next(true);
    }

    public hideSpinner() {
        this.events.next(false);
    }
}

在调用组件中,我有

@Component({
    selector: 'edit-auction',
    templateUrl: '/auctions/edit.html'
})
export class EditAuctionComponent {

    constructor(public spinnerService: SpinnerService) {  }

    ngAfterViewInit() {
        //start the spinner
        this.spinnerService.showSpinner();
    }
}

在app.module.ts(根模块)中

@NgModule({
    imports: [BrowserModule, FormsModule, HttpModule, routes],
    declarations: [..],
    providers: [NotificationsService, SpinnerService],
    bootstrap: [AppComponent]
})
export class AppModule { }

解决方案

从其他组件访问数据对我来说听起来并不好.

对于您可能想做的最好的事情是定义将共享可观察的服务:

@Injectable()
export class EventService {
    public selectedCategoryName: string = '';
    private events = new BehaviorSubject<Boolean>(false);
    constructor() {

    }

    public showSpinner(){
        this.events.next(true)
    }

    public hideSpinner(){
        this.events.next(false);
    }

    public get spinnerStatus() : Observable<boolean> {
        return this.events.asObservable();
    }
}

然后在您的根组件中订阅

eventServiceInstance.spinnerStatus.subscribe(state=>{
            //thisSpinner.visible = state
        })

现在您将在所有其他地方打电话

eventServiceInstance.showSpinner()
eventServiceInstance.hideSpinner()

PS.为了使其正常工作,应在NgModule中而不是组件内部添加EventService提供程序

I have a spinner/loader element defined in app template (root component's template) like

<!--I have it here so that I don't have to paste it in all my templates-->
<div #spinner></div>

In my child components, I am trying to access it using @ViewChild but that seems to always return undefined. My code for accessing this in child component is

@ViewChild('spinner', { read: ViewContainerRef }) container: ViewContainerRef;  //this is always undefined

However when I place my #spinner in my child component's HTML, it gets picked up correctly.

Is there a way to get the element defined in parent component in your child component as a ContainerRef?

I need the view reference to create the component on it dynamically using ComponentFactoryResolver.

It seems a similar issue but can't find a way to overcome.

EDIT: I am now using a shared service with the observable, but still it doesn't raise an event on .next.

Here is my code in SpinnerComponent

@Component({
    selector: 'spinner',
    styleUrls: ['app/styles/spinner.component.css'],
    template:
    `<div [hidden]="state.visible" class="in modal-backdrop spinner-overlay"></div>
     <div class="spinner-message-container" aria-live="assertive" aria-atomic="true">
        <div class="spinner-message" [ngClass]="spinnerMessageClass">{{ state.message }}</div>
    </div>`
})
export class SpinnerComponent {

    constructor(spinnerService: SpinnerService) {
        spinnerService.spinnerStatus.subscribe(event => {
            console.log('Event: ' + event); <= not getting called
            this.state.visible = event;
        });
    }

    public state = {
        message: 'Please wait...',
        visible: false
    };
}

In SpinnerService, I have

@Injectable()
export class SpinnerService {
    public events: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

    public get spinnerStatus(): Observable<boolean> {
        return this.events.asObservable();
    }

    public showSpinner() {
        this.events.next(true);
    }

    public hideSpinner() {
        this.events.next(false);
    }
}

And in the calling component, I have

@Component({
    selector: 'edit-auction',
    templateUrl: '/auctions/edit.html'
})
export class EditAuctionComponent {

    constructor(public spinnerService: SpinnerService) {  }

    ngAfterViewInit() {
        //start the spinner
        this.spinnerService.showSpinner();
    }
}

In app.module.ts (root module)

@NgModule({
    imports: [BrowserModule, FormsModule, HttpModule, routes],
    declarations: [..],
    providers: [NotificationsService, SpinnerService],
    bootstrap: [AppComponent]
})
export class AppModule { }

解决方案

Accessing data from other components does not sounds good to me.

For what you are trying to do probably best would be to define service which will share observable:

@Injectable()
export class EventService {
    public selectedCategoryName: string = '';
    private events = new BehaviorSubject<Boolean>(false);
    constructor() {

    }

    public showSpinner(){
        this.events.next(true)
    }

    public hideSpinner(){
        this.events.next(false);
    }

    public get spinnerStatus() : Observable<boolean> {
        return this.events.asObservable();
    }
}

Then in your root component you will subscribe to

eventServiceInstance.spinnerStatus.subscribe(state=>{
            //thisSpinner.visible = state
        })

And now in all other places you will call

eventServiceInstance.showSpinner()
eventServiceInstance.hideSpinner()

PS. To make it works EventService provider should be added in NgModule and not inside of components

这篇关于如何访问在父组件上定义的ViewChild参考-Angular 2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆