2

this is my first question so I apologize if I break any protocol. Anyway. I'm trying to have my ng-repeat update in the then clause of my service call. USE CASE: User logs in via an ajax call and then a call is made for that users 'items'. For example, here is what is in my controller:

appControllers.controller('UserCtrl', function($rootScope, $scope, sessionService, alertService, $modal, itemService){
    $scope.login = function() {
        $scope.loggedInUsersItems = [];
        sessionService.login($scope.account).then(
                function(data) {
                    alertService.add('success', 'You are logged in.');
                    itemService.getItemsByUserName($rootScope.loggedinUserName).then(
                            function(data){
                                $scope.loggedInUsersItems  = data.data;
                            }
                    )
                },
                function() {
                    alertService.add('danger', 'There was a problem logging in. Check your credentials and try again.');
                }
        )
    };
...

I think I looked at every question on stack and elsewhere and I keep on spinning my wheels. I tried doing a $scope.$apply(), but that resulted in the expected digest already happening error. I also tried .push() and iterating and pushing, as well as placing the itemService.getItemsByUserName in a chained then with no luck. I'm new to Angular, but I believe I understand $scope is not to be in the service layer, so I'd like to avoid that.

I should mention that the login process is working great, and I do set some $rootScope items in the login service and I see my view updating as a result of successful login (such as the authenticated div showing and a success message). The only thing that doesn't update is my ng-repeat. EDIT to provide more details: The snippet below is already on the view when the login is fired. Login is done using a modal - the user fills in credentials and hits login and the controller is fired. Not sure if this information changes anything but I thought I'd try giving more details.

    <div ng-show="authenticated">
...
<tr class="text-left" ng-repeat="item in loggedInUsersItems">
                        <td>{{ item.itemName }}</td>
                        <td>{{ item.itemType }}</td>
                    </tr>
...
</div>

Here is my the snippet in my service:

 ... 
service.getItemsByUserName = function(username){
        return $http.get('useritems',  {params: { username: username }})
    }; 
...
  • 1
    could you please add a `console.log(data)` inside the function and attach it here? – manoj Jul 27 '15 at 19:47
  • Can you paste your service logic? – Mathew Berg Jul 27 '15 at 19:49
  • Sure. When I log the data in `itemService.getItemsByUserName` as `console.log(data.data)` I see my arrays getting returned as I would expect. – Brian Harris Jul 27 '15 at 19:55
  • why is there two different scopes injected into the controller? $RootScope and $scope . You should lose the $RootScope. You might be working in the wrong scope. That maybe why your loggedInUserItems is not mapping to the view. – Lakmal Caldera Jul 27 '15 at 19:56
  • I'm looking at `$rootScope` for global parameters, such as the username and authenticated. I don't set any `$rootScope` variables in the controller. Just `$scope` as my understanding is that is for the view. – Brian Harris Jul 27 '15 at 19:59
  • At what point are you initialising the username in the $rootscope. You should rightfully do it inside the login success call back. Since your not assigning it in the callback you might be getting undefined for $rootScope.loggedinUserName. Thus your second web service might be failing. – Lakmal Caldera Jul 27 '15 at 20:08
  • Thanks @LakmalCaldera but I can see the call firing and getting the correct response in the network tab. The `$rootScope.loggedinUserName` is getting set in `sessionService.login($scope.account)` – Brian Harris Jul 27 '15 at 20:10
  • @brian, I'm having the same issue on updating a list displayed via a ng-repeat that does not update. I tested with angular 1.3.16 and 1.4.7, it fails the same on both. The only dirty fix I've found is to reload my list after my update. you could use 'ExtensionAngularJS Batarang' to see you angular scopes more easily as with logs. Could you tell me what angular version you use ? – Fonzarely Oct 30 '15 at 10:31

2 Answers2

0

use reference to the current scope to keep your controller in current state. Try AngularJS’s Controller As and the vm Variable

appControllers.controller('UserCtrl', function($rootScope, $scope, sessionService, alertService, $modal, itemService){
var vm=this;
vm.login = function() {
    vm.loggedInUsersItems = [];
    sessionService.login(vm.account).then(
            function(data) {
                alertService.add('success', 'You are logged in.');
                itemService.getItemsByUserName($rootScope.loggedinUserName).then(
                        function(data){
                            vm.loggedInUsersItems  = data.data;
                        }
                )
            },
            function() {
                alertService.add('danger', 'There was a problem logging in. Check your credentials and try again.');
            }
    )
};

HTML

<div ng-controller="UserCtrl as vm">
<tr class="text-left" ng-repeat="item in vm.loggedInUsersItems">
                    <td>{{ item.itemName }}</td>
                    <td>{{ item.itemType }}</td>
                </tr>
Subhashini
  • 114
  • 5
  • Thank you for your answer but I didn't make any progress using this approach. From what I read, this is more of a style preference? Also, I think I read this is becoming the Angular preferred way of writing controllers. But, I didn't read anything that would explain why this approach would fix my situation. If there is any documentation that maybe explains it that would be greatly appreciated. – Brian Harris Jul 28 '15 at 00:29
  • You can refer this post. http://stackoverflow.com/questions/21287794/angularjs-controller-as-syntax-clarification – Subhashini Jul 29 '15 at 13:50
  • I thought there might be dot rule problems.So suggested. – Subhashini Jul 29 '15 at 14:05
0

The way I see it you're doing the following:

sessionService.login($scope.account)

returns a promise that resolves and your .then().. code executes. Presumably you see this happen and it's okay. Your alertService fires the .add method correctly. You call the following line which also returns a promise:

itemService.getItemsByUserName($rootScope.loggedinUserName)

This too resolves at your .then() and you try to set the bound variable to the new value retrieved from the promise:

$scope.loggedInUsersItems  = data.data;

Could you log console.log($scope.loggedInUserItems) to see if it correctly gets the value which is a list of objects each of which contain a property called itemType and itemName? This last part is crucial because if the formatting of your returned object doesn't match your html it won't end up showing anything.

  • Thanks for idea. I did what you suggested and I DO see the list of objects coming back and they are correctly formed. I'm really scratching my head here as this has to be a pretty common usecase. One thing to mention is the `ng-repeat` is already on the screen when this function executes. In other words, its hidden until the person is authenticated and then the div containing the `ng-repeat` is displayed. Maybe I'm breaking a cycle somewhere? – Brian Harris Jul 28 '15 at 10:54
  • Could you post all the rest of your html code please? – Ibrahim Rabbani Jul 28 '15 at 15:36