S
S
stcmd042362018-01-31 10:40:49
Angular
stcmd04236, 2018-01-31 10:40:49

How to bind to data in a service?

Good afternoon! I am learning angular2. There is a service OrdersService.ts
function this.get(api.orders) loads data from the server.

@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);
  }
}

Now I use it like this:
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);
  }
}

And this is main.html
<div class="col-6">
    <app-yamap [orderData] = "orderData" (placemarkSelection)="onPlacemarkSelected($event)"> </app-yamap>
 </div>

The "yamap.component.ts" component displays this data on a map. The @orderData setter parses the data and creates points on the map.
And so I would like to make it so that when the data changes, the data on the map also changes. Googling, I realized that for this, in the ordersService service, you first need to load the data and use the BehaviorSubject, Subject and Observable. But I couldn't figure out how it's done. Please tell me how to make it so that when the data in the component changes, the data changes in the service and vice versa, too, i.e. when the data in the service changes, the data in the component also changes.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Demian Smith, 2018-02-01
@stcmd04236

In principle, this can be solved using BehaviorSubject:

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

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

Next comes the approximate code for the YaMap component. I don't know what the idea is behind this component, but I want to show how it can accept and change the data of the BehaviourSubject passed to it.
Card Controller:
export class YaMap implements OnInit {
  @Input() orderData$: BehaviourSubject<OrderViewModel[]>;

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

View maps:
<order-map-element *ngFor="let order of orderData$ | async">
  {{ order.price }}
</order-map-element>
<button (click)="addOrder({price: 14.99})">Add another order</button>

In this particular case, you can completely do without the BehaviourSubject and you were on the right track with the event (placemarkSelection)="onPlacemarkSelected($event)" (if I see the train of thought correctly). The idea is to have the app-yamap component just display the [orderData] data, but not change it on its own. The data must be changed from the outside by an event from the component.
Why is it better to try not to use BehaviourSubject? It complicates the code, making the component less reusable. Here is a great post by Dan Abramov about "smart" and "dumb" components https://medium.com/@dan_abramov/smart-and-dumb-com...This idea applies to all component approaches, not just React. Try to make as many dumb components as possible and you will often enjoy the flexibility and extensibility of your own code.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question