What is a better way and how to achieve sending object from one nested component to another

送分小仙女□ 提交于 2019-12-11 05:59:57

问题


I'm working on simple application about products, basically when user choose a product it should be sent to another component which would hold product.

Product is allways choosen one by one, I am NEVER sending a LIST! Only item by item!

So basically when I click on any of products in the middle of screen (Product food 1, Product food 2, Product food 3) it should be sent to the right part of the screen which is also separated component.

So my middle component looks like this:

<div *ngFor="let product of products;" class="product-holder">
  <div id="product.id" class="product" [style.background]="'url('+ product.imgUrl +')'">
    <p class="product-price">{{product.mpc | number}}</p>
    <p class="product-title">{{product.title}}</p>
  </div>
</div>

And a typescript code:

@Component({
  selector: 'app-products',
  templateUrl: './app-products.component.html',
  styleUrls: ['./app-products.component.css']
})
export class ProductsComponent implements OnInit {

  products: Article[];

  constructor(private _sharedService: SharedService) { }

  ngOnInit() {
    this._sharedService.getEventSubject().subscribe((param: any) => {
      if (param !== undefined) {
        this.theTargetMethod(param);
      }
    });
  }

  theTargetMethod(param) {
    // Here I am populating middle screen with products 
    this.products = param;
  }
}

And now I will post my right component which should receive product :

<div class="order-article">
  <div class="order-img"></div>
  <div class="order-title">
    <p>HERE I SHOULD WRITE ARTILE TITLE</p>
  </div>
  <div class="order-quantity pull-right">
    <span class="order-quantity-number">ARTICLE QUANTITY</span>
  </div>
</div>

export class ReceiptItemComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

So this 'right' component should receive clicked product from the middle, and I don't know how to do it, I red about @Input and @Output decorators and also about services, I guess @input and @output are right solution here because I'm sending one by one item?

But I don't know practically how to to solve this..

Any kind of help would be awesome

Thanks

AFTER fjc help:

<div *ngFor="let product of products;" class="product-holder" (click)="addReceiptItem(article)">
  <div id="product.id" class="product" [style.background]="'url('+ product.imgUrl +')'">
    <p class="product-price">{{product.mpc | number}}</p>
    <p class="product-title">{{product.title}}</p>
  </div>
</div>

As you can see guys:

1.) I added addReceiptItem method

2.) This method accepts clicked product:

addReceiptItem(receiptItem: Product) {
    this._sharedService.addReceiptItem(receiptItem);
  }

3.)Injected service '_sharedService' and created method there called also 'addReceiptItem'

4.)In my service I created BehaviorSubject like this: private receiptItem = new BehaviorSubject<any>(undefined);

4.)Method in a service looks like this:

addReceiptItem(receiptItems: Product) {
    this.arr1.push(receiptItems);
    this.receiptItem.next(this.arr1);
  }

This method is pushing clicked items to an array which will be send to a component that displays products

4.11) Added also method for getting data which returns BehaviorSubject:

getReceiptItem(): BehaviorSubject<any> {
    return this.receiptItem;
  }

5.)Edited Components that display products (code was posted also before doing anything - empty typescript file), and now it looks like this:

export class ReceiptItemComponent implements OnInit {

  constructor(private _sharedService: SharedService) { }

  receiptItems: Product[];

  ngOnInit() {
    this._sharedService.getReceiptItem().subscribe(products => this.receiptItems = products);
  }

}

Left is only to do destroy somehow?


回答1:


There are a couple of strategies to solve this. Overall, this is a state management problem: Multiple components are working on one joint state.

Option 1: Parent Component Manages State

This might be the most simple solution.

  • The parent component that holds all other components has a list of selected products.
  • The child components that let the user pick a product have an @Output() EventEmitter that emits when the user picks a product. The parent component listens to that output and adds the emitted product to its list of products.
  • The child components that display selected products have an @Input() array of products, based on which they display products. The parent component sets this input to its product list.

Option 2: State Service

Quickly implemented, but much cleaner separation of concerns than #1.

  • Implement an @Injectable StateService. It has a) a BehaviorSubject<Product[]> with a list of products, b) a method addProduct(product: Product) that adds a product to the current value of the BehaviorSubject and emits it.
  • Each component uses that service (constructor(stateService: StateService)). When the user picks a product, the component calls this.stateService.addProduct(product).
  • Components that display products listen to changes in the service's product list: this.stateService.products.subscribe(products => this.products = products) and display the products accordingly.

Option 3: Use a State Store Library

Use something like NGRX or Redux that takes care of state management for you.




回答2:


you can add a productsSelected array to your ProductsComponent, into which you push selected products when selected and then pass it as an Input to your ReceiptItemComponent ( or ReceiptItemsComponent ). Don't forget of [()] -- box of bananas, two way data binding - if you are going to change the quantity in the child component but you are going to save the array in your parent component.

You could use a service also, that holds the selectedProducts as a behaviorSubject and inject it in both components. Then you have to subscribe to changes in both components to receive the updates.




回答3:


This is exactly what I wrote my library RxCache for. It gives push data flow to Angular applications without having to add the complexity and ridiculous amount of boiler plate code involved in adding a store like NGRX.

https://github.com/adriandavidbrand/ngx-rxcache

Testbed on StackBlitz - https://stackblitz.com/edit/angular-3yqpfe

A redo of the official ngrx example app can be seen here on StackBlitz - https://stackblitz.com/edit/github-tsrf1f



来源:https://stackoverflow.com/questions/51079474/what-is-a-better-way-and-how-to-achieve-sending-object-from-one-nested-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!