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.
source to share
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
source to share
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>
source to share