在Angular 2中,组件视图如何通过服务进行更新

时间:2016-09-02 17:34:47

标签: angular angular2-services angular2-components

我是Angular2的新手,并且正在努力通过服务获取组件视图以进行更新。

我想在我的应用程序中使用两种不同的页面类型。一个显示带有小徽标的标题,另一个显示标题并且具有更大的徽标。

我在根应用程序组件下直接有一个app-header组件。 app-header组件检查服务中的数组,并使用* ngIf更改它显示的内容。我附加了路由更改,因此它检查NavigationStart并使用服务相应地更新值。

如果我点击刷新,则视图会正确显示,但如果我在应用程序中更改路径,则视图app-header组件不会更新。当我在console.log中看到值时,我看到服务值和组件类属性正在正确更改,但在组件视图中没有任何更新。我虽然可能有多个服务实例,但我在服务上添加了一个随机数来检查它,它们都是相同的实例。

以下是模板服务:

import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/switchMap';

import { Injectable } from '@angular/core';
import { Template } from './template'

//HANDLE TEMPLATES IN AN ORGANIZED WAY
@Injectable()
export class TemplateService  {

    template: Template = {
        showHeader: true,
        imagePath: "",
        name: Math.random()
    };

    public setShowHeader(value:boolean){
        this.template.showHeader = value;
        console.log(value, this.template.showHeader);//CHECK TO MAKE SURE VALUES MATCH
        console.log("name", this.template.name);//CHECK TO MAKE SURE SAME INSTANCE
    }

    //ALLOW BACKGROUND TO BE MANUALLY SET IF DESIRED - NOT USED FOR NOW
    public setImage(url){
        this.template.imagePath = url;
    }

    //WHEREVER A ROUTE IS DEFINED A PAGE CAN CALL THIS SERVICE AND ADD SPECIFY AS THIS TEMPLATE
    public noHeadRoutes = [];

    public setRandomImage(){
        this.template.imagePath = this.availableImagePaths[Math.floor(Math.random() * this.availableImagePaths.length)];
    }

    //USE THESE IF NO MANUAL IMAGE IS SET
    private availableImagePaths:[string] = [
        "images/home/globe.jpg",
        "images/home/typing.jpg"
    ];

    constructor() {
        this.setRandomImage();
    }

}

以下是app-header组件:

import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, OnInit } from '@angular/core';
import { Router, NavigationStart } from '@angular/router';
import { TemplateService, Template } from '../services/template';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'app-header',
  styles: [
    require('./app-header.scss')
  ],
  template: `
    {{ [(template.showHeader)] }} -- {{ template.name }}
    <header class="header" *ngIf="template.showHeader">
      <nav class="navbar navbar-fixed-top bg-inverse navbar-dark">
        <a class="navbar-brand" Routerlink="/" RouterLinkActive="/">
            <img src="../../images/logo.svg" class="app-logo" />
        </a>
        
        <ul class="nav navbar-nav pull-right">
            <li class="nav-item" *ngIf="authenticated">
                <a class="nav-link" (click)="signOut.emit()" href="#">
                    Sign out
                </a>
            </li>
            <li class="nav-item" *ngIf="!authenticated">
                <a class="nav-link" Routerlink="/login" RouterLinkActive="active">
                    Login
                </a>
            </li>
        </ul>
        
      </nav>
    </header>
    
    <!-- PUT IN A BACKGROUND IMAGE AND ADJUST SPACING -->
    <div *ngIf="!template.showHeader">
        <style type="text/css">
            .hey{font-size:10px;}
            
        </style>
        <div class="big-logo">
            <img src="images/logo.svg" />
        </div>
    </div>
  `
})

export class AppHeaderComponent implements OnInit{

  @Input() authenticated: boolean;
  @Output() signOut = new EventEmitter(false);
  template: Template;

  constructor(private _router: Router, private _ts: TemplateService) {

    this.template = _ts.template;

  }

  ngOnInit(){
    //ALL VIEWS CAN SET A NO HEAD TEMPLATE IF NEEDED. THIS CHECKS AT NAVIGATION START AND SETS THE HEADER
    this._router.events.subscribe( (event) =>{

      if(event instanceof NavigationStart) {

        if(this._ts.noHeadRoutes.includes(event.url)){
          this._ts.setShowHeader(false);
        }

        else{
          this._ts.setShowHeader(true);
        }

      }

    });

  }

}

1 个答案:

答案 0 :(得分:1)

所以写这篇文章并问这个我看到了我明显的错误,但我没有看到任何其他答案,所以我仍然会发布一个答案。

我的问题是changeDetection使用的是OnPush,之前我没有注意到。一旦设置为默认值,它就会按预期运行。