Я новичок в Angular2 и пытаюсь выяснить шаблон проектирования для родительских и дочерних компонентов для выполнения действий при изменении атрибута в службе, эта служба доступна глобально (объявлено в app.component.ts
в атрибуте providers
). Я использую:
- Угловой 2.2.1
- rxjs 5.0.0-бета.12
- машинопись 2.2.1
По сути, служба подключается к удаленному API, и этот API требует аутентификации с помощью токена. Сервис имеет общедоступные функции login()
и logout()
. Первый выполняет вызов API, а затем устанавливает закрытый атрибут token
в строку токена (если действителен логин) или '' (если неверный логин). Все другие общедоступные функции, которые вызывают API, используют этот закрытый токен.
Я предположил, что компонентам, использующим эту службу, не нужно видеть или использовать атрибут токена, потому что они должны быть «тупыми» для бизнес-процессов API и потреблять данные только через эту службу.
Сервис (упрощенный)
import { Injectable } from '@angular/core';
import { Http, Response, Headers, URLSearchParams } from '@angular/http';
import {Observable, Subject} from 'rxjs/Rx';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
@Injectable()
export class ApiService {
private url:string = 'my.service.com/';
private username: string;
private password: string;
private token: string;
constructor (private http: Http) {}
public getUsername(): string {
return this.username;
}
public setUsername(username: string) {
this.username = username;
}
public getPassword(): string {
return this.password;
}
public setPassword(password: string) {
this.password = password;
}
private setToken(token: string) {
this.token = token;
}
public login() {
let headers = new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' });
let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', this.username);
urlSearchParams.append('password', this.password);
let body = urlSearchParams.toString();
let url = this.url + 'user/login';
this.http.post(url, body, {headers: headers})
.map(res => {this.setToken(typeof res['token'] !== 'undefined' ? res['token'] : '');});
}
public logout() {
this.setToken('');
}
public getData() {
let headers = new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' });
let urlSearchParams = new URLSearchParams();
urlSearchParams.append('token', this.token);
let body = urlSearchParams.toString();
let url = this.url + 'data';
return this.http.get(url, body, {headers: headers})
.map(res => res.json());
}
app.component.ts
import { Component, ViewEncapsulation } from '@angular/core';
import { ApiService } from './services/api';
@Component({
selector: 'app',
encapsulation: ViewEncapsulation.None,
styleUrls: ['./app.component.global.scss'],
templateUrl: './app.component.html',
providers: [ApiService]
})
export class AppComponent {
constructor(private apiService: ApiService) {}
}
дочерний компонент
import { Component } from '@angular/core';
import { ApiService } from '../services/api';
@Component({
selector: 'child-component',
styleUrls: ['./child-component.component.scss'],
templateUrl: './child-component.component.html'
})
export class ChildComponent {
data: any[];
constructor(private apiService: ApiService) {}
}
Как мне получить компоненты (например, ChildComponent
для наблюдения за состоянием закрытого атрибута token
в ApiService
, а когда это не '', для вызова функций в службе, которым требуется токен (например, getData()
)? Возможно, я подхожу к этому в неправильно, но мои причины для такого подхода заключаются в том, что есть несколько дочерних компонентов, зависящих от действительного токена для выборки/отправки и отображения данных, и должны получать/отправлять данные только при успешном входе в систему. Я экспериментировал с различные ngOnChanges, Observerable, Subject.emit и т. д., но не смогли заставить эту работу работать.