Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Event-Driven Shopping Features with Custom Emitter and Custom Dialogs in HarmonyOS

Tech 1

Project Structure Overview

entry/src/main/ets/
|---ui-components
|   |---TabNav.ets                      // Bottom tab navigation panel
|   |---SpecSelector.ets                // Product specification selection
|   |---PromoDialog.ets                 // Promotional overlay
|   |---ProductInfo.ets                  // Detailed product specs block
|   |---PriceTag.ets                     // Price display component
|---dummy-data
|   |---ProductDetailData.ets            // Product detail mock data
|   |---ProductListData.ets              // Product catalog mock data
|---data-models
|   |---ProductDetail.ets                // Product detail type definitions
|   |---ProductItem.ets                  // Product item type definitions
|---screens
|   |---ProductDetail.ets               // Product detail screen
|   |---Home.ets                          // Main catalog screen
|   |---ShoppingCart.ets                   // Cart screen
|---cart-feature
|   |---CartPanel.ets                     // Cart content panel
|   |---RecommendedList.ets                  // Recommended product grid
|---helpers
|   |---LogHelper.ets                    // Log utility wrapper
feature/event-bus/src/main/ets/
|---constants
|   |---EventKeys.ts                       // Event ID constants
|---helpers
|   |---feature
|   |   |---EventBusManager.ets           // Custom event emitter wrapper

Custom Event Bus Implementation

import emitter from '@ohos.events.emitter';
import { EventKeys } from '../../constants/EventKeys';
import Base from '@ohos.base';

interface EventPayload {
  itemId: number;
}

interface EventWrapper {
  payload: EventPayload;
}

export class EventBusManager {
  private cartItems: EventWrapper[] = [];

  // Trigger one-time promotional overlay display
  public triggerPromoOverlay(callback: Base.Callback<emitter.EventData>): void {
    const promoEventInner: emitter.InnerEvent = {
      eventId: EventKeys.PROMO_SHOW_ID
    };
    const promoEventPayload: emitter.EventData = {
      data: {
        triggerKey: EventKeys.PROMO_SHOW_ID
      }
    };
    emitter.once(promoEventInner, callback);
    emitter.emit(promoEventInner, promoEventPayload);
  }

  // Trigger one-time promotional overlay close
  public triggerPromoClose(callback: Base.Callback<emitter.EventData>): void {
    const closeEventPayload: emitter.EventData = {
      data: {
        triggerKey: EventKeys.PROMO_CLOSE_ID
      }
    };
    emitter.once(EventKeys.PROMO_CLOSE_ID, callback);
    emitter.emit(EventKeys.PROMO_CLOSE_ID, closeEventPayload);
  }

  // Subscribe to persistent cart add events
  public subscribeCartAdd(callback: (data: emitter.EventData) => void): void {
    const addEventInner: emitter.InnerEvent = {
      eventId: EventKeys.CART_ADD_ID
    };
    emitter.off(EventKeys.CART_ADD_ID);
    emitter.on(addEventInner, (eventData: emitter.EventData) => {
      callback(eventData);
    });
  }

  // Subscribe to persistent cart remove events
  public subscribeCartRemove(callback: (data: emitter.EventData) => void): void {
    emitter.off(EventKeys.CART_REMOVE_ID);
    emitter.on(EventKeys.CART_REMOVE_ID, (eventData: emitter.EventData) => {
      callback(eventData);
    });
  }

  // Publish cart add event
  public publishCartAdd(productId: number): void {
    const addEventInner: emitter.InnerEvent = {
      eventId: EventKeys.CART_ADD_ID
    };
    const addEventPayload: emitter.EventData = {
      data: {
        itemId: productId
      }
    };
    emitter.emit(addEventInner, addEventPayload);
  }

  // Publish cart remove event
  public publishCartRemove(listIndex: number): void {
    console.info('publishCartRemove index:', JSON.stringify(listIndex));
    const removeEventPayload: emitter.EventData = {
      data: {
        itemId: listIndex
      }
    };
    emitter.emit(EventKeys.CART_REMOVE_ID, removeEventPayload);
  }

  // Subscribe to persistent purchase count event
  public startPurchaseTracking(): void {
    emitter.on(EventKeys.PURCHASE_TRACK_ID, () => {});
  }

  // Retrieve current purchase count via listener count
  public fetchPurchaseCount(callback: (count: number) => void): void {
    callback(emitter.getListenerCount(EventKeys.PURCHASE_TRACK_ID));
  }

  // Reset purchase count by unsubscribing all purchase track listeners
  public resetPurchaseCount(callback: (count: number) => void): void {
    emitter.off(EventKeys.PURCHASE_TRACK_ID);
    callback(emitter.getListenerCount(EventKeys.PURCHASE_TRACK_ID));
  }
}

Feature Breakdown

  • **Promotional Overlay Display: Uses emitter.once() with a numeric event ID binds a one-time listener for the CustomDialogController trigger, auto-unsubscribing after execution.
  • **Promotional Overlay Close: Uses emitter.once() with a string event ID binds a one-time listener for dismissing the CustomDialogController, auto-unsubscribing after execution.
  • **Cart Item Addition: Uses emitter.on() with a numeric event ID for persistent listening, updating the cart item array whenever an add event is published.
  • **Cart Item Removal: Uses emitter.on() with a string event ID for persistent listening, updating the cart item array whenever a remove event is published.
  • **Purchase Count Tracking: Leverages emitter.getListenerCount() to track active purchase event listeners, displaying the result on the cart screen; resetting unsubscribes all listeners, returning a count of 0.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.