Reputation: 121
I am playing around with angular 2. I want to build a global service that holds an interface. This interface can be changed through a HeaderComponent
. After the user changed the interface through the HeaderComponent
the interface has also been changed in another ChildComponent
. Therefor I worked with this answer found on stack overflow.
Let's say I have an interface and 2 different classes. Each of these classes are holding a different type of the interface.
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",
};
}
A global service is implementing this interface.
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);
}
}
}
}
}
Now the HeaderComponent
which is implemented as directive in app.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 { }
is able to change the interface through a select field:
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);
}
}
So far so good. After I changed the interface through my HeaderComponent
I want that the interface also be changed in another ChildComponent
that is going to be displayed through <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;
}
}
The problem is that the change of the interface through the HeaderComponent
is working but the interface doesn't change for the ChildComponent
. The changeInterface(interface: MyInterface)
function in my ChildComponent
isn't even called. Here the user is working with:
...
constructor(globalService: GlobalService) {
globalService.interfaceChanged.subscribe(_interface => this.changeInterface(_interface));
}
...
for the ChildComponent
. But if I do so there is an error within my sublime editor: "Parameter 'interface' implicitly has an 'any' type." So what am I doing wrong? What am I missing here?
Here you can see it on Plunker.
Upvotes: 2
Views: 1999
Reputation: 16758
The error in your editor
"Parameter 'interface' implicitly has an 'any' type."
is because you have strict TypeScript rule that prevents tsc from compiling your code. Either change the config by going to tsconfig.json
and turn off noImplicitAny
flag:
"noImplicitAny": false
Or add type to your interface in your subscribe
callback:
globalService.interfaceChanged.subscribe((_interface: MyInterface)
=> this.changeInterface(_interface));
Upvotes: 2