Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 角度4:订阅可观察的_Javascript_Angular_Typescript - Fatal编程技术网

Javascript 角度4:订阅可观察的

Javascript 角度4:订阅可观察的,javascript,angular,typescript,Javascript,Angular,Typescript,我正在从事一个项目,该项目要求加载和选择客户(不是用户,而是更像客户)。 不幸的是,我似乎无法订阅我在组件中加载的观测值。我已经尝试了在网上找到的所有可能的解决方案,但也许我对Angular的缺乏经验妨碍了我找到正确的解决方案 目前正在运行的功能: -在选择框中加载客户端 -为选择框中的选项提供客户端id值 -将客户端id发送到client.service并将所选客户端保存为可观察的 因此,我唯一的问题是组件没有注意到client.service中的可观察对象的变化 这是我的client.ser

我正在从事一个项目,该项目要求加载和选择客户(不是用户,而是更像客户)。

不幸的是,我似乎无法订阅我在组件中加载的观测值。我已经尝试了在网上找到的所有可能的解决方案,但也许我对Angular的缺乏经验妨碍了我找到正确的解决方案

目前正在运行的功能:
-在选择框中加载客户端
-为选择框中的选项提供客户端id值
-将客户端id发送到client.service并将所选客户端保存为可观察的

因此,我唯一的问题是组件没有注意到client.service中的可观察对象的变化

这是我的client.service.ts:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { ApiService } from '../api.service';
import { Client } from './client';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/filter';

@Injectable()
export class ClientService {

    clients$: Observable<Client[]>;
    client: Client;
    selectedClient$: Observable<Client[]>;

    constructor(private api: ApiService) {
        this.clients$ = this.getAll();
    }

    public getAll(): Observable<Client[]> {
        return this.api.get<Client[]>('clients');
    }

    public setSelectedClient(clientId: number) {
        this.clients$ = this.getAll();
        if (clientId == null) {
            // Do nothing
        } else {
            this.selectedClient$ = this.clients$.map(arr =>
            { return arr.find(client => client.id === clientId) });
        }
    }

    public getSelectedClient() : Observable<Client> {
        return this.selectedClient$;
    }

}
从'@angular/core'导入{Injectable};
从“rxjs/Observable”导入{Observable};
从“../api.service”导入{ApiService};
从“/Client”导入{Client};
导入'rxjs/add/operator/map';
导入'rxjs/add/operator/filter';
@可注射()
导出类客户端服务{
客户美元:可观察;
客户:客户;
selectedClient$:可观察;
构造函数(私有api:ApiService){
this.clients$=this.getAll();
}
public getAll():可观察{
返回此.api.get('clients');
}
public SetSelected客户端(客户端ID:编号){
this.clients$=this.getAll();
if(clientId==null){
//无所事事
}否则{
this.selectedClient$=this.clients$.map(arr=>
{返回arr.find(client=>client.id==clientId)};
}
}
public getSelectedClient():可观察{
返回此。selectedClient$;
}
}
My component(我的组件),带有注释位以显示修复我的问题的一些尝试:

import { Component, OnInit } from '@angular/core';
import { Observable } from "rxjs/Observable";
import { ClientService } from "../client/client.service";
import { Client } from "../client/client";
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/filter';

@Component({
    selector: 'app-left-menu',
    templateUrl: './left-menu.component.html',
    styleUrls: ['./left-menu.component.css']
})

export class LeftMenuComponent implements OnInit {

    selectedClient$ : Observable<Client>;
    client: Client = new Client();
    clients$ : Observable<Client[]>;

    constructor(private clientService: ClientService) {

    }

    ngOnInit() {
        // this.clientService.getSelectedClient().subscribe(selectedClient$ => {
        //     this.selectedClient$ = Observable.of(selectedClient$);
        // });
        // //
        // this.clientService.getAll().subscribe(clients$ => {
        //     this.clients$ = Observable.of(clients$);
        // });

        this.selectedClient$ = this.clientService.getSelectedClient();
        this.clients$ = this.clientService.getAll();
    }

    public setSelectedClient(clientId: number) {
        this.clientService.setSelectedClient(clientId);
    }

}
从'@angular/core'导入{Component,OnInit};
从“rxjs/Observable”导入{Observable};
从“./client/client.service”导入{ClientService};
从“./Client/Client”导入{Client};
导入'rxjs/add/operator/map';
导入'rxjs/add/operator/filter';
@组成部分({
选择器:“应用程序左菜单”,
templateUrl:'/左菜单.component.html',
样式URL:['./左菜单.component.css']
})
导出类LeftMenuComponent实现OnInit{
selectedClient$:可观察;
客户机:客户机=新客户机();
客户美元:可观察;
构造函数(专用clientService:clientService){
}
恩戈尼尼特(){
//this.clientService.getSelectedClient().subscribe(selectedClient$=>{
//this.selectedClient$=可观察的(selectedClient$);
// });
// //
//this.clientService.getAll().subscribe(客户端$=>{
//此.clients$=可观察的(clients$);
// });
this.selectedClient$=this.clientService.getSelectedClient();
this.clients$=this.clientService.getAll();
}
public SetSelected客户端(客户端ID:编号){
this.clientService.setSelectedClient(clientId);
}
}
我用来显示和选择客户端的html部分:

 <select #selectClient [ngModel]="selectedClient$ | async" 
   (ngModelChange)="setSelectedClient(selectClient.value)">
        <option *ngFor="let client of clients$ | async" [value]="client.id">
            {{ client.firstName }}
            {{ client.preposition }}
            {{ client.lastName }}
        </option>
 </select>

 <!-- Displaying selected client -->
 <h2 *ngIf="selectedClient$">{{(selectedClient$ | async)?.firstName}}
 </h2>

{{client.firstName}
{{client.preposition}}
{{client.lastName}
{{(selectedClient$| async)?.firstName}

如果有人能帮我解决这个问题,我将不胜感激,谢谢

您的问题源于您将
客户端$
selectedClient$
可观察属性分配给
LeftMenuComponent
的方式

ClientService
上的
setSelectedClient()
方法将更改服务的属性。但是,您的
LeftMenuComponent
ngOnInit()
只分配一次属性,并且
setSelectedClient()
中的更改不会反映在LeftMenuComponent上

若要实现这一点,不需要将特性重新指定给组件。您可以简单地将服务的属性直接绑定到模板中,如下所示:

 <select #selectClient [ngModel]="clientService.selectedClient$ | async" 
   (ngModelChange)="setSelectedClient(selectClient.value)">
        <option *ngFor="let client of clientService.clients$ | async" [value]="client.id">
            {{ client.firstName }}
            {{ client.preposition }}
            {{ client.lastName }}
        </option>
 </select>
export class LeftMenuComponent implements OnInit {

    client: Client = new Client();
    get selectedClient$(): Observable<Client> {
        return this.clientService.selectedClient$;
    }
    get clients$(): Observable<Client> {
        return this.clientService.client$;
    }

    constructor(private clientService: ClientService) {

    }

    ngOnInit() {
        // init things, but no assignment needed now
    }

{{client.firstName}
{{client.preposition}}
{{client.lastName}
另一种可能更简洁的方法是在组件上使用getter属性,而不是赋值,如下所示:

 <select #selectClient [ngModel]="clientService.selectedClient$ | async" 
   (ngModelChange)="setSelectedClient(selectClient.value)">
        <option *ngFor="let client of clientService.clients$ | async" [value]="client.id">
            {{ client.firstName }}
            {{ client.preposition }}
            {{ client.lastName }}
        </option>
 </select>
export class LeftMenuComponent implements OnInit {

    client: Client = new Client();
    get selectedClient$(): Observable<Client> {
        return this.clientService.selectedClient$;
    }
    get clients$(): Observable<Client> {
        return this.clientService.client$;
    }

    constructor(private clientService: ClientService) {

    }

    ngOnInit() {
        // init things, but no assignment needed now
    }
导出类LeftMenuComponent实现OnInit{
客户机:客户机=新客户机();
get selectedClient$():可观察{
返回此.clientService.selectedClient$;
}
获取客户端$():可观察{
返回此.clientService.client$;
}
构造函数(专用clientService:clientService){
}
恩戈尼尼特(){
//开始工作,但现在不需要分配任务
}

使用
[ngValue]
而不是
[value]
将客户端对象本身绑定到
[ngModel]
指令,我还使用
Subject
轻松通知新选择的客户端的其他订户:

client.service.ts:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

import { Client } from './client';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/filter';
@Injectable()
export class ClientService {

    clients$: Observable<Client[]>;
    client: Client;
    selectedClient$: Subject<Client> = new Subject<Client>();

    //...
    public setSelectedClient(client: Client) {
        if (client)
            this.selectedClient$.next(client);
    }
    //...
}
从'@angular/core'导入{Injectable};
从“rxjs/Observable”导入{Observable};
从'rxjs/Subject'导入{Subject};
从“/Client”导入{Client};
导入'rxjs/add/operator/map';
导入'rxjs/add/operator/filter';
@可注射()
导出类客户端服务{
客户美元:可观察;
客户:客户;
selectedClient$:Subject=新主题();
//...
公共设置选定客户端(客户端:客户端){
如果(客户)
this.selectedClient$.next(客户端);
}
//...
}
组件1.ts:

import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';

import { ClientService } from './client.service';
import { Client } from './client'


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

    selectedClient : Client;
    client: Client = new Client();
    clients$ : Observable<Client[]>;

    constructor(private clientService: ClientService) {

    }

    ngOnInit() {
        //...
        this.clients$ = this.clientService.getAll();
        this.clientService.selectedClient$.subscribe(console.log)
    }

    setSelectedClient(client : Client){
      this.selectedClient = client;
      this.clientService.setSelectedClient(client)
    }
}
从'@angular/core'导入{Component};
从“rxjs/Observable”导入{Observable};
从“/client.service”导入{ClientService};
从“./Client”导入{Client}
@组成部分({
选择器:“我的应用程序”,
templateUrl:“./app.component.html”,
样式URL:['./app.component.css']
})
导出类AppComponent{
selectedClient:Client;
客户机:客户机=新客户机();
客户美元:可观察;