Advanced

Events



Introduction

Events are powerful when you need to handle logic after something occurs in your application. Nylo's event system allows you to create, dispatch, and listen to events from anywhere in your application, making it easier to build responsive, event-driven Flutter applications.


Understanding Events

Event-driven programming is a paradigm where the flow of your application is determined by events such as user actions, sensor outputs, or messages from other programs or threads. This approach helps decouple different parts of your application, making your code more maintainable and easier to reason about.


Common Event Examples

Here are some typical events your application might use:

  • User registration completed
  • User logged in/out
  • Product added to cart
  • Payment processed successfully
  • Data synchronization completed
  • Push notification received

Creating an Event

You can create a new event using either the Nylo framework CLI or Metro:

# Using Nylo framework CLI
dart run nylo_framework:main make:event PaymentSuccessfulEvent

# Using Metro
metro make:event PaymentSuccessfulEvent

After running the command, a new event file will be created in the app/events/ directory.


Event Structure

Here's the structure of a newly created event file (e.g., app/events/payment_successful_event.dart):

import 'package:nylo_framework/nylo_framework.dart';

class PaymentSuccessfulEvent implements NyEvent {
  final listeners = {
    DefaultListener: DefaultListener(),
  };
}

class DefaultListener extends NyListener {
  handle(dynamic event) async {
    // Handle the payload from event
  }
}

Dispatching Events

Events can be dispatched from anywhere in your application using the event helper method.


Basic Event Dispatch

To dispatch an event without any data:

event<PaymentSuccessfulEvent>();

Dispatching with Data

To pass data along with your event:

event<PaymentSuccessfulEvent>(data: {
  'user': user,
  'amount': amount,
  'transactionId': 'txn_123456'
});

Broadcasting Events

By default, Nylo events are only handled by the listeners defined in the event class. To broadcast an event (making it available to external listeners), use the broadcast parameter:

event<PaymentSuccessfulEvent>(
  data: {'user': user, 'amount': amount},
  broadcast: true
);

Listening to Events

Nylo provides multiple ways to listen for and respond to events.


Using the listenOn Helper

The listenOn helper can be used anywhere in your application to listen for broadcasted events:

NyEventSubscription subscription = listenOn<PaymentSuccessfulEvent>((data) {
  // Access event data
  final user = data['user'];
  final amount = data['amount'];
  
  // Handle the event
  showSuccessMessage("Payment of $amount received");
});

Using the listen Helper

The listen helper is available in NyPage and NyState classes. It automatically manages subscriptions, unsubscribing when the widget is disposed:

class _CheckoutPageState extends NyPage<CheckoutPage> {
  @override
  get init => () {
    listen<PaymentSuccessfulEvent>((data) {
      // Handle payment success
      routeTo(OrderConfirmationPage.path);
    });
    
    listen<PaymentFailedEvent>((data) {
      // Handle payment failure
      displayErrorMessage(data['error']);
    });
  };
  
  // Rest of your page implementation
}

Unsubscribing from Events

When using listenOn, you must manually unsubscribe to prevent memory leaks:

// Store the subscription
final subscription = listenOn<PaymentSuccessfulEvent>((data) {
  // Handle event
});

// Later, when no longer needed
subscription.cancel();

The listen helper automatically handles unsubscription when the widget is disposed.


Working with Listeners

Listeners are classes that respond to events. Each event can have multiple listeners to handle different aspects of the event.


Adding Multiple Listeners

You can add multiple listeners to your event by updating the listeners property:

class PaymentSuccessfulEvent implements NyEvent {
  final listeners = {
    NotificationListener: NotificationListener(),
    AnalyticsListener: AnalyticsListener(),
    OrderProcessingListener: OrderProcessingListener(),
  };
}

Implementing Listener Logic

Each listener should implement the handle method to process the event:

class NotificationListener extends NyListener {
  handle(dynamic event) async {
    // Send notification to user
    final user = event['user'];
    await NotificationService.sendNotification(
      userId: user.id,
      title: "Payment Successful",
      body: "Your payment of ${event['amount']} was processed successfully."
    );
  }
}

class AnalyticsListener extends NyListener {
  handle(dynamic event) async {
    // Log analytics event
    await AnalyticsService.logEvent(
      "payment_successful",
      parameters: {
        'amount': event['amount'],
        'userId': event['user'].id,
      }
    );
  }
}

Global Event Broadcasting

If you want all events to be broadcasted automatically without specifying broadcast: true each time, you can enable global broadcasting.


Enabling Global Broadcasting

Edit your app/providers/app_provider.dart file and add the broadcastEvents() method to your Nylo instance:

class AppProvider implements NyProvider {
  @override
  boot(Nylo nylo) async {
    // Other configuration
    
    // Enable broadcasting for all events
    nylo.broadcastEvents();
  }
}

With global broadcasting enabled, you can dispatch and listen to events more concisely:

// Dispatch event (no need for broadcast: true)
event<PaymentSuccessfulEvent>(data: {
  'user': user,
  'amount': amount,
});

// Listen for the event anywhere
listen<PaymentSuccessfulEvent>((data) {
  // Handle event data
});