Обновить отображение товаров в корзине с помощью Subject/Observable

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

Функциональность, которую я ищу, проста: когда я добавляю элемент и он попадает в локальное хранилище, число на моей панели навигации рядом с логотипом корзины покупок должно увеличиваться на 1. Я знаю, что это можно обработать с помощью Observables и Subjects, я просто с трудом понимаю это. Для начала я переместил код из компонента в сервис, потому что полагаю, что это позволит обоим компонентам взаимодействовать с ним. Я могу правильно добавить элементы в локальное хранилище с помощью службы, но после этого я застрял, где мне нужно отслеживать количество элементов, добавленных с помощью службы.

Вот служба:

@Injectable({
  providedIn: 'root'
})
export class MenuService {
  public apiRoot: string = `http://localhost:3000`;
  orders;

  constructor(private http: HttpClient) { }

  order(id, name, options, price) {
    //confirm the order is correct
    const orderConfirmed = confirm("Add this item to your cart?");

    if (orderConfirmed) {
    let order = new Order(id, name, options, price)   

    //get and set any existing orders from local storage or set to a blank array if there are none
    this.orders = localStorage.getItem('order') ? JSON.parse(localStorage.getItem('order')) : [];

    //push to our orders array
    this.orders.push(order)

    //store in localStorage
    localStorage.setItem('order', JSON.stringify(this.orders)) 
    }
  }

Тогда вот мой navbar.ts:

export class NavbarComponent implements OnInit {
  itemsInCart;
  constructor() { }

  getItemsInCart() {
    this.itemsInCart = JSON.parse(localStorage.getItem('order'))
  }

  ngOnInit() {
    this.getItemsInCart();
  }

}

Прямо сейчас я просто извлекаю элементы непосредственно из локального хранилища и отображаю их, но, очевидно, это не будет работать в режиме реального времени, если я добавлю другие элементы, в основном я хочу сделать свой компонент навигационной панели, который находится над выходом маршрутизатора. чтобы иметь возможность подписаться на свойство this.orders в MenuService, чтобы я мог отслеживать длину this.orders в режиме реального времени, когда пользователь добавляет товары в корзину. Извините, если это кажется очевидным, все еще учусь!

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
1 346
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

вместо этого не используйте хранилище localstorage в памяти, когда вы закрываете вкладку браузера или данные обновления уничтожаются (уровень эксперта вы должны использовать Ngrx Store)

check Unrelated Components: Sharing Data with a Service here

хранилище.service.ts

export class StorageService {
  private foo: String;
  public fooChanged$: EventEmitter<any>; // For Communication between components
  constructor() {
    this.fooChanged$ = new EventEmitter(); // For Communication between components 
  }

  public emitFooChange(): void {// For Communication between components
    this.fooChanged$.emit();
  }

  setFoo(data: String) {
    this.foo = data;
  }

  getFoo(): Number {
    return this.foo;
  }
}

компонент.ts

constructor(private storageService: StorageService){}
ngOnInit(){
  this.storageService.setFoo("Foo");
  console.info('foo', this.storageService.getFoo());
}
Ответ принят как подходящий

Добавьте тему в свою службу, вызовите ее в методе заказа и подпишитесь на нее в своем компоненте.

хранилище.service.ts

orders
ordersChanged = new Subject<any>()

order(){
   //your code
   this.ordersChanged.next(this.orders)
    }

компонент.ts

itemsInCart

constructor(private storageService: StorageService){}

ngOnInit(){
   this.storageService.ordersChanged.subscribe(items => itemsInCart = items)
}

Это было идеально, это помогло мне лучше понять предметы после того, как я немного повозился с ним, и я также смог убедиться, что цена обновляется, подписавшись на тот же предмет в другом компоненте, очень полезно. Большое спасибо @RadekF!

Kyle Scott 04.05.2019 03:22

Я надеюсь, что вы используете фреймворк Angular, сервисы следуют шаблону singleton, поэтому будет только один экземпляр этого свойства. (Нет необходимости использовать наблюдаемый шаблон.)

Создайте сервис со свойством cart_items_count. В конструкторе присвойте значение (реальное количество, извлеченное из локального хранилища) свойству. Когда вы добавляете в корзину, увеличьте cart_items_count также на 1.

Другие вопросы по теме