为什么当添加到阵列来自另一个组件时,ngFor不会更新?

时间:2016-01-20 03:26:20

标签: angular

我已经有一段时间了,很多文章,文档,很多试验和错误,但我觉得我错过了一些核心内容。

本质上,我尝试创建一个可扩展的导航组件,其他组件可以在添加到页面时添加项目。我试图通过几种方式实现这一目标,包括服务,这个例子我通过将一个组件注入另一个组件来尝试它。

我有一个包含项目列表的组件,我有一个ngFor循环遍历项目并显示文本。我在页面上有一个按钮,当您单击时向项目添加项目。我还将组件注入另一个组件,我已经在NgOnInit()上添加了一个项目(尝试了其他生命周期事件和构造函数)。

奇怪的是,当按钮将项目添加到数组时,列表会更新,但是当其他组件添加项目时,列表不会更新UI,即使项目计数增加,我也可以在UI中看到组件已加载并呈现默认项目。

import {Component} from 'angular2/core'; 
import {Router, RouteParams} from 'angular2/router'; 
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; 
import {Injectable} from 'angular2/core';

@Component({
    selector: 'caseBasedSearchSidebar',
    template: `<ul id="sidebar-wrapper" class="clearfix nav navbar-default sidebar-nav">
                  <li *ngFor="#nav of navigationItems">
                    <span>{{nav.name}}</span>
                  </li>
           <ul>  <button (click)=addNavigationItem()>Add</button> `,
directives: [ROUTER_DIRECTIVES] })

@Injectable() export class SidebarComponent {
    public navigationItems: Array<ISideNavigationItem>;

    constructor() {
        this.navigationItems = [{ name: 'test' }];
    }

    public addNavigationItem(item: ISideNavigationItem) {
        this.navigationItems.push({ name: 'test' });
    } 
}

export interface ISideNavigationItem {
name: string; }

import {Component, OnInit} from 'angular2/core'; 
import {SidebarComponent} from '../sideBar.component';

@Component({
    templateUrl: '/CaseBasedSearch/PatientInformation',
    providers: [SidebarComponent] 
})
export class PatientInformationComponent implements OnInit {
    private sideBarComponent: SidebarComponent;

    constructor(sideBarComponent: SidebarComponent) {
        this.sideBarComponent = sideBarComponent;
    }

    ngOnInit() {
        this.sideBarComponent.addNavigationItem({ name: 'testing' });
    } 
}

感谢任何指导。

3 个答案:

答案 0 :(得分:1)

您正在navigationItems内分配SidebarComponent模型。对此模型的更改不会传播到其他组件。

考虑将navigationItems设置为@Input属性:

@Input() public navigationItems: Array<ISideNavigationItem>;

将模型从父组件(PatientInformationComponent)传递到子组件(SidebarComponent):

<case-based-search-sidebar [navigationItems]="navigationItems">

另外,作为惯例,SidebarComponent中的选择器应该是蛇形的:

selector: 'case-based-search-sidebar'

正如其他人所说:

  • SidebarComponent不是服务。您不应该将它注入构造函数中,也不需要将它添加到providers属性。
  • 应删除组件的@Injectable属性。

答案 1 :(得分:1)

最终我的问题是注入服务/组件的范围。我在每个组件上使用提供者项目,并且使用服务,这导致每个服务都拥有它自己的实例。当组件更新服务时,它没有更新先前测试使我相信它的相同阵列。我将注入移动到boot.ts它们都开始获得相同的实例。回答here

最终代码;

import {Component, OnInit} from 'angular2/core';
import {CaseBasedSearchNavigationService} from '../caseBasedSearchNavigation.service';
import {ISideNavigationItem} from '../caseBasedSearchNavigation.service';

@Component({
    templateUrl: '/CaseBasedSearch/PatientInformation'
})


export class PatientInformationComponent implements OnInit {
    private navigationService: CaseBasedSearchNavigationService;

    constructor(navigationService: CaseBasedSearchNavigationService) {
        this.navigationService = navigationService;

        this.navigationService.addNavigationItem({ name: 'testing' });
        this.navigationService.addNavigationItem({ name: 'testing' });
    }

    ngOnInit() {

    }
} 

import {Component, Input} from 'angular2/core';
import {Router, RouteParams} from 'angular2/router';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {CaseBasedSearchNavigationService} from './caseBasedSearchNavigation.service';
import {ISideNavigationItem} from './caseBasedSearchNavigation.service';

@Component({
    selector: 'case-based-search-sidebar',
    template: `<ul id="sidebar-wrapper" class="clearfix nav navbar-default sidebar-nav clearfix">
              {{navigationItems.length}}
               <li *ngFor="#nav of navigationItems">
                        <span>{{nav.name}}</span>
                      </li>
               <ul>`,
    directives: [ROUTER_DIRECTIVES]
})

export class SidebarComponent {
   public navigationItems: ISideNavigationItem[];

   constructor(navigationService: CaseBasedSearchNavigationService) {
        this.navigationItems = navigationService.navigationItems;

        navigationService.addNavigationItem({name : 'test2'});
    }
}

import {Injectable} from 'angular2/core';

@Injectable()
export class CaseBasedSearchNavigationService {
    public navigationItems: ISideNavigationItem[];

    constructor() {
        this.navigationItems = [];
    }

    public addNavigationItem(item: ISideNavigationItem) {
        this.navigationItems.push(item);
    }
}

export interface ISideNavigationItem {
   name : string;
}

答案 2 :(得分:0)

也许你应该删除@Injectable组件的SidebarComponent装饰器,只保留@Component组件。

希望它可以帮到你, 亨利