Git Product home page Git Product logo

event-aggregator's Introduction

Aurelia

License: MIT npm version CircleCI TypeScript Twitter

Backers on Open Collective Sponsors on Open Collective Discord Chat

Aurelia 2

This is the Aurelia 2 monorepo, containing core and plugin packages, examples, benchmarks, and documentation for the upcoming major version of everybody's favorite modern JavaScript framework, Aurelia.

Introduction

Aurelia is a modern, front-end JavaScript framework for building browser, mobile, and desktop applications. It focuses on aligning closely with web platform specifications, using convention over configuration, and having minimal framework intrusion. Basically, we want you to just write your code without the framework getting in your way. 😉

Aurelia applications are built by composing a series of simple components. By convention, components are made up of a vanilla JavaScript or Typescript class, with a corresponding HTML template.

//app.js
export class App {
  welcome = "Welcome to Aurelia";

  quests = [
    "To seek the holy grail",
    "To take the ring to Mordor",
    "To rescue princess Leia"
  ];
}
<!-- app.html -->
<form>
  <label>
    <span>What is your name?</span>
    <input value.bind="name & debounce:500">
  </label>

  <label>
    <span>What is your quest?</span>
    <select value.bind="quest">
      <option></option>
      <option repeat.for="q of quests">${q}</option>
    </select>
  </label>
</form>

<p if.bind="name">${welcome}, ${name}!</p>
<p if.bind="quest">Now set forth ${quest.toLowerCase()}!</p>

This example shows you some of the powerful features of the aurelia binding syntax. To learn further, please see our documentation.

Feeling excited? Check out how to use makes to get started in the next section.

Note: Please keep in mind that Aurelia 2 is still in beta. A number of features and use cases around the public API are still untested and there will be a few more breaking changes.

Getting Started

First, ensure that you have Node.js v8.9.0 or above installed on your system. Next, using npx, a tool distributed as part of Node.js, we'll create a new Aurelia 2 app. At a command prompt, run the following command:

npx makes aurelia

This will cause npx to download the makes scaffolding tool, along with the aurelia generator, which it will use to guide you through the setup process. Once complete, you'll have a new Aurelia 2 project ready to run. For more information on Aurelia's use of makes, see here. If you aren't interested in taking our preferred approach to generating a project, you can also see the examples folder in this repo for pure JIT setups (no conventions) with various loaders and bundlers.

Documentation

You can read the documentation on Aurelia 2 here. Our new docs are currently a work-in-progress, so the most complete documentation is available in our getting started section. If you've never used Aurelia before, you'll want to begin with our Quick Start Guide.

Contributing

If you are interested in contributing to Aurelia, please see our contributor documentation for more information. You'll learn how to build the code and run tests, how best to engage in our social channels, how to submit PRs, and even how to contribute to our documentation. We welcome you and thank you in advance for joining with us in this endeavor.

Staying Up-to-Date

To keep up to date on Aurelia, please visit and subscribe to the official blog and our email list. We also invite you to follow us on twitter. If you have questions, have a look around our Discourse forum. For chat on Aurelia 2, join our new Aurelia 2 community on Discord. If you'd like to join the growing list of Aurelia sponsors, please back us on Open Collective.

License

Aurelia is MIT licensed. You can find out more and read the license document here.

event-aggregator's People

Contributors

aaike avatar bryanrsmith avatar cmichaelgraham avatar derekpitt avatar doktordirk avatar eisenbergeffect avatar fkleuver avatar gamtiq avatar martingust avatar micahzoltu avatar plwalters avatar pndewit avatar strahilkazlachev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

event-aggregator's Issues

Feature Request - Method to get all Event Names

I'm submitting a feature request

  • Library Version:
    1.0.3

Please tell us about your environment:

  • Operating System:
    Windows 10

  • Node Version:
    12.14.0

  • NPM Version:
    6.13.4

  • JSPM OR Webpack AND Version
    WebPack

  • Browser:
    all | Chrome XX | Firefox XX | Edge XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView

  • Language:
    all

Current behavior:
There are no ways of accessing all the events, internally I can see the eventLookup object being used but there are no methods that we can call to get this object/list and it seems to be a private object.

Expected/desired behavior:
It would be nice to have a method to at least access the eventLookup so that we could perhaps do an Object.keys on it, or even better a method that would return a string array of all the events that were created.

  • What is the expected behavior?

  • What is the motivation / use case for changing the behavior?
    For my use case, I have a plugin library Aurelia-Slickgrid and I would like to loop through all the events I used in the plugins and for some of them (with a certain prefix or keyword) re-expose them to the outside through a dispatch event. So it's kind of a way to take some internal plugin events and expose some of them to the outside (user of my plugin). Currently, to do this, I have to go through every event that I want to re-expose 1 by 1 and do a dispatch event from there, but it would be so useful to just loop through the list and filter out only the ones I want to re-expose.

Use Case Example

// current usage, I have about 10 types of Event I would like to re-expose
this.pluginEa.subscribe('excelExportService:beforeExport', (triggered: boolean) => {
   this.elm.dispatchEvent(DOM.createCustomEvent(`asg-on-before-excel-export`, {
          bubbles: true,
          detail: triggered
   }));
});
// View
<aurelia-slickgrid 
    grid-id="grid1" 
    column-definitions.bind="columnDefinitions" 
    grid-options.bind="gridOptions"
    dataset.bind="dataset" 
    asg-on-before-excel-export.delegate="spinner = true"
    asg-on-after-excel-export.delegate="spinner = false">
  </aurelia-slickgrid>

So if I could loop through all Events that start with asg, I could assign a dispatchEvent and be done with it, instead of having to type them 1 by 1.

Chrome console not outputting error thrown in subscribe callback

I'm submitting a bug report

  • Library Version:
    1.0.0

Please tell us about your environment:

  • Operating System:
    OSX 10.12.1

  • Node Version:
    6.6.0

  • NPM Version:
    3.10.3

  • JSPM OR Webpack AND Version
    JSPM 0.16.47

  • Browser:
    Chrome 54.0.2840.71 (64-bit)

  • Language:
    ESNext

Current behavior:
If an error is thrown in a subscribe callback e.g.

eventAggregator.subscribe('some_event', ()=>{
    //some error here
})

error is not output in chrome console. If a breakpoint is set, then error can be seen being caught by catch statement. Please see image below

screen shot 2016-10-27 at 15 31 52

Expected/desired behavior:

Runnable gist

check app.js

  • What is the expected behavior?
  • What is the motivation / use case for changing the behavior?

Fix 1.0.3 Release Tag

Very minor, but looks like there is a typo in the release tag for 1.0.3. It is tagged 1.3.1, but should be 1.0.3

aurelia-event-aggregator Not Triggering Event Handler When "messageType" is an Object

I'm submitting a bug report

  • Library Version:
    [email protected]

  • Operating System:
    Windows 10 Pro

  • Node Version:
    v6.10.2

  • NPM Version:
    3.10.10

  • JSPM OR Webpack AND Version
    JSPM 0.16.52
    Running against local jspm install

  • Browser:
    Chrome Version 57.0.2987.133 (64-bit)

  • Language:
    ESNext

Current behavior:
When using the event aggregator to publish an event where the "event" parameter is an instantiated object, I receive the error: "[event-aggregator] TypeError: Right-hand side of 'instanceof' is not callable". This happens in the if statement of the handle() function of the Handler class (ln. 13 of the index.js file) because the statement message instanceof this.messageType fails every time as "message" is exactly equal to "messageType" and is not an instance of it.

Also, the implementation of the invokeHandler() function inside the publish() function (ln. 84) is flawed because an "event" object is passed as the "data" parameter and actual event data cannot currently be passed to the handle() function of the Handler class.

Expected/desired behavior:
I should be able to use the aurelia-event-aggregator module to subscribe to events using an instantiated class object as the event type. When I publish an event with an instantiated class object as the "event" or "messageType" parameter, the event aggregator should locate all subscribers to the event and trigger them while passing in any given data.

  • What is the motivation / use case for changing the behavior?
    I was following through Brian Noyes' PluralSight Tutorial on Aurelia and I came across this bug in module 10. I've fixed this issue in my own source code. After submitting this issue, I will submit a pull request to check in the fix. Please view my gist for a copy of my source code correcting this issue.

Thanks for all your hard work. LOVE AURELIA!
-Anthony

Subscribe to event with function call

Shouldn't this work?

Within the constructor:
this.myProperty = 'Test value';
eventAggregator.subscribe(SomeEvent, this.handleEvent);

handleEvent(event) {
      let data = event.data;
      console.log(this.myProperty );
}

I can access the event object, but when I try to access this.myProperty I get an error: ERROR [event-aggregator] TypeError: Cannot read property 'myProperty' of null.

How to subscribe to window events?

I walked through the docs and wondered, what the Aurelia way of subscribing to window events may be. Say, I want to execute the callback foo() on orientationchange. How would I do that?

Could you extend the docs as well?

P.S. (Yes, I've read the Contribution docs but I want to have the answer findable somwhere without having to create just another account. So pardon me not asking on Stack Overflow or Gitter).

Subscribe in routing activate

Not sure if this is a bug or if I'm doing somethig wrong.

I subscribe to an event (a channel in this case) in the activate() hook. When I route to the same view, but with different parameter (like id), the activate hook is called again and then I have two (2) subscriptions on the channel (and then 3 and then 4 etc.). Not sure if it's clear what I mean..? :)

Anyway, I moved the subscribe() call to the constructor instead, and then it works. Not sure if this is the right way to do it? Or should there be an unsubscribe function which could be called in the deactivate hook?

Thanks!

event-aggregator not working with dependency injection

When injecting the event-aggregator, and trying to publish an event, I receive the following error...

Uncaught TypeError: Cannot read property 'publish' of undefined.

also, when I console.log(eventAggregator) "undefined" is printed.

I have been going crazy trying to figure out why this isn't working... Any help would be greatly appreciated.

Here is my code...

import {inject} from 'aurelia-framework';
import {UIDialog} from 'aurelia-ui-framework';
import {EventAggregator} from 'aurelia-event-aggregator';

@inject(EventAggregator)
export class DeleteConfirmation extends UIDialog {

  title = "confirm delete operation";
  content = "Are you sure you want to delete this item?";
  info = "";
  modal = true;
  resize = false;
  height = 100;

  constructor(eventAggregator) {
    super();
    this.eventAggregator = eventAggregator;
    console.log(eventAggregator);
  }

  no(){
    this.eventAggregator.publish('confirm-delete-dialog-close', {result: false});
    super.close();
  }

  yes(){
    this.eventAggregator.publish('confirm-delete-dialog-close', {result: true});
    super.close();
  }
}

Improve Error Message

Hi,
I just made a mistake in my application that caused the EA to report this error:

ERROR [event-aggregator] TypeError: subscribers[i] is not a function()

After adding some console statements into the aurelia-event-agregator source code I discovered my EA.subscribe call was not passing in a function because I had not made the function yet. Simple mistake but made harder due to the error message.

It is an obvious mistake now that I look at it and the error message should have had me looking in the right direction, but it's late, I was coming back to old code, and you know how it goes.

Could this error message be more descriptive?

The function call is at line 57 of event-aggregator/src/index.js.

Please kill this if you think I am being a little nuts.

Ability to subscribe / publish array of channels

Would like to be able to publish / subscribe to multiple channels at the same time.

For example:

    this.eventAggregator.publish(['channel1','channel2','channel3'], payload);

or

    this.eventAggregator.subscribe(['channel1','channel2','channel3'], payload => {
        ...
    });

My use case deals more with the subscribe side, but for symmetry the publish should be possible as well.

Feat proposal: decorators

I made a couple of decorators for EventAggregator:
You put a @handle decorator on the event handler, and you put a @subscribeon the attached() to register all the subscriptions on attach:

Here is a usage sample:

@subscribe
attached() {
}

@unsubscribe
detached() {
}

@handle(‘store:users:changed’)
usersChanged(msg) {
     // do something
}

@handle(‘store:other_event’)
otherEventHandler(event) {
     // do something
}

I'm not sure about the names, maybe @handleEvent, @subscribeEventHandlers... would be better.

Here is the current code:

import {Metadata} from './metadata.js'
import {Container} from 'aurelia-framework';
import {EventAggregator} from 'aurelia-event-aggregator';

export function handle(...properties) {
    return function(target, key, descriptor) {
        // Get a unique (using Symbol) metadata store to avoid collisions
        let metadata = Metadata.getOrCreateMetadata(target);
        // Store each event / handler pairs
        properties.forEach( prop => metadata.handlers.push( {msg: prop, handler: key} ));

        return descriptor;
    }
}

export function subscribe() {
    let eventAggregator = Container.instance.get(EventAggregator);

    return function(target, key, descriptor) {
        // Override the decorated method in order to subscribe to all the registered events
        return {
            ...descriptor,
            value: function() {
                console.log('subscribe');
                let metadata = Metadata.getOrCreateMetadata(target);
                let handlers = metadata.handlers;
                for(let i=0; i < handlers.length; ++i) {
                    metadata.subscriptions.push(eventAggregator.subscribe(handlers[i].msg, (...args) => {
                        this[handlers[i].handler].apply(this, args)
                    }));
                }
                // Call the original method
                descriptor.value.apply(this, arguments);    
            }
        }
    }
} 

export function unsubscribe() {
    return function(target, key, descriptor) {
        // Override the decorated method in order to dispose of all subscriptions.
        return {
            ...descriptor,
            value: () => {
                let metadata = Metadata.getOrCreateMetadata(target);
                metadata.subscriptions.forEach( (subscription) => {
                    subscription.dispose();
                });
                // Call the original method
                descriptor.value.apply(this, arguments);    
            }
        }
    }
} 

and the metadata.js:

export class Metadata {
    static metadata = Symbol('eventAggregatorMetadata');

    static getOrCreateMetadata(target) {
        if(target[this.metadata] === undefined) {
            target[this.metadata] = new Metadata();
        }

        return target[this.metadata];
    }

    static exists(target) {
        return target[this.metadata] !== undefined && target[this.metadata] instanceof Metadata;
    }

    constructor() {
        this.handlers = [];
    this.subscriptions = [];
    }
}

What do you think, should I PR this as it is? What about the names?

Dispose all... (possibly scoped to the current view model)

I'm curious if there is a way to dispose all subscriptions?

Currently I'm storing a reference to them all and then disposing them individually but it would be nice there were an option to dispose them all, perhaps scoped to the current view model. so the deactivate method becomes something like

deactivate() {
  this.ea.disposeAll();
}

rather than

deactivate() {
  this.event1.dispose();
  this.event2.dispose();
  this.event3.dispose();
  this.event4.dispose();
  this.event5.dispose();
  this.event6.dispose();
}

(I know I could store all the events in an array and dispose them with a looping helper class but that feels like I'm doing the EventAggregators job :P)

question - Subscribe by interface to match multiple event types?

event model:

class PaneSizeToggledEvent : IMyEvent {
}

publisher:
this._eventAgg.publish(new PaneSizeToggledEvent(!pShow));

consumer:

 this._eventAgg.subscribe(IMyEvent,
            (pEvent: IMyEvent) => {
                this._logger.debug("Instance of one of my events", pEvent);
            });

is this supported ? also, how does the event type subscription work if I subscribe using just type PaneSizeToggledEvent , is it typeof and just the name of the class ?

Trouble with jspm dl-loader

After cloning this repo and running jspm dl-loader I get:

     Looking up loader files...

err  Error downloading loader files.
Potentially unhandled rejection [2] TypeError: Install of %aurelia-tools% to `^0.1.3` has no registry property provided.
    at /usr/local/lib/node_modules/jspm/lib/package.js:280:13
    at Array.forEach (native)
    at processDeps (/usr/local/lib/node_modules/jspm/lib/package.js:263:21)
    at setDefaults (/usr/local/lib/node_modules/jspm/lib/config/package.js:125:28)
    at PackageJSON.read (/usr/local/lib/node_modules/jspm/lib/config/package.js:112:3)
    at /usr/local/lib/node_modules/jspm/lib/config.js:74:25
    at tryCatchReject (/usr/local/lib/node_modules/jspm/node_modules/systemjs/node_modules/es6-module-loader/dist/es6-module-loader.src.js:1183:30)
    at runContinuation1 (/usr/local/lib/node_modules/jspm/node_modules/systemjs/node_modules/es6-module-loader/dist/es6-module-loader.src.js:1142:4)
    at Fulfilled.when (/usr/local/lib/node_modules/jspm/node_modules/systemjs/node_modules/es6-module-loader/dist/es6-module-loader.src.js:930:4)
    at Pending.run (/usr/local/lib/node_modules/jspm/node_modules/systemjs/node_modules/es6-module-loader/dist/es6-module-loader.src.js:821:13)

Running JSPM 0.15.5
node 0.12
npm 2.5.1

Publish order

I have parent component and its child component, both subscribed on same event through EA. When event is published, callback in child component is called before parent callback. I would expect that callbacks are fired in same order as they were registered. Wouldn't be better if EA uses FIFO instead of LIFO?

There is no way to unsubscribe an event

I'm submitting a feature request

  • Library Version:
    1.0.1

Please tell us about your environment:

  • Operating System:
    Linux (distro)

  • Node Version:
    8.4.0

  • NPM Version:
    5.5

  • Browser:
    Chrome 60.1

  • Language:
    TypeScript 2.40

Current behavior:

Our use case is: A controller will subscribe a event in attached() and when it happens, a dialog will open. Now, the controller detaches and attaches again, when the event happens, two of the same dialog opens.

There is no way to un-subscribe a handler. Hence if a controller subscribe an event, and the controller detaches and attaches again, there are two handlers registered on the eventLookup.

Expected/desired behavior:

  • What is the expected behavior?

Un-subscribe event on detached
so that subscribe on attached() method.

  • What is the motivation / use case for changing the behavior?
    Well, this could improve our code. We are now hacking into to eventLookup and manually remove the handler in detached method.

subscribe should return subscriptionInfo object with an unsubscribe/cancel function

The api right now around how to un subscribe is not really obvious and I see many people in Gitter asking how to do it which lead to something like this:

var subscribe = ea.subscribe(''test"); // Subscribe
subscribe(); // Unsubscribe

Which is really weird when you look back at the code and does not reflect at all what is really going on.

Ideally, the Event Aggregator should return a subscription object such as:

{
  channel: 'test',
  subscribedAt: dateProperty,
  unsubscribe: function() {...}
}

So people can do:

var sub = ea.subscribe(''test"); // Subscribe
sub.unsubscribe(); // Unsubscribe

What do you think ?

it is seems not work in aurelia plugin

I write a plugin(back-nav-bar)

import {bindable,inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
import {EventAggregator} from 'aurelia-event-aggregator';
import {BackMessage2} from '../channel_msg/backMessage';
@bindable('router')
@bindable({ name: 'backIcon', defaultValue: 'mdi-navigation-arrow-back' })
@inject(EventAggregator,Router)
export class BackNavBar{
    constructor(ea,rt) {
        this.ea = ea;
        this.rt = rt;
        this.ea.subscribe(BackMessage2, msg => {console.log('test2');});
        this.ea.subscribe(BackMessage2, msg => {console.log('test3');});
    }
    back() {
        this.ea.publish(new BackMessage2());
        //this.rt.navigateBack();
    }
}
<template>
    <nav class="white" role="navigation">
        <div class="nav-wrapper container">
            <a id="logo-container" href="#" class="brand-logo">${header}</a>
            <a href="#" class="button-collapse" click.trigger="back()">
                <i class="${backIcon}"></i>
            </a>
        </div>
    </nav>
</template>

when click it is console 'test2' and 'test3',but when i use this plugin in other page

import {inject} from 'aurelia-framework';
import {EventAggregator} from 'aurelia-event-aggregator';
import {BackMessage2} from '../channel_msg/BackMessage';
@inject(EventAggregator)
export class Index{
    constructor(ea) {
        this.ea = ea;
        this.ea.subscribe(BackMessage2, msg => {console.log('test1');});
    } 
}
<template>
    <back-nav-bar></back-nav-bar>
</template>

when i click it is just console 'test1' 'test2'. why?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.