1

I am trying to set a dynamic parameter in the $resources URLs.

I have found this helpful post, but sadly it hasn't solved my problem. THE cid's are still not filled in the $resource functions.

messageApp.factory('conversationService', function($http) {
    var data = {cid: ''};
    $http({method: "GET", url: '/myApp/resources/conversationwizard'}, {cache: true})
            .success(function(d) {
                data.cid = d;
            })
            .error(function(data) {
                alert("Could not initiate conversation" + data);
            });
    return data;
});

messageApp.factory('messagesService', function($resource) {
    return $resource('/myApp/resources/message/all', {}, {
        query: {method: 'GET', isArray: true}
    });
});

messageApp.factory('messageEventPoller', function($http, $timeout, conversationService) {
    var data = {data: ''};
    var poller = function() {
        $http.get('/myApp/msgnotification?cid=' + conversationService.cid).then(function(r) {
            data.data = r.data;
            $timeout(poller, 1);
        });
    };
    poller();
    return data;
});

messageApp.factory('createMessageService', function($resource, conversationService) {
    return $resource('/myApp/resources/message?cid=:cid', {cid: conversationService.cid}, {
        create: {method: 'POST'}
    });
});

messageApp.factory('messageService', function($resource, conversationService) {
    return $resource('/myApp/resources/message/:id?cid=:cid', {cid: conversationService.cid}, {
        show: {method: 'GET'},
        update: {method: 'PUT', params: {id: '@id'}},
        delete: {method: 'DELETE', params: {id: '@id'}}
    });
});

Any pointers would be much appreciated.

Community
  • 1
  • 1
dngfng
  • 1,923
  • 17
  • 34

1 Answers1

3

The problem you're having is that conversationService.cid is fetched from server using a separate asynchronous ajax request.

When you configure: $resource('/myApp/resources/message?cid=:cid', {cid: conversationService.cid}, the response does not arrive yet and the conversationService.cid is still empty.

Unfortunately, there are no easy solutions for this. Here I suggest some approaches:

1) Use synchronous ajax from jQuery with async : false : (not good as it blocks the browser thread)

messageApp.factory('conversationService', function($http) {
    var data = {cid: ''};

    $.ajax({
        url: '/myApp/resources/conversationwizard',
        async : false 
       })
       .done(function(d) {
            data.cid = d;
        })
       .fail(function(){
            alert("Could not initiate conversation" + data);  
        });
    return data;
});

2) Load your '/myApp/resources/conversationwizard' into a global object before bootstrapping angular (using jQuery ajax). And in your conversationService, you could assign data.cid = yourglobal;

3) Use angular promises:

messageApp.factory('conversationService', function($http,$q) {  
    var deferred = $q.defer();

    var data = {cid: ''};
    $http({method: "GET", url: '/myApp/resources/conversationwizard'}, {cache: true})
            .success(function(d) {
                data.cid = d;
                deferred.resolve(data);
            })
            .error(function(data) {
                alert("Could not initiate conversation" + data);
            });

    return deferred.promise;
});

messageApp.factory('createMessageService', function($resource, conversationService) {
   var deferred = $q.defer();

   conversationService.then(function (data){
      var createMessageService = $resource('/myApp/resources/message?cid=:cid', 
         {cid: data.cid}, 
         {create: {method: 'POST'}
      });

      deferred.resolve(createMessageService);
   });

   return deferred.promise;
});

But this would add complexity to code using the resources. For example

messageApp.controller("testCtrl",function (createMessageService){
     createMessageService.then(function(service){
        //use your service here
     });
});
Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • ok, understood. However I am not sure how to solve this issue, I have only started using Javascript and angularJS recently. How would you solve this problem? – dngfng Jun 29 '14 at 10:14
  • @dngfng: I'm afraid we don't have a solution to this problem as we cannot inject resolved promises as dependencies to `factory`. A workaround could be: load your `'/myApp/resources/conversationwizard'` into a global object before bootstrapping angular (using jQuery ajax). And in your `conversationService`, you could assign `data.cid = yourglobal;`. – Khanh TO Jun 29 '14 at 10:43
  • Could this be resolved by changing the factory to a service? Also if the global variable where to change, would that change take effect or would the old value remain? – dngfng Jun 29 '14 at 11:05
  • @dngfng: `Could this be resolved by changing the factory to a service?` => no. The point is to `preload` this value and store it elsewhere before bootstrapping angular application. – Khanh TO Jun 29 '14 at 12:03
  • @dngfng: a simple solution is to use `synchronous` ajax. – Khanh TO Jun 29 '14 at 12:11
  • @dngfng: `Also if the global variable where to change, would that change take effect or would the old value remain?` => the old value remains, but should be fine as we should only initialize the service once. – Khanh TO Jun 29 '14 at 12:20