0

I am showing employee record using AngularJS. I am using two views to show data, I am using two views emp-box.htm and its respective controller(empController) and in this controller employeeBoxController I am fetching data from service, I want the result which is obtained in employeeBoxController to be used in empController and show in view (emp-list.htm), I created a service eService

app.service('dataService',function() {

  var s = {};

  this.setData = function(data,key) {
    s[key]=data;
  },
  this.getData = function(key) {
    return s[key];
  }
  this.hello = function() {
    return 'hello';
  }
})

for fetching result and setting data in employeeBoxController and getting in empController but when I fetch the data using console.log(dataService.getData('result')); in empController i get undefined

The employeeBoxController is

app.controller("employeeBoxController", ['$scope', 'employeeService', 
  'dataService', function($scope, employeeService, dataService) {
  $scope.getEmployeeDetails = function(eid) {
    $scope.isLoading = false;
    employeeService.getDetails($scope.eid).then(function(result) {
      dataService.setData(result, 'result');
      $scope.isLoading = true;
      console.log(dataService.getData('result'));
    })
  }
}])

The empController is :-

app.controller("empController", ['$scope', 'employeeService', 'dataService', 
  function($scope, employeeService, dataService) {

    $scope.result = dataService.getData('result');
    //console.log(dataService.hello());

    console.log(dataService.getData('result'));

    console.log(dataService.hello());
  }
])

The service class employeeService is :-

  app.config(["employeeServiceProvider",function(employeeServiceProvider){
      employeeServiceProvider.config('http://localhost:8080/pos');
  }]);

  app.provider("employeeService",function(){
    var myurl='';

    this.config=function(eurl){
      myurl=eurl;
    }

    this.$get=['$http','$log',function($http,$log){
      var employeeobj={};
      employeeobj.getDetails=function(eid){
        return $http.get(myurl+'/getEmployees/'+eid);
    }

  return employeeobj;
    }];
  });

emp-box.htm is:-

    <div>
  Enter the id: <input type="text" ng-model="eid"/>
  <button ng-click="getEmployeeDetails()">show</button>
   </div>
   emp-list.htm is:-
       <div class="panel panel-primary">
       <div class="panel-body" style="text-align:center; margin:0 auto">
      <h3>Employee Data</h3>
      </div>
     </div>
      <div class="panel panel-primary">
        <div class="panel-body">
      <!--  <div ng-show="!isLoading" style="color:red">
      <span class="glyphicon glyphicon-time"></span>Loading...
      </div>-->
     <table class="table table-hover">
     <thead>
      <tr>
      <th>ID</th>
      <th>Name</th>
      <th>empno</th>
      <th>salary</th>
      </tr>
    </thead>
     <tbody>
      <tr ng-repeat="oemp in result.data">

      <td>{{oemp.eid}}</td>
      <td>{{oemp.name}}</td>
      <td>{{oemp.empno}}</td>
      <td>{{oemp.sal}}</td>
    </tr>
  </tbody>

    </table>
  </div>
  </div>
11
  • Does setData return something ? Commented Jun 5, 2017 at 11:56
  • no setData is setting the data,its not return anything Commented Jun 5, 2017 at 11:58
  • But doesn't data contain anything? Just trying to figure Commented Jun 5, 2017 at 12:00
  • i am setting the data value dataService.setData(result, 'result'); check above code Commented Jun 5, 2017 at 12:00
  • Have you made sure that employeeService.getDetails() actually returns data? if its an $http/Ajax call, the data would be in result.data. Commented Jun 5, 2017 at 12:16

2 Answers 2

2

From what I understand you're trying to cache your API results in another service, so you don't have to call the API again in another controller. Also, empController is executed first, and when you're doing dataService.getData('result') the API response of setting it isn't received yet which in turn is called from another service. I would suggest you combine these 2 services, so that instead of caching the exact values in service, you can cache the API call itself, and in case where cache doesn't contain your data, make an API call and cache it.

Here's something I'd make, say CacheAPIService.

app.factory('CacheAPIService', ['$http', function($http) {
  var cache = {};
  return {
    get: function(api) {
     if(angular.isUndefined(cache[api])) {
       cache[api] =  $http.get(api); //storing in cache while making API call
     }
     return cache[api]; //Return from cache
    },
    clear: function(api) {
        delete cache[api];
    }
  }
}]);

So, whenever you need to make an cache an API call, use this service in addition to making API call it'll also cache it. And, if it is already cached, no new API call is made. Benefits is you'll never run into cases where it return's undefined, as you are returning promise.

In your 1st controller, updated code becomes:

app.controller("employeeBoxController", ['$scope', 'CacheAPIService', function($scope, CacheAPIService) {
  $scope.getEmployeeDetails = function(eid) {
    $scope.isLoading = true;
    var endpoint = 'api/endpoint/'+$scope.eid;    //Replace with your API endpoint
    CacheAPIService.get(endpoint).then(function(result) {
      $scope.isLoading = false;
      console.log(dataService.getData('result'));
    })
  }
}]);

Here, 1st API call is made and is cached. Take a look at your other controller:

app.controller("empController", ['$scope', 'CacheAPIService', function($scope, CacheAPIService) {
  CacheAPIService.get(endpoint).then(function(data) {
    var endpoint = 'api/endpoint/'+$scope.eid; //your API endpoint
    console.log('data =', data);
  });

}]);

Here, you still use the same service, but it'll be cached, and if not cached, it'll make API call and cache that promise. Here I've directly used API endpoint as key for storing in cache. This way you don't have to provide unique keys every time, as endpoint itself is unique.

Note that in cases where you want to delete cached data, when making POST or PUT call, you can call CacheAPIService.clear(apiEndpoint) to clear details from cache.

Sign up to request clarification or add additional context in comments.

2 Comments

this is good approach to cache the api but i am getting undefined for the eid which i set in employeeBoxController and when i try to use in $scope.eid
This way you create a cache service that also implements rest logics to get data...
0

$http.get will return a promise. To correctly set data to dataService:

 employeeService.getDetails($scope.eid).then(function(result) {
      dataService.setData(result.data, 'result'); // note .data
      $scope.isLoading = true;
      console.log(dataService.getData('result'));
    })

Storing the promise in your "cache" service is not the best option.

I expect getEmployeeDetails() function is going to route to empController, so if you still store $promise in your service as you stated, you can do.

    dataService.getData('result').then(function(result){
        $scope.result = result.data;
  });

When $scope.result is set to $scope, ng-repeat will start iterating over.

With the first change suggested, you just don't need to touch empController but just the ng-repeat directive emp-list.html with:

<tr ng-repeat="oemp in result">

Refactor the http call with factory recipe and $resource. https://docs.angularjs.org/api/ngResource/service/$resource

That is easier and quicker than writing providers.

4 Comments

i debuged the code empController is executing first before the ajax call happens as mentioned above by @Pankaj Parkar so data in empController is undefined , i am not sure how multiple view are working i cilck on button then function getEmployeeDetails() is called and ajax call happens but how the controller empController is intantiated first
The fact is that the $http service is acutally calling the server endpoint with an async request. Of course you'll get the execution of the controller first (always) but promise are supposed to work that way. Angular anyway, will watch your scope variable and when feed with data, will show/parse it. i Suggest you this reading. robotlolita.me/2015/11/15/how-do-promises-work.html
how do i store the promise in my dataService,should i again make a new ajax call using $http.get
The service can store values (cache) but also functions.. Just add a function inside the service that do your httpRequest. If will be available everywhere once injected.. or better, use the factory recipe with $resource you can find in angular docs. This concern logic separation. Storing the promise into a vector right after call then is a bad idea.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.