BehaviorSubject: next не является функцией

Я пытаюсь обмениваться данными между одноуровневыми компонентами и делаю это через общую службу. Когда первый компонент загружается, он получает список серверов из моего API и заполняет поле выбора всеми полученными серверами. Теперь я хочу уведомить другой свой компонент, когда пользователь выбрал новый сервер, чтобы я мог отобразить его подробности.

Это моя услуга:

@Injectable()
export class DashboardService {
    servers: Server[] = [];
    selectedServer = new BehaviorSubject<Server>(null);

    setServers(servers: Server[]) {
        this.servers = servers;
    }

}

Компонент с полем выбора:

@Component({
  selector: 'app-servers-select',
  template: `
    <div class="form-group">
      <label>Server</label>
      <select class="form-control" [(ngModel)]="this.dashboardService.selectedServer" (ngModelChange)="change($event)">
        <option disabled>-- Select server --</option>
        <option *ngFor="let server of servers" [ngValue]="server">{{server.Name}}</option>
      </select>
    </div>`,
  styleUrls: ['./servers-select.component.css'],
  providers: [ServerService]
})
export class ServersSelectComponent implements OnInit {
  servers: Server[] = [];

  constructor(private serverService: ServerService, private dashboardService: DashboardService) { }
  ngOnInit() {
    this.serverService
      .getServers()
      .subscribe(s => {
        this.servers = s;
        this.dashboardService.setServers(s);
        console.log(s);
      },
      e => console.log(e));

  }

  // todo: pass to dashboard component
  public change = (event: any) => {
    console.log(event);
    this.dashboardService.selectedServer.next(event);
  }

}

Компонент детали:

@Component({
  selector: 'app-server-details',
  template: `
  <section>
  <div class="form-group">
    <label>Description</label>
    <input type="text" [(ngModel)]="server">
  </div>
</section>
  `,
  styleUrls: ['./server-details.component.css']
})
export class ServerDetailsComponent implements OnInit {

  private server: Server = null;

  constructor(private dashboardService: DashboardService) { }

  ngOnInit() {
    this.dashboardService.selectedServer.subscribe((value: Server) => {
      console.log(value + 'lalalal');
      this.server = value;
    });
  }

}

Когда я выбираю новый сервер, метод change () вызывается правильно, но выдает следующую ошибку в консоли:

ОШИБКА Тип: Ошибка: _this.dashboardService.selectedServer.next не является функцией в ServersSelectComponent.change (servers-select.component.ts: 39)

Подписка, кажется, уже работает, так как я получаю «nulllalalal» в моей консоли. Что мне не хватает?

РЕДАКТИРОВАТЬ: - Я использую angular 5 и rxjs 5.5.2 - В моем DashboardService я импортирую BehaviorSubject следующим образом:

import { BehaviorSubject } from 'rxjs/BehaviorSubject';

person Christophe Loeys    schedule 20.12.2017    source источник
comment
Можете ли вы показать, откуда вы импортируете тему поведения в свой класс обслуживания приборной панели   -  person Karan Garg    schedule 20.12.2017
comment
@KaranGarg См. Мою правку :)   -  person Christophe Loeys    schedule 20.12.2017
comment
Можете ли вы попробовать этот импорт import {BehaviorSubject} из 'rxjs / Rx';   -  person Karan Garg    schedule 20.12.2017
comment
Не могли бы вы попробовать ввести свою переменную, например selectedServer: BehaviorSubject<Server> = new BehaviorSubject(null);   -  person    schedule 20.12.2017
comment
Не импортировать из rxjs / Rx   -  person Jota.Toledo    schedule 20.12.2017
comment
@KaranGarg все импортировать не буду (+ не работает, тестил ради)   -  person Christophe Loeys    schedule 20.12.2017
comment
@trichetriche безуспешно   -  person Christophe Loeys    schedule 20.12.2017


Ответы (1)


В шаблоне ServersSelectComponent у вас есть:

[(ngModel)]="this.dashboardService.selectedServer"

Это заменяет свойство службы selectedServer значением одной из опций.

Если вы хотите передавать изменения через тему RxJS, вы определенно не хотите использовать [(ngModel)] и запускать изменение вручную с помощью (change) прослушивателя событий, например (change)="change($event)".

person martin    schedule 20.12.2017
comment
Или вы можете использовать асинхронный канал в своей ngModel, я думаю, с [(ngModel)]="this.dashboardService.selectedServer | async", поскольку selectedServer является Observable. В любом случае, неплохо было найти этот @martin! - person ; 20.12.2017
comment
@martin Спасибо, это действительно была проблема! Однако я не вижу, как получить выбранный сервер сейчас, поскольку в моем предыдущем коде событие $ было бы равно моему серверу, а теперь это объект Event. Могу ли я теперь просто посмотреть, что такое текущий выбранный вариант? - person Christophe Loeys; 20.12.2017
comment
@trichetriche Нет, я действительно сомневаюсь, что это сработает. async просто подписывается на предыдущее выражение и выводит его результат. он ничего никуда не испускает. - person martin; 20.12.2017
comment
@ChristopheLoeys Вы можете подписаться на тему в компоненте и использовать [(ngModel)] с локальным свойством. Или, может быть, использование только [ngModel]="this.dashboardService.selectedServer | async" тоже может сработать, но я никогда не пробовал - person martin; 20.12.2017
comment
@ChristopheLoeys См. Эту angular.io/guide/template-syntax#inside-ngmodel - person martin; 20.12.2017
comment
@martin большое спасибо за вашу помощь, я многому научился из этого как новичок в Angular. :) - person Christophe Loeys; 20.12.2017