angular 2 - 通过组件更改全局服务中的接口,并更新另一个

时间:2016-07-29 11:21:06

标签: typescript angular

我正在使用角度2.我想构建一个包含接口的全局服务。可以通过HeaderComponent更改此界面。用户通过HeaderComponent更改界面后,界面也在另一个ChildComponent中更改。因此,我在堆栈溢出时找到了this answer

假设我有一个界面和2个不同的类。这些类中的每一个都持有不同类型的接口。

MyInterface的

export interface MyInterface {
    key: string,
}

ClassA的

import { MyInterface } from './interfaces/my-interface';
export class ClassA {
    type = "A";
    _interface: MyInterface = {
        key: "value1",
    };
}

ClassB的

import { MyInterface } from './interfaces/my-interface';
export class ClassB {
    type = "B";
    _interface: MyInterface = {
        key: "value2",
    };
}

全球服务正在实施此界面。

GlobalService

import { Injectable, EventEmitter }    from '@angular/core';

import { ClassA } from './classes/class-a';
import { ClassB } from './classes/class-b';
import { MyInterface } from './interfaces/my-interface';

@Injectable()
export class GlobalService {

    public interfaceChanged: EventEmitter<MyInterface>;
    _interface: MyInterface;

    interfaceList: string[] = [];

    interfaces = [
        new ClassA(),
        new ClassB()
    ];

    selectedInterface: string;

    constructor() {
        this.interfaceChanged = new EventEmitter<MyInterface>();
        for (var i = 0; i < this.interfaces.length; i++)
            this.interfaceList.push(this.interfaces[i].type);
        this.changeInterface(this.interfaceList[0]);
    }

    changeInterface(_interface: string): void {
        if (this.interfaceList.includes(_interface)) {
            this.selectedInterface = _interface;
            for (var i = 0; i < this.interfaces.length; i++) {
                if (this.interfaces[i].type == this.selectedInterface) {
                    this._interface = this.interfaces[i]._interface;
                    this.interfaceChanged.emit(this.interfaces[i]._interface);
                }
            }
        }
    }
}

现在HeaderComponentapp.component.ts

中作为指令实施

app.component.ts

import { HeaderDirective } from './directives/header';
import { FooterDirective } from './directives/footer';

@Component({
  selector: 'my-app',
  template: `
    <my-header></my-header>
    <div class="container">
      <router-outlet></router-outlet>
    </div>
    <my-footer></my-footer>
  `,
  styleUrls: [ ],
  directives: [HeaderDirective, FooterDirective, ROUTER_DIRECTIVES]
})
export class AppComponent { }

可以通过选择字段更改界面:

import { Component } from '@angular/core';
import { MyInterface } from './interfaces/my-interface';
import { LanguageService } from './services/global-service';

@Component({
    selector: 'my-header',
    template: `
      <select (change)="change($event.target.value)">
        <option *ngFor=" let _interface of interfaceList ">{{ _interface }}</option>
      </select>
    `,
})
export class HeaderComponent {

    selectedInterface: string;
    interfaceList: string[];
    _interface: MyInterface;

    constructor(private globalService: GlobalService) {
        this.selectedInterface = this.globalService.selectedInterface;
        this.interfaceList = this.globalService.interfaceList;
        this._interface = this.globalService._interface;
    }

    change(_interface: string) {
        this.globalService.changeInterface(_interface);
    }
}

到目前为止一切顺利。在我通过HeaderComponent更改界面后,我希望通过ChildComponent

显示另一个<router-outlet></router-outlet>的界面
import { Component, EventEmitter } from '@angular/core';
import { GlobalService } from './services/global-service';
import { MyInterface } from './interfaces/my-interface';

@Component({
  selector: 'my-child',
  template: `
    <p>Test: {{ _interface.key }}</p>
  `,
})
export class ChildComponent {

    private _interface: MyInterface;

    constructor(private globalService: GlobalService) {

        this.globalService.interfaceChanged
                          .toPromise()
                          .then(_interface => {
                              this.changeLanguage(_interface);
                          })
                          .catch(err => {
                              console.log(err);
                          });
    }

    changeInterface(_interface: MyInterface) {
        this._interface = _interface;
    }
}

问题是通过HeaderComponent的界面更改正在运行,但ChildComponent的界面不会更改。我的changeInterface(interface: MyInterface)中的ChildComponent函数甚至没有被调用。用户正在使用的Here

...
constructor(globalService: GlobalService) {
    globalService.interfaceChanged.subscribe(_interface => this.changeInterface(_interface));
}
...

代表ChildComponent。但如果我这样做,我的sublime编辑器中就会出现错误:“参数'接口'隐式具有'任意'类型。”那么我做错了什么?我在这里缺少什么?

Here你可以在Plunker上看到它。

1 个答案:

答案 0 :(得分:2)

编辑器中的错误

  

“参数'接口'隐式具有'任意'类型。”

是因为您有严格的TypeScript规则阻止tsc编译代码。通过转到tsconfig.json更改配置并关闭noImplicitAny标志:

"noImplicitAny": false

或者在subscribe回调中为您的界面添加类型:

globalService.interfaceChanged.subscribe((_interface: MyInterface) 
  => this.changeInterface(_interface));