Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the right way to send data between modules in AngularJS?

One of the great things about angular is that you can have independent Modules that you can reuse in different places. Say that you have a module to paint, order, and do a lot of things with lists. Say that this module will be used all around your application. And finally, say that you want to populate it in different ways. Here is an example:

angular.module('list', []).controller('listController', ListController);
var app = angular.module('myapp', ['list']).controller('appController', AppController);

function AppController() {
  this.name = "Misae";
  this.fetch = function() {
    console.log("feching");
    //change ListController list
    //do something else
  }
}

function ListController() {
  this.list = [1, 2, 3];
  this.revert = function() {
    this.list.reverse();
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="app" ng-app="myapp" ng-controller="appController as App">

  <div class="filters">
    Name:
    <input type="text" ng-model="App.name" />
    <button ng-click="App.fetch()">Fetch</button>
  </div>

  <div class="list" ng-controller="listController as List">
    <button ng-click="List.revert()">Revert</button>
    <ul>
      <li ng-repeat="item in List.list">{{item}}</li>
    </ul>
  </div>

</div>

Now, when you click on Fetch button, you'll send the name (and other filters and stuff) to an API using $http and so on. Then you get some data, including a list of items you want to paint. Then you want to send that list to the List module, to be painted.

It has to be this way because you'll be using the list module in diferent places and it will always paint a list and add some features like reordering and reversing it. While the filters and the API connection will change, your list behaviour will not, so there must be 2 different modules.

That said, what is the best way to send the data to the List module after fetching it? With a Service?

like image 418
Vandervals Avatar asked Oct 26 '16 14:10

Vandervals


People also ask

What is the efficient way of sharing data between controllers?

Approach: To share data between the controllers in AngularJS we have two main cases: Share data between parent and child: Here, the sharing of data can be done simply by using controller inheritance as the scope of a child controller inherits from the scope of the parent controller.

How pass data from one component to another in AngularJS?

Angular provides the Decorator, @Input(). By using this decorator, we can pass data from the Parent component to the Child component. Angular provides the Decorator, @Output(). By using this decorator, we can pass data from the child component to the parent component.


2 Answers

There are many ways to pass data from one module to another module and many ppl have suggested different ways.

One of the finest way and cleaner approach is using a factory instead of polluting $rootScope or using $emit or $broadcast or $controller.If you want to know more about how to use all of this visit this blog on Accessing functions of one controller from another in angular js

By simply inject the factory you have created in main module and add child modules as dependancy in main module, then inject factory in child modules to access the factory objects.

Here is a sample example on how to use factory for sharing data across the application.

Lets create a factory which can be used in entire application across all controllers to store data and access them.

Advantages with factory is you can create objects in it and intialise them any where in the controllers or we can set the defult values by intialising them in the factory itself.

Factory

app.factory('SharedData',['$http','$rootScope',function($http,$rootScope){

    var SharedData = {}; // create factory object...
    SharedData.appName ='My App';
    return SharedData;
}]);

Service

app.service('Auth', ['$http', '$q', 'SharedData', function($http, $q,SharedData) {
   this.getUser = function() {

            return $http.get('user.json')
              .then(function(response) {
                  this.user = response.data;
                  SharedData.userData = this.user; // inject in the service and create a object in factory ob ject to store user data..
                  return response.data;
              }, function(error) {
                  return $q.reject(error.data);
              });

    };

}]);

Controller

var app = angular.module("app", []);
app.controller("testController", ["$scope",'SharedData','Auth',
  function($scope,SharedData,Auth) {

    $scope.user ={};
   // do a service call via service and check the shared data which is factory object ...
   var user = Auth.getUser().then(function(res){
       console.log(SharedData);
       $scope.user = SharedData.userData;// assigning to scope.
   });


  }]);

In HTML

<body ng-app='app'>
    <div class="media-list" ng-controller="testController">

       <pre> {{user | json}}</pre>

    </div>

</body>
like image 196
ngCoder Avatar answered Sep 28 '22 03:09

ngCoder


You should be using Angular components for this task.

You should create a module with a component that will be displaying lists and providing some actions that will modify the list and tell the parent to update the value.

var list = angular.module('listModule', []);

list.controller('listCtrl', function() {
    this.reverse = function() {
        this.items = [].concat(this.items).reverse();
        this.onUpdate({ newValue: this.items });
    };
});

list.component('list', {
  bindings: {
    items: '<',
    onUpdate: '&'
  },
  controller: 'listCtrl',
  template: '<button ng-click="$ctrl.reverse()">Revert</button><ul><li ng-repeat="item in $ctrl.items">{{ item }}</li></ul>'
});

This way when you click on "Revert" list component will reverse the array and execute the function provided in on-update attribute of HTML element.

Then you can simply set your app to be dependent on this module

var app = angular.module('app', ['listModule']);

and use list component

<list data-items="list" data-on-update="updateList(newValue)"></list>

You can see the rest of the code in the example

like image 36
Dennis Baizulin Avatar answered Sep 28 '22 03:09

Dennis Baizulin