NgRepeat not updating after model change

I am trying to code a small search to get data from a database using ngResource.

the data is displayed on the page using ng-repeat, but when I search and the $ scope is updated, the view is not updated and shows the old data.

Here is the code:

main.html (active view)

<div ng-controller="searchCtrl as searchCtrl" layout="column">
    <form class="form-inline search-form col-md-offset-1">
        <div class="form-group col-md-5">
            <label class="sr-only" for="search_location">Location</label> <input
                id="search_location" type="search" class="form-control"
                ng-Autocomplete ng-model="place" placeholder="Location" />
        </div>
        <div class="form-group col-md-5">
            <label class="sr-only" for="search_tags">Tags</label> <input
                style="width: 100%;" id="search_tags" type="search"
                class="form-control" id="search_tags" placeholder="Tags">
        </div>

        <div class="col-md-1">
            <md-button class="md-fab md-mini" aria-label="Search" ng-click="searchCtrl.search()"> <md-icon class="md-fab-center"
                md-font-icon="glyphicon glyphicon-search" style="color: black;"></md-icon>
            </md-button>
        </div>
    </form>
</div>

<div ng-controller="mainCtrl">

    <div ng-repeat="evento in eventi" ng-include="'views/components/event_card.html'" class="col-md-3"></div>

</div>

      

main.js

'use strict';
app.factory('Eventi', function($resource) {
    return $resource('/eventsws/events/:location', {location : '@location'}, { 
        search: {
            method: 'GET',
            params: {
                'location' : "@location"
            },
            isArray : true
        }
    })
});

app.controller('mainCtrl', function($scope, Eventi) {
    $scope.eventi = Eventi.query();
});

      

searchbar.js

'use strict';
app.controller('searchCtrl', function($scope, Eventi) {
    $scope.place = null;

    this.search = function() {

        $scope.eventi = Eventi.search({
            'location' : $scope.place
        });
    }
});

      

when it starts, it gets all data from the database and displays it correctly, when I try to search, $ scope.eventi is updated (I can see new data in $ scope.eventi from debug) but the view still shows old data and never is not updated.

I tried using $ scope. $ is applied at the end of the search function, but the result is the same.

Do you have an idea why it doesn't work?

Thank you for your time.

+3


source to share


2 answers


The $ scope.eventi you see in debug is in your searchCtrl, not in your mainCtrl. To update your mainCtrl $ scope.eventi you need to find another way.

A clean but long-term solution would be to use services to exchange variables in your controllers.

To answer the question in the comments:

I can see that it has been updated, but the view is still showing old data

I guess that's the problem (even though I haven't actually seen your code).

Problem

If you bind your var like this:

Service

[...]
service.serviceVar = 1;
return service
[...]

      

This will create a variable "1" with a link.

Controller

  [...]
  $scope.myvar = Service.serviceVar;
  [...]

      

This will bind $ scope.myvar to reference "1".

If you do this in your service or another controller:

   service.serviceVar = 2;

      

You will create a new var "2" with a new link and you will assign this link to service.serviceVar. Bad all your old references to old 1 var will not be updated.

Decision

To avoid this, follow these steps:



Service

[...]
service.servicevar = {};
service.servicevar.value = 1;
return service
[...]

      

You create an object with a new reference and assign it to the servicevar. You create variable "1" and assign servicevar.value to it.

Controller

[...]
$scope.myvar = Service.servicevar;
[...]

      

You are assigning the servicevar reference to your var scope.

view

{{myvar.value}}

      

You can use this value using your var property.

Var update:

service.servicevar.value = 2;

      

You will create a new var "2" with a new link and replace the old link with this one.

BUT this time, you will keep all your servicevar references in your controllers.

I hope I understand and the answer to your question.

EDIT:

Try to never use $ scope. $ apply. This is a very bad practice. If you are using this to get something to work, you should probably find someone else to do it (And that would be a great question for Stacks, I think, "Why do I need $ apply to solve my XXXXX problem")

rsnorman15 makes good sense about using async calls. See also his answer.

Here is one of my old plunkers using a property exchange service

+6


source


Just change:

$scope.eventi = Eventi.search({
   'location' : $scope.place
});

      

to

Eventi.search({
  'location' : $scope.place
}, function(eventi) {
  $scope.eventi = eventi
});

      



This is an asynchronous call, so it must be assigned in a success handler.

Another problem you are facing is yours is ng-repeat

not contained in a div that has a region searchCtrl

. Update your HTML to contain it like this:

<div ng-controller="searchCtrl as searchCtrl" layout="column">
  <form class="form-inline search-form col-md-offset-1">
    ... form stuff
  </form>

  <div ng-repeat="evento in eventi" ng-include="'views/components/event_card.html'" class="col-md-3"></div>
</div>

      

+2


source







All Articles