Что лучше и как добиться отправки объекта из одного вложенного компонента в другой - PullRequest
0 голосов
/ 28 июня 2018

Я работаю над простым приложением о продуктах, в основном, когда пользователь выбирает продукт, его следует отправить другому компоненту, который будет содержать продукт.

Товар всегда выбирается один за другим, Я НИКОГДА не высылаю СПИСОК ! Только пункт за элементом !

Таким образом, в основном, когда я нажимаю на любой из продуктов в середине экрана ( Продукт питания 1, Продукт питания 2, Продукт питания 3 ), его следует отправить в правую часть экрана, которая также отдельный компонент.

Итак, мой средний компонент выглядит так:

<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>

И машинописный код:

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

А теперь я опубликую свой правильный компонент, который должен получить продукт:

<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() {
  }

}

Таким образом, этот «правильный» компонент должен получать по клику продукт с середины, и я не знаю, как это сделать, я рассказываю о @Input и @Output декораторах, а также о services, я думаю, @input и @output - правильное решение, потому что я отправляю один за другим элемент?

Но я практически не знаю, как это решить ..

Любая помощь будет отличной

Спасибо

ПОСЛЕ справки fjc:

<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>

Как видите ребята:

1.) Я добавил addReceiptItem метод

2.) Этот метод принимает выбранный товар:

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

3.) Внедренный сервис '_sharedService' и созданный там метод, называемый также 'addReceiptItem'

4.) В своем сервисе я создал BehaviorSubject вот так: private receiptItem = new BehaviorSubject<any>(undefined);

4.) Метод в сервисе выглядит так:

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

Этот метод помещает выбранные элементы в массив, который будет отправлен компоненту, отображающему продукты

4.11) Добавлен также метод для получения данных, который возвращает BehaviorSubject:

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

5.) Отредактированные компоненты, которые отображают продукты (код был опубликован также перед тем, как что-либо делать - пустой файл машинописи), и теперь это выглядит так:

export class ReceiptItemComponent implements OnInit {

  constructor(private _sharedService: SharedService) { }

  receiptItems: Product[];

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

}

Осталось только как-то уничтожить?

Ответы [ 3 ]

0 голосов
/ 28 июня 2018

вы можете добавить массив productsSelected в ваш ProductsComponent, в который вы помещаете выбранные продукты, когда они выбраны, и затем передаете его как входные данные для вашего ReceiptItemComponent (или ReceiptItemsComponent). Не забудьте о [()] - поле бананов, двухстороннее связывание данных - если вы собираетесь изменить количество в дочернем компоненте, но вы собираетесь сохранить массив в своем родительском компоненте.

Вы также можете использовать сервис, который содержит выбранные продукты в качестве объекта поведения и внедрить их в оба компонента. Затем вы должны подписаться на изменения в обоих компонентах, чтобы получать обновления.

0 голосов
/ 10 июля 2018

Это именно то, для чего я написал свою библиотеку RxCache. Это обеспечивает поток данных для приложений Angular без необходимости добавлять сложность и нелепый объем кода, который используется при добавлении магазина, такого как NGRX.

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

Испытательный стенд на StackBlitz - https://stackblitz.com/edit/angular-3yqpfe

Оформление официального примера приложения ngrx можно увидеть здесь, на StackBlitz - https://stackblitz.com/edit/github-tsrf1f

0 голосов
/ 28 июня 2018

Есть несколько стратегий для решения этой проблемы. В целом, это проблема управления состоянием: несколько компонентов работают в одном объединенном состоянии.

Вариант 1: родительский компонент управляет состоянием

Это может быть самое простое решение.

  • Родительский компонент, содержащий все остальные компоненты, имеет список выбранных продуктов.
  • Дочерние компоненты, позволяющие пользователю выбрать продукт, имеют EventEmitter @Output (), который генерируется, когда пользователь выбирает продукт. Родительский компонент прослушивает этот вывод и добавляет испущенный продукт в свой список продуктов.
  • Дочерние компоненты, отображающие выбранные продукты, имеют массив продуктов @Input (), на основе которого они отображают продукты. Родительский компонент устанавливает этот вход в свой список продуктов.

Вариант 2: Государственная служба

Быстро реализовано, но намного чище разделение проблем, чем # 1.

  • Реализация @Injectable StateService. У него есть а) BehaviorSubject<Product[]> со списком товаров, б) метод addProduct(product: Product), который добавляет товар к текущему значению BehaviorSubject и выдает его.
  • Каждый компонент использует эту услугу (constructor(stateService: StateService)). Когда пользователь выбирает продукт, компонент вызывает this.stateService.addProduct(product).
  • Компоненты, отображающие продукты, прослушивают изменения в списке продуктов службы: this.stateService.products.subscribe(products => this.products = products) и отображают продукты соответствующим образом.

Вариант 3: использовать библиотеку State Store

Используйте что-то вроде NGRX или Redux, которое позаботится об управлении состоянием для вас.

...