0

I am trying to write a service that makes a http request to my route (NodeJs) to add a user to the db.

If I just write it in the controller it works but then you won't see the user added until I refresh the browser:

my code in the controller:

//Function to add a user to the db
$scope.inviteUser = function(){
    $http.post('/api/users/invite', {
        'email': $scope.user.email,
        'role_id': $scope.user.role
    }, {
        headers: {
            "Content-Type": "text/plain"
        }
    })
    .success(function(data, status, headers, config) {
        console.log("Successfully saved a user to the DB", data);

        $scope.userInfo.push(data);


    })
    .error(function(data, status, headers, config) {
        console.log("Failed to add user to DB");
    });
}

The reason I need it in a service is because people on stack told me that it would resolve the issue that I am currently facing that is when a user is added you won't see it until the browser is refreshed. This is because I have a view with a button invite and when you click on it a popup shows (md-dialog -> angular material). This dialog has its own tmple.html file. In the view where the invite button resides is the $scope.userInfo linked to (defined in the function inviteUser - code from above)

Code for the view with the invite button and the list where the user get added:

<div id="sidebar" class="md-whiteframe-z4" ng-data-color="">
      <div style="height: 80px;"></div>
      <div class="userList">
        <li id="customLI" ng-repeat="user in userInfo" id="userPos" class="circular md-whiteframe-z2" style="background-color: {{ user.color }} " ng-click=" showPopUpDeletionConfirmation(); setDeleteId( user._id )" ng-data-id="{{ user._id }} ">
          <p class="initials" id="userValue" style="top: {{ user.top }};" >
              <custom id="user._id"></custom>
              {{user.initials}}
          </p>
        <md-tooltip>
        <!-- Delete this user -->  {{user.name}}
        </md-tooltip>
        </li>
      </div>
    </div>

Code of the dialog box :

  <md-dialog aria-label="" ng-controller="CalendarCtrl">
    <form name="form"  >
      <md-toolbar>
        <div class="md-toolbar-tools">
          <h1 class="customH1">Invite a user</h1>

          <span flex></span>
          <!-- <md-button class="md-icon-button" ng-click="closeDialog()">
            <md-icon md-svg-src="images/ic_close_24px.svg" aria-label="Close dialog"></md-icon>
          </md-button> -->
        </div>
      </md-toolbar>
      <md-dialog-content>
        <div id="containerForm">
            <div layout="row">
              <md-input-container flex="">
                <div class="form-group" ng-class="{ 'has-success': form.email.$valid && submitted,'has-error': form.email.$invalid && submitted }">
                  <label>Enter the user's e-mail</label>
                  <input type="email" name="email" id="to" class="form-control" ng-model="user.email" required mongoose-error/>
                  <p class="help-block" ng-show="form.email.$error.email && submitted">
                    Doesn't look like a valid email.
                  </p>
                  <p class="help-block" ng-show="form.email.$error.required && submitted">
                    What's your email address?
                  </p>
                  <p class="help-block" ng-show="form.email.$error.mongoose">
                    {{ errors.email }}
                  </p>
                </div>
              </md-input-container>
            </div>  

            <br /><br />

            <div ng-show="form.email.$dirty && form.email.$valid">
              <h5>Assign one of the following role's:</h5>

              <div id="wrapperRadioButtons">
                <md-radio-group ng-model="user.role">
                  <md-radio-button ng-repeat="userrole in roleInfo" value="{{userrole.id}}" class="md-primary">{{userrole.role}}</md-radio-button>
                </md-radio-group>
              </div>
              </div>

            <br />

        </div>
      </md-dialog-content>
      <div class="md-actions" layout="row" >
        <md-button ng-click="closeDialog()" class="md-primary">Cancel</md-button>

        <md-button id="send_email" ng-click="inviteUser(); closeDialog()" class="md-primary">Invite</md-button>
      </div>
    </form>
  </md-dialog>

This is the service I wrote and tried to link to the function inviteUsers:

zazzleApp.factory('UserService', ['$q', '$http', function ($q, $http) {
            var service = {};

            service.get = function() {
              var deferred = $q.defer();

              deferred.resolve(service.data);
              return deferred.promise;
            }

            service.save = function(data) {
                var promise = $http({
                    method: 'POST',
                    url: 'api/users/invite'
                })

                var deferred = $q.defer();

                service.data.push(data);
                deferred.resolve();
                return deferred.promise;
            }

            return service;
        }
    ]);

Part of my controller:

angular.module('zazzleToolPlannerApp')
    .controller('CalendarCtrl', function ($scope, $mdDialog, $http, $rootScope, $timeout, User, Auth, UserService) {

        //Function to add a user to the db
        $scope.inviteUser = function(){

           var obj = {
                'email': $scope.user.email,
                'role_id': $scope.user.role
           };
           UserService.save(obj).then(function(){
                $scope.getUsers();

           })
        }
});

Now when I try to add a user I get an error in my console -> https://gyazo.com/34b39d7eda18b8afd9ef11094b4f429a

So basically what I am asking is how to write a service that makes an http request and link it to a controller ....

Side note: I have never done this before so thats why its probably not working.

GY22
  • 755
  • 2
  • 17
  • 48

2 Answers2

2

all I can see is that in your log it says

typeError can not read property 'push' of undefined at object.service.save

I think this does not have anything to do with your HTTP request. You have not defined your service.data.push(data); and that is where he dumps

Try defining the data property of service object as an array before you push values to it (it doesnt know that its an array yet, so it cant access the arrays prototyp functions)

do this

service = { data: [] };

hope this helped.

Max Bumaye
  • 1,017
  • 10
  • 17
  • yes that solved the issue but then i get another error. I mostly like because of what bosch said but I am still waiting on his fiddle ... – GY22 Aug 06 '15 at 10:01
1

The reason you get an error in the console is because service.data in service.data.push(data); does not exist. What you meant was probably to push the new user into an array of users which has not been created yet (and you seem confused about the "data" in the code:P).

Anyway, the solution for your problem is much simpler: in the service you can return the $http.post() to the controller and process the request in the controller on the .success() callback. Further, the list of users that you need updated should reside in the service and you bind to it from your controller; this way it will keep the template updated after you add a new user without refreshing the browser. You just have to retrieve the list of users on the $http callback from the service.

I can write a fiddle if you still find this confusing.

EDIT: here is the fiddle: http://jsfiddle.net/bosch/8pnL23k7/. Hope it will help you understand the concepts better

bosch
  • 1,089
  • 11
  • 16
  • here is your fiddle http://jsfiddle.net/bosch/8pnL23k7/, hope it helps. Sorry it looks bad, I did it in a hurry. If it's still not clear, feel free to ask. – bosch Aug 06 '15 at 10:34
  • mmm i uses your fiddle on my code. and when the application loads, the existing users and not loading in and when i invite a user i get following error -> https://gyazo.com/a25b69283865228714024b1e436942f2 – GY22 Aug 06 '15 at 11:49
  • from the error it appears that you do not return the promise from the service to the controller. Make sure you use the keyword "return" before $http in the AddUser method – bosch Aug 06 '15 at 12:36
  • update, i am now able to save a user to the db and but i can't read out the users ... – GY22 Aug 06 '15 at 12:37
  • after you save the user don't forget to call the method to retrieve the users list: on the .success() you should call UserService.getUsers() or whatever is the name of that method – bosch Aug 06 '15 at 12:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/85302/discussion-between-gy22-and-bosch). – GY22 Aug 06 '15 at 12:40
  • you this bit: $scope.getDataFromService = function () { UserService.getUsers(); //after this gets called, the data will be shown in the page automatically } $scope.getDataFromService(); its already added in the controller – GY22 Aug 06 '15 at 12:41
  • its already added in the controller in the save function i got this: $scope.addUserWithService = function () { UserService.addUser($scope.newUser) .success(function(data){ console.log("Controller: the user has been added"); UserService.getUsers() }) .error(function(data){ console.log("Controller: the user has been added"); }); } – GY22 Aug 06 '15 at 12:48
  • the thing is the users are coming back from the server because i see them in my log (chrome) but i some how can't show them visually ... – GY22 Aug 06 '15 at 12:59
  • let's discuss further in the chat room you created – bosch Aug 06 '15 at 13:00