@stcmd04236

Как выполнить привязку к данным в сервисе?

Добрый день! Изучаю angular2. Есть сервис OrdersService.ts
функция this.get(api.orders) выполняет загрузку данных из сервера.
@Injectable()
export class OrderService extends BasicService {

  orders : OrderViewModel[] = [];

  private 

  constructor(public http: Http, public notificationService: NotificationsService){
    super(http,notificationService);
  }

  getOrders() : Observable<Array<models.OrderViewModel>> {
    return this.get(api.orders);
  }
}


Сейчас его использую так:

main.ts

export class MainComponent implements OnInit {

  exportData: ExportModel[] = [];
  orderData : OrderViewModel[];


  constructor(config: NgbTabsetConfig, private orderService: OrderService, private exportService: ExportService) {
    config.justify = "center";
    config.type = "pills";    
   } 

   public options = {
    position: ['top','right']
  };

  ngOnInit() {
    this.orderService.getOrders().subscribe(r=>{
      this.orderData = r;
    });

    this.exportService.getExports().subscribe(r=>{
      this.exportData = r;
    });
  }

  onPlacemarkSelected(data:any){
    alert(data.length);
  }
}


А это main.html
<div class="col-6">
    <app-yamap [orderData] = "orderData" (placemarkSelection)="onPlacemarkSelected($event)"> </app-yamap>
 </div>


Компонент "yamap.component.ts" отображает эти данные на карте. В сеттере @orderData выполняется разбор данных и создается точки на карте.
И так хотелось бы сделать так чтобы при изменении данных изменились данные и на карте. Погуглив понял что для этого в сервисе ordersService сначало надо загрузить данные и использовать BehaviorSubject, Subject и Observable. Но не смог понят как все это делается. Подскажите пожалуйста как сделать так чтобы при изменении данных в компоненте менялись данные и в сервисе и обратно тоже т.е. при изменении данных в сервисе изменились данные и в компоненте.
  • Вопрос задан
  • 65 просмотров
Решения вопроса 1
search
@search
Мама говорит что я особенный
В принципе, это можно решить при помощи BehaviorSubject:

export class MainComponent implements OnInit {
  public orderData$ = new BehaviourSubject<OrderViewModel[]>([]);

  ngOnInit() {
    this.orderService.getOrders().subscribe(r=>{
      this.orderData$.next(r);
    });
  }
}


<app-yamap [orderData$]="orderData$"></app-yamap>

Дальше идёт приблизительный код компонента YaMap. Я не знаю какая идея стоит за этим компонентом, но хочу показать как он может принимать и изменять данные переданного в него BehaviourSubject.

Контроллер карты:
export class YaMap implements OnInit {
  @Input() orderData$: BehaviourSubject<OrderViewModel[]>;

  public addOrder(newOrder: OrderViewModel) {
    this.orderData$.next([...this.orderData$.getValue(), newOrder]);
  }
}


Вью карты:
<order-map-element *ngFor="let order of orderData$ | async">
  {{ order.price }}
</order-map-element>
<button (click)="addOrder({price: 14.99})">Add another order</button>


В данном конкретном случае можно вполне обойтись и без BehaviourSubject и вы шли по верному пути с событием (placemarkSelection)="onPlacemarkSelected($event)" (если я правильно вижу ход мысли). Идея в том чтоб компонент app-yamap просто отображал данные [orderData], но не менял их самостоятельно. Данные должны меняться извне по событию от компонента.

Почему лучше постараться обойтись без использования BehaviourSubject? Он усложняет код, делая компонент  менее пригодным для переиспользования. Вот замечательный пост Дена Абрамова об "умных" и "тупых" компонентах https://medium.com/@dan_abramov/smart-and-dumb-com... Эта идея применима ко всем компонентным подходам, не только к Реакту. Старайтесь делать как можно больше тупых компонентов и будете чаще кайфовать от гибкости и расширяемости собственного кода.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы