christianalfoni / flux-angular

Use the FLUX architecture with Angular JS
313 stars 50 forks source link

Any thoughts on integration with Angular 1.4 "new" Router? #44

Closed 5inline closed 8 years ago

5inline commented 9 years ago

Seems like the new router observes the "component" structure as well, so the $scope doesn't seem to be intended to be accessible. In short, I can't find a way to make "$listenTo" accessible in a controller.

New Router: https://github.com/angular/router

My Code:

VoteController.$inject = ['widgetStore','flux'];
function VoteController (widgetStore, flux)
{

    //
    // Internal
    // 
    var _self = this;

    // Defaults
    this.votes = widgetStore.getVotes();

    // Expose Functions
    this.submitVote = submitVote;

    //
    // Events
    // 

    this.$listenTo(widgetStore, 'widget.vote', onVote ); <--- errors out here 

    //
    // Functions
    // 

    function submitVote ()
    {
        console.log( 'submitVote' );

        flux.dispatch('submitVote', {});
    }

    function onVote ()
    {
        console.log( 'onVote' );
    }
}
christianalfoni commented 9 years ago

Hi @5inline,

I believe we researched this a bit with the "controllFor" syntax, which I believe does the same thing. The problem is that you need a way to unregister the listener when the controller is not in use anymore. You could use $rootScope, but $rootScope will never be "destroyed".

You know if there is some "destroy" event on these controllers? Or maybe they never will be destroyed? In that case it is perfectly okay to use $rootScope or you could wire up the listeners manually:

VoteController.$inject = ['widgetStore','flux'];
function VoteController (widgetStore, flux)
{

    //
    // Internal
    // 
    var _self = this;

    // Defaults
    this.votes = widgetStore.getVotes();

    // Expose Functions
    this.submitVote = submitVote;

    //
    // Events
    // 

    widgetStore.on('widget.vote', onVote ); <--- errors out here 

    //
    // Functions
    // 

    function submitVote ()
    {
        console.log( 'submitVote' );

        flux.dispatch('submitVote', {});
    }

    function onVote ()
    {
        console.log( 'onVote' );
    }
}

Again, you will get a memory leak if the controller is destroyed and created, but considering this is part of the routing it would never happen.

pramodsankarl commented 9 years ago

@christianalfoni This is interesting, do you have an on/off method on the store in order to regsiter to change events from store (I would prefer using them)? btw, I am referring to widgetStore.on. Actually new router has life cycle events like canDeactivate, deactivate, canActivate etc.. so you could actually detach them on canDeactivate.

christianalfoni commented 9 years ago

Hi again :-)

Yup, all the stores uses the EventEmitter2. So you can use any of those API methods to register and unregister events on the store.

Maybe we should document this a bit. Would you try it out? And give me a comment on it working as expected?

jrust commented 8 years ago

@5inline we've written a number of controllers in the new "component" structure (e.g. controllerAs) and the trick is to just inject $scope into your controller. You still use this for assigning data from the store to the view-model, but $scope is the object adds a listener. So, our controllers end up looking like:

function VoteController ($scope, widgetStore) {
  var vm = this;
  $scope.$listenTo(widgetStore, function() {
    vm.name = widgetStore.name;
  });
}