Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular-- What is the best practice for calling a controller-specific function from another controller?

I'm relatively new to Angular. I'm making an app that takes data in a form and saves it as an object in MongoDB. I have a controller and directive for a sidebar that is present at all times in the application, which lists all of the saved objects. In this controller, I have a function that updates the list:

$scope.refreshList = function(){
  //http call to database & refresh list accordingly
};

And then to make that function available to be called from other controllers, I have this:

$window.refreshList = $scope.refreshList;

So that, for example, I can call $window.refreshList from my form submit function to update the form when a new object is submitted.

I feel though that this might not be the best practice. What would be the best way to do this, keeping in mind that the refreshList function relies on some variables that are defined in the list controller?

like image 886
Nathan Avatar asked Aug 27 '26 21:08

Nathan


2 Answers

Angular is a framework which simplifies things for you. It has its own guidelines on how the code should be organized, hence there are concepts of scope, controllers, services etc

Now coming back to your question, on how to make two controllers communicate or share data between them, or how to call one controller function from another controller ?

First assume you have two controllers, one main controller which controls the index page which has got side bars (your list side bar), top bar and a view where we load all the other pages.

So your basic structure would be as follows,

  <div id="main" ng-controller="MainController">
     <nav id="sideBar"> <!-- Your list where items are dynamically shown --></nav>
     <div id="view" ng-view><!-- This is where you will load your templates dynamically --></div>
   </div>

Now any server call within should be placed in service so this can be called from any controller just by injecting the service and its not tightly coupled with one particular controller. So your call for refreshList will be in a service.

  app.service("serverCalls", function(){
     this.refreshListFromServer = function() {
         // Logic to get data from server and returning promise which can be resolved in your controller.
      }
   })

Now assuming your main controller has a method $scope.refreshList() which will call your method from service serverCalls.refreshListFromServer() and refresh your side bar.

$scope.refreshList = function() {
 serverCalls.refreshListFromServer().then(function(){
   // logic to handle response returned from server.
 })
}

Now if form is being submitted by another controller (may be form controller) then you may want to reload your side bar once the form is successfully submitted, to achieve this, you can set up a listener on one of the method in MainController as follows,

//This will get the dataObj, sent by emitter.
$scope.$on("refreshSideBar", function(event, dataObj){
  $scope.refreshList(dataObj);
})

And in your FormController, you can emit the event which will be picked by the listener we sat up above in MainController.

//dataObj can be any arbitrary data you want to pass to listener.
$scope.$emit("refreshSideBar", dataObj);

$emit: Dispatches an event name upwards through the scope hierarchy notifying the registered $rootScope.Scope listeners.

like image 117
ExpectoPatronum Avatar answered Aug 30 '26 10:08

ExpectoPatronum


For sharing functionality over different parts of your application, you should use services.

for example:

app = angular.module( 'app' );

app.service( 'Backend', [ function () {
    this.refreshList = function () {
      //http call to database & refresh list accordingly
    };
} ] );

app.controller( 'Controller1', [ '$scope', 'Backend', function ( $scope, Backend ) {
    Backend.refreshList().then( function ( results ) {
        // work with the results and the scope here
    } );
} );

// And reuse the code in other controllers
app.controller( 'Controller2', [ '$scope', 'Backend', function ( $scope, Backend ) {
    Backend.refreshList().then( function ( results ) {
        // work with the results and the scope here and do something different
    } );
} );
like image 37
Pedro M. Silva Avatar answered Aug 30 '26 11:08

Pedro M. Silva



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!