jedgard
jedgard

Reputation: 868

Triggering function on another component in the same module

I have a module called LegalModule, there are three components that subscribe to the same module, basically:

Both components have their own folder and each have an index.js file where they bootstrap like:

angular.module('LegalModule')
      .component('person', require('person.component.js')
      .controller('PersonController', require('person.controller.js');

and another file like

var component = {
   templateUrl: 'person-tamplate.html',
   controller: 'PersonController',
   bindings: {info: '<'}
}
module.exports = component;

Then in that controller i have something like :

var controller = ['PersonRepository','$stateParams', function(PersonRepository, $stateParams)
{
    var vm = this;
    //other code
    function Save(){
       //code that saved
    }

    function onSuccess(){
       //Let another component know this happened and call its refresh function.
    }

}];

Other component / controller

angular.module('LegalModule')
      .component('buildings', require('buildings.component.js')
      .controller('BuildingController', require('buildings.controller.js');

and the component

var component = {
    templateUrl: 'building-template.html'
    controller: 'BuildingController'
}

Controller

var controller = ['BuildingReader',function(BuildingReader){
    function refreshBuildings(){
         //this needs to be called on success of the save of the Person Repository
    }
}];

On the main tamplate:

<div class="LegalFacilities">
     <person></person>
     <buildings></buildings>
</div>

So i am new to components and i am not sure how to make in a way that when something is saved in the person controller, on it's success, that it can trigger the refresh function in the building controller to fire.

I really do not want to use $scope or anything like that , there is gotta be a cleaner way?. (not sure but i would appreciate any inputs).

Upvotes: 0

Views: 798

Answers (1)

Andrew Eisenberg
Andrew Eisenberg

Reputation: 28757

Since you have two components that are not on the same DOM element, your methods of communicating between them are more limited. You still have several ways that you can do it:

  1. onSuccess() emits an event on the $rootScope and all interested controllers listen for that event (just make sure to unsubscribe to the event on $destroy).
  2. Create one or more services that contain the all the non-UI shared application state. All controllers that need access to state inject the service that contains that state. And controllers can also $watch a variable on the service to be notified when something changes and something needs to be refreshed.
  3. Pass state around using the parent scope. Ie- each child scope declares a scope variable that is bound to the same variable in the parent scope. And if the state changes in one of the child scopes, the $digest cycle will ensure that the state is propagated to the other child scope.

In general, my preference is #2. The reason is that this keeps a clear separation between application state and UI state. And it becomes very easy to ensure that all parts of your application can share bits that they need to.

In your case, since you need to notify that an action happened, you can trigger this through changing a successHash number (an opaque number that just gets incremented on every save such that all watchers are notified).


Edit: a very simple example of sharing state using services.

angular.module('mymod').service('myService', function() {
  this.val = 9;
});

angular.module('mymod').directive('dir1', function(myService, scope) {
  scope.doSomething().then(res => myService.val = res);
});

angular.module('mymod').directive('dir2', function(myService, scope) {
  scope.$watch(() => myService.val, () => console.log(`It happened! ${myService.val});
});

Upvotes: 1

Related Questions