绑定到路由器出口内子组件的输入属性

时间:2017-01-24 02:21:55

标签: angular typescript rxjs

我想将父组件输入元素值绑定到子组件属性。皱纹是子组件通过路由器插座嵌套在父组件中。似乎最好的方法是在父组件和子组件之间使用共享服务,如演示here

这是我的测试实施:

父组件

import { Component } from '@angular/core';
import { Router }   from '@angular/router';
import { ThreadsService }   from './threads.service';

@Component({
    moduleId: module.id,
    selector: 'threads',
    templateUrl: 'threads.component.html',
    styleUrls: ['threads.component.css'],
    providers: [ ThreadsService ]
})


export class ThreadsComponent {

    constructor(private router: Router,
    private threadsService: ThreadsService){}

    emit(value: string) {
        let emission = value;
        this.threadsService.emissionReceived(emission);

    }

}

父模板

<div class="col-sm-9 threads">
    <div class="threads">
        <div class="thread-container">
            <ul class="nav nav-tabs">
                <li [class.active]="router.url == '/featured'">
                    <a routerLink="/featured">Featured</a>
                </li>
                <li [class.active]="router.url == '/new'">
                    <a routerLink="/new">New</a>
                </li>
                <li [class.active]="router.url == '/trending'">
                     <a routerLink="/trending">Trending</a>
                </li>
                <div class="col-sm-3 search-div">
                    <input #threadsearch (keyup.enter)="emit(threadsearch.value)" type="text" class="form-control  search-box" placeholder="Search topics...">
                </div>
            </ul>
            <!--Child component in here-->          
            <router-outlet></router-outlet> 
        </div>
    </div>
</div>

子组件:

import { Component, Input } from '@angular/core';
import { ThreadsService } from './threads.service'
import { Subscription }   from 'rxjs/Subscription';

@Component({
    moduleId: module.id,
    selector: 'featured-threads',
    template: `
        <div class="featured">
        <thread [threads]="threads" [emission]="emission"></thread>
        </div>`, 
    providers: [ ThreadsService ]
})

export class FeaturedThreadsComponent {
    subscription: Subscription;
    emission = '';

    constructor(private threadsService: ThreadsService) { 
        this.subscription = threadsService.searchResults$.subscribe(
            emission => {
                this.emission = emission;
                console.log(emission)
            }
        )

    ngOnDestroy() {
    // prevent memory leak when component destroyed
        this.subscription.unsubscribe();

    }
}

我可以从父组件和共享服务将emission登录到控制台,但不能从此子组件登录。尽可能地看,子组件有一个自己的子组件,一个最终将呈现emission的模板。

2 个答案:

答案 0 :(得分:2)

首先

.addListener()

您的所有代码都在为 var mql = window.matchMedia("(max-width: 767px)"); mql.addListener(query) query(mql) function query(mediaquery) { console.log(mediaquery); if (mediaquery.matches) { // media query matches } else { // media query does not match } }; 创建新实例,为providers: [ ThreadsService ] 创建新实例,这会对您的代码造成损害。 Coz服务必须是单身,必须在Child component

中添加

例如

Parent

答案 1 :(得分:1)

Günther的评论完全正确:

  

“你得到每个提供者的实例。如果你在两个组件上提供它,将为这些组件的每个实例创建一个实例。如果你只在父组件上提供它,那么子组件将获得父组件的实例(或者因此,在包含路由器插座的组件(对于其中一个祖先)上只提供一次。在树的顶部(根注入器)是AppModule。当在任何祖先组件上找不到提供者时查阅根注射器“

您可以在ngModule

中提供服务
providers: [ ThreadsService ]

因此从您的子级和父级中删除提供程序。

或者您从子组件中删除提供程序。

以下是您的代码的plunker,其中providers仅在父代中设置:

plunker

查看控制台时,您可以看到数据现在也会发送给孩子。

最后摘录了angular.io

  

当底部的组件请求依赖时,Angular会尝试使用在该组件自己的注入器中注册的提供程序来满足该依赖关系。如果组件的注入器缺少提供程序,它会将请求传递给其父组件的注入器。如果该注入器无法满足请求,则将其传递给其父组件的注入器。在我们找到可以处理请求或用完组件祖先的注入器之前,这些请求一直在冒泡。如果我们用尽祖先,Angular会抛出错误。

     

...假设我们使用Car,Engine和Tires的提供程序配置了根注入器(标记为A)。我们创建一个子组件(B),为Car和Engine定义自己的提供者。这个子组件是另一个组件(C)的父组件,它定义了自己的Car提供者。

     

在幕后,每个组件都会设置自己的注入器,并为该组件本身定义一个或多个提供程序。