0

I'm new in angular and I need help to call an http request. I had this controller

var app = angular.module('myApp',[]);
app.controller('freeUserController', function($scope, $http) {
    $http({
        method: 'GET',
        url: 'users'
    }).then(function successCallback(response) {
        $scope.users = response.data.result;
        // this callback will be called asynchronously
        // when the response is available
    }, function errorCallback(response) {
        // called asynchronously if an error occurs
        // or server returns response with an error status.
    });

});

It allows to fill Select in a modal form modal form

This Select change every time user click on confirm button(select shows free users) so I though to create a service with the above http call and use this or on confirm button ( or on inside javascript of confirm button) or when user clicks on select tho show user. So I change angular code like this:

var app = angular.module('"modalUploadLicense"',[]);
app.controller('freeUserController', function() {
    freeUserService();

});
app.service("freeUserService",function($scope, $http){
    $http({
        method: 'GET',
        url: 'users'
    }).then(function successCallback(response) {
        $scope.users = response.data.result;
        // this callback will be called asynchronously
        // when the response is available
    }, function errorCallback(response) {
        // called asynchronously if an error occurs
        // or server returns response with an error status.
    });

});

But it give me an error and moreover I don't know the best way to call the service when the user list change. This is my confirm button javascript:

$("#createLicenseButton").click(
    function() {
        var form = $("#addLicenseForm");        
        $.ajax({
            type : "POST",
            url : form.attr("action"),
            data : form.serialize(),
            // all right with rest call
            success : function(data) {  
                //No exception occurred
                if (data.status==true){ 
                    //Also the field are right(for e.g. form value)
                    if(data.success==true){
                        //il risultato sta in data.result
                        //window.location.reload(true);
                        $('#licensesTable').load(document.URL +  ' #licensesTable');
                        angular.element(document.getElementById('freeUserController')).scope().get();
                        //reload only the tag with id carsTable, so only the table
                        //$('#carsTable').load(document.URL +  ' #carsTable');
                        $('#addLicenseModal').modal("hide");
                        notifyMessage("Your license has been created!", 'success');
                    }
                    else{
                        //code if there are some error into form for example
                    }
                } else {
                    //code exception
                    $('#addLicenseModal').modal("hide");
                    notifyMessage("Error! Your license hasn't been created!", 'error');
                }
            },
            //error during rest call
            error : function(data) {
                window.location.href = "/ATS/500";
            }
        });
    });

Whereas html Select is:

<label>Username</label> <select class="form-control select2"
        style="width: 100%;" name="user" ng-model="selectedItem" ng-options="user.username as user.username for user in users track by user.username">                                  
</select>

How can I update my Select value?thanks

luca
  • 3,248
  • 10
  • 66
  • 145

2 Answers2

1

First, change your service so it has a function to call:

app.service("freeUserService",['$http', function($http){
    var service = this;

    service.getusers = getusers;

    function getusers() {
       var url = "your url gets here";
       return $http.get(url);
    }

}]);

Then like Arnab says, you need to change your controller:

app.controller('freeUserController', ['freeUserService', '$scope', function(freeUserService, '$scope') {

     $scope.fetchusers = function() {
         freeUserService.getusers()
                     .then(handleGetUsers)
                     .catch(handleErrors);
     }

     function handleGetUsers(result){
        //This is a promise, because $http only does asynchronous calls. No
        //need to wrap this in a jquery thingy. 

       //As soon as the async function is resolved, the result data is put 
       // on your scope. I used $scope.users on purpose, because of your
       //html
       $scope.users = result.data;
     }

     function handleErrors(error){
      console.log(error);
     }

}]);

As you can see, I have put the "variable" users on the scope. I did this on purpose because of your html

<label>Username</label> <select class="form-control select2"
        style="width: 100%;" name="user" ng-model="selectedItem" ng-options="user.username as user.username for user in users track by user.username">                                  
</select>

The select looks into the scope for a variable called users. Because the variable users is on your html, angular automatically watches the variable for changes.

What I understand from your question is that every time the http call is done, you get another result, right? So Angular will automatically watch for a change, and reflect the result on your select element. if interested in more information, you should read this. I also suggest following a 'start with Angular tutorial', because going from your question, I think you are missing the basics of Angular.

The last step you need to do (I think, if i understand your question), is bind the $http function to your HTML. There is a "ng-click" directive you can use. In your case, the button then could look like this:

<button ng-click="fetchusers()" type="submit">Get me new users</button>

As you can see, I use the $scope.fetchusers() function in the ng-click directive, wich will make a new http call, getting new uses (ofcourse, if the http call gets new users every time you call it).

Plunker with modified code here.

You can use the ng-init directive to initialize the value. I ll update my plunker so that you can see how the ng-init works. You should set it right next to your ng-controller. ng-init will make the first call and give you data from the start. Then every time you press the button, new data will come, and your select will be updated. I have updated the plunk. I have added one of my own webservices. Do mind, my webservices are on a free heroku account. If you wait too long, the heroku application will go to sleep mode and the first call for data will timeout.

About multiple asynchronous calls:

Angular promises can be chained! So you can do one asynchronous call (for example doing a post to a database), wait for it to finish, then get the updated data. In your service, you could do this:

function getUsers(parameters) {
       var posturl = "url to post to";


       return $http.post(url, data) //the update, it returns a promise
                   .then(handlePost)
                   .catch(handleError);
   }

function handlePost(result){
       //the $http.get will only be executed after the previous promise has been
       //resolved!
       var geturl  = "url to get data from";
       return $http.get(url); // this is the second asynchronous call
}

It is good practice to chain promises. It would be bad practice to use a jQuery ajax call for this.

Community
  • 1
  • 1
ocket-san
  • 874
  • 12
  • 22
  • I tried with your code but I retrieve Unknown provider: $scopeProvider <- $scope <- freeUserService and I have removed '' from function(freeUserService, '$scope'). For the second question I know about data binding but I have to call this http function because Angularjs can't know that the returned values are changed if I don't call the function – luca Feb 03 '16 at 10:28
  • Now it can't return exception, but the function is called only with button click? because I have a ng-show on users.length and I need this value even at page load – luca Feb 03 '16 at 10:46
  • thanks, I understand and it works. Only a small problem: if I use ng-click on submit button it is called before that the instructions associate to the button are finished (it calls a Rest web service that writes into database), so it retrieves not updated data. So I have linked ng-click to open modal button but it obtains the length of array after the modal is showed, so user sees modal changes. The only solution is to call fetch users() inside Jquery success call(associate to the submit button), is it possible? – luca Feb 03 '16 at 11:30
  • So basically, there are 2 calls: one that writes to the database and then one that fetches the updated data? Is that correct? And you want ofcourse the one that returns data to wait so it returns the updated data? – ocket-san Feb 03 '16 at 12:04
  • yes, it's correct. I should call fetchusers() in ajax success result – luca Feb 03 '16 at 13:08
  • Do I have to convert $("#createLicenseButton").click.. into angular function right? – luca Feb 03 '16 at 14:52
  • Yes indeed. You can access the function you made with the directive 'ng-click'. If you want more example code, I can change the plunkr code so it actually does 2 asynchronous calls – ocket-san Feb 03 '16 at 15:03
  • Maybe it is not a good idea because I have to rewrite all my code. I have a table with Upload and Delete button (so the modals receive id of element row) and Create button that's we are talking about that send form to ajax http. I'm also using Spring security with CSRF – luca Feb 03 '16 at 15:54
0

Inject freeUserService to your controller freeUserController to atleast call the service from your controller, like:

app.controller('freeUserController', ['freeUserService', function(freeUserService) {
    freeUserService();

}]);

Otherwise you write like this:

var app = angular.module('myApp',[]);
app.controller('freeUserController', ['freeUserService', function($scope, freeUserService) {

    var promise = freeUserService();
    promise.then(function successCallback(response) {
        $scope.users = response.data.result;
        // this callback will be called asynchronously
        // when the response is available
    }, function errorCallback(response) {
        // called asynchronously if an error occurs
        // or server returns response with an error status.
    });

    // And bind the users variable in your template

}]);

app.service("freeUserService", ['$http', function($http){


    return $http({
        method: 'GET',
        url: 'users' // Proper url to your api
    });

}]);
Arnab Das
  • 3,548
  • 8
  • 31
  • 43