ng-repeat with filter not updating - javascript

I'm building an ionic app. I have a state where the user can see all of their posts. Each post has many fields, one of which is 'active' - boolean field.
I'm rendering the list by:
<ion-item ng-repeat="post in posts | filter:{active:true}" ng-click="goToPost(post.id)"
class="item item-thumbnail-left">
<some fields here />
</ion-item>
Then the user has an option to deactivate a post.
<ion-option-button class="button-assertive" ng-click="deactivate(post.id, $index)">
DEACTIVATE
</ion-option-button>
This option makes a request to the backend, and also it locally sets the active field of the post into "false". After the deactivation is complete, I can't get the ng-repeat to re-filter the list - since the current post should no longer appear in the list of active posts.
I tried $scope.$apply() and it threw the $digest error... I tried to add ng-change and ng-model, and that didn't work either. I also tried reloading the state completely, but for some reason, I can't get this done.
Can anyone help me? Thanks in advance!

Look at the fiddle
<div ng-app="app" ng-controller="demoController">
<ion-item ng-repeat="post in data | filter:{activated:true}" ng-click="deativate(post.id)">
{{post.col1}} {{post.activated }} {{"click Me"}} </br>
</ion-item>
</div>
var app= angular.module("app",[]);
app.controller('demoController', ['$scope',
function($scope) {
$scope.data = [
{id:1,col1:"abc",activated:true},
{id:2,col1:"abc1",activated:true},
{id:3,col1:"abc2",activated:true},
{id:4,col1:"abc3",activated:true},
{id:5,col1:"abc4",activated:false},
{id:6,col1:"abc5",activated:true},
];
$scope.deativate = function(id){
angular.forEach($scope.data,function(item){
if(item.id === id){
item.activated = false;
}
})
}
}]);
and for your code you can share your code snippet.

Related

Angular 1.4: How do I force update of directive within a ng-repeat with filter?

How does one force a directive to update if it nested in a ng-repeat which has a filter?
Input Box
<input type="text" class="name-search" ng-model="search.text">
HTML
<ul>
<li ng-repeat="user in users track by $index | filter:search">
<profile-photo user="user"></profile-photo>
<span>{{ user.name }}</span>
<li>
</ul>
As I type in the input box, the users filter properly but the profile-photo directive doesnt have the proper user.
Any help would be greatly appreciated!
Heres a dumbed down Plunker of my actual code. If you start typing, you will notice that it filters but the image doesnt update.
https://plnkr.co/edit/FWD2bFdIh7jQa5aqdkjrPlunker
your link's function code only executes once, when compiling the directive. After that, scope.photoUrl does not change even if you change the user, because you're not $watching the value. You can add a watch, or directly, use this in the template
ng-src="{{user.photoUrl}}"

Optimizing large list View in Ionic App

I Am trying to fetch data from http, json array and display in list view and there is over 1000 items and loading all of them at once makes scrolling so laggy and am trying to load 20 items first and when scrolled down i want to load more 20 items but my code is not working. Can anyone help me out.
HTML
<ion-content ng-controller="ListController" on-infinite-scroll="addMoreItem" class="has-subheader" scroll-watch >
<ion-list >
<ion-item href="{{ item.url }}.jpg" ng-repeat="item in id | limitTo:numberOfItemsToDisplay" class="item-thumbnail-left item-text-wrap" >
<img src="{{ item.thumbnailUrl }}.jpg" alt="Photo">
<h2>
{{item.id}}
</h2>
<p>{{item.title}}</p>
</ion-item>
</ion-list>
</ion-content>
AngularJS
.controller('ListController',['$scope','$http',function($scope,$http){
$http.get('http://jsonplaceholder.typicode.com/photos').success(function(data){
$scope.id = data;
})
$scope.numberOfItemsToDisplay = 20; // number of item to load each time
$scope.addMoreItem = function(done) {
if ($scope.item.length >= $scope.numberOfItemsToDisplay)
$scope.numberOfItemsToDisplay += 20; // load 20 more items
done(); // need to call this when finish loading more data
}
}])
When dealing with huge lists, ionic suggest that you should use the collection-repeat directive instead of ng-repeat cause it gives a far more better performance. collection-repeat renders into the DOM only as many items as are currently visible and thats how it keeps the performance up. Please read more on the official doc here: collection-repeat
I suggest solving it through infinite-scroll.. :)

ng-class not refresh when data change

I want to change the color item whan my data change. I use this template code:
<ion-view view-title="Evénement" class="content">
<ion-content class="padding">
<ion-list>
<ion-item ng-repeat="myuser in users">
<span>{{myuser.user_name}} </span><a class="button button-icon icon ion-person-add icon_add" ng-click="addContact('{{myuser.id}}')" ng-class="{contact_added : myuser.isContact }"></a>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
I use firebase to loading and saving data. So, I use this code for synchronizing data.
ref.child('contact').child(authData.uid).on('child_added', function (snapshot) {
var myUser = snapshot.key();
$scope.users.push(myUser);
});
When I add a contact on firebase, my color icon does not change immediately. I must click and move my mouse on html page to update the color.
How I have to do to refresh instantly my icon when the data change?
Don't use $scope.$apply(), use AngularFire.
Angular apps should not have to manage the digest loop. Firebase directly integrates with Angular with the AngularFire library, which manages data synchronization and the triggering of $digest.
In your case you can create a $firebaseArray to synchronize your changes:
angular.module('app', ['firebase'])
.constant('FirebaseUrl', '<my-firebase-app>')
.service('rootRef', ['FirebaseUrl', Firebase])
.controller('MyCtrl', MyController);
function MyController($scope, rootRef, $firebaseArray) {
var userRef = rootRef.child('contact').child(authData.uid);
$scope.users = $firebaseArray(userRef);
}
The advantage of using AngularFire is two fold. Firstly, you don't have to manage $scope.$apply(). Secondly, you get realtime array synchronization for free.
add $scope.$apply(); after $scope.users.push(myUser); line.

Retrieve array over $http and view in ion-item of ion-list

Like the title says, I'm trying to assign a list from a $http request and then see that list in a view.
I believe the problem is the view is shown before the data loads, if I understand ionic correctly. And the view is never updated when the variables change.
I'm told resolves are one way of fixing this but I'd prefer for the view to change and then show a loading indicator while it waits for the http request to finish, and then show the list.
Thanks!
Edit: I think I need to add the way I'm loading the data is through ng-init in the html file, which seems wrong too. Is there a better way altogether?
view html file:
<ion-view view-title={{ListName}} ng-init="getList()">
<ion-content ng-controller="ListCtrl">
<ion-list>
<ion-item ng-repeat="item in list"
class="item-thumbnail-left">
{{item.id}}
<img ng-src="{{item.thumbnail}}">
</ion-item>
</ion-list>
</ion-content>
</ion-view>
controller snippet:
.controller('ListCtrl', function($scope){
$scope.list = []
$scope.ListName = ''
$scope.getList = function(){
$scope.ListName = 'list'
$scope.list = [{id: 1, thumbnail:null}, {id: 2, thumbnail:null},{id: 3, thumbnail:null} ,{id: 4, thumbnail:null}]
}
})
the list is actually gotten in a http request that returns a promise but this gives me the same problem. It's something annoyingly basic that I just don't understand about ionic yet
Dinesh answered my question. Putting the ng-controller in the ion-view was all I needed to do!

Not able to fetch scope value in back button method in Ionic

On same template ionic is unable to get the value in ion-nav-bar directive.
Problem - Whatever the amount I filled in textbox <input type="text" placeholder="70" ng-model="getamt"> in below mentioned code, I am able to get the same value at Getting Amt here: {{getamt}} ie.if I type 56 I am able to get 56 typed like Getting Amt here: 56 BUT I am expecting the same to print at Not updating Amt {{getamt}} but in this case I am not getting any value.
I need to send this value to my previous page..so I am trying to do this stuff.
Let me know how to fix this weird issue with ionic.
<ion-view>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button class="button-clear" ng-click="myGoBack(getamt)">
<i class="icon ion-ios7-arrow-back"></i> Not updating Amt {{getamt}}
</ion-nav-back-button>
</ion-nav-bar>
<ion-content class="has-subheader" padding-bottom="true">
<div class="row">
<div class="col col-30">
<input type="text" placeholder="70" ng-model="getamt">
</div>
<div class="col col-30 item">
Getting Amt here: {{getamt}}
</div>
</div>
</ion-content>
</ion-view>
EDIT -
My controller code -
.controller('mystate2Ctrl', function($scope, $stateParams, $localstorage, $rootScope, $ionicHistory) {
console.log("----- mystate2Ctrl -----");
$scope.myGoBack = function(val){
console.log(val);
$ionicHistory.goBack();
};
$rootScope.$on( "$ionicView.leave", function( scopes, states ) {
if( states.stateName == "app.mystate1" ) {
console.log("In Ionic View blah blah code here");
}
});
The problem you're facing has to do with nested scopes and in particular with the way you use your "model".
The scope is not the model.
I would suggest you to watch this video from Miško Hevery where he talks about the problem you're having. At some point he says something like this:
Whenever you have ng-model there’s gotta be a dot in there somewhere.
If you don’t have a dot, you’re doing it wrong.
Anyway, if you want to fix your problem you should define a model in your controller.
The solution is to create one:
.controller('mystate2Ctrl', function($rootScope, $scope, $state) {
$scope.mymodel = { getamt: 0 };
});
Now you can reference your model in your views using the dot and your view should look something like this:
<ion-view view-title="my-app">
<ion-nav-buttons side="right" class="button-clear" ng-click="myGoBack(mymodel.getamt)">
<i class="icon ion-ios7-arrow-back"></i> Not updating Amt {{mymodel.getamt}}
</ion-nav-buttons>
<ion-content class="has-subheader" padding-bottom="true">
<div class="row">
<div class="col col-30">
<input type="text" placeholder="70" ng-model="mymodel.getamt">
</div>
<div class="col col-30 item">
Getting Amt here: {{mymodel.getamt}}
</div>
</div>
</ion-content>
</ion-view>
If you want to see how it works you can check my plunker.
Probably the best approach is the one John Papa suggests in his Angular guidelines.
If you read carefully the controllerAs View Syntax here he states why you should go for this approach:
Why?: It promotes the use of binding to a "dotted" object in the View
(e.g. customer.name instead of name), which is more contextual, easier
to read, and avoids any reference issues that may occur without
"dotting".
Why?: Helps avoid using $parent calls in Views with nested
controllers.
This is a second plunker with the controllerAs sample.
It seems like because, your Getting Amt here: {{getamt}} and Not updating Amt {{getamt}} in two different directives. So make sure they both can access mystate2Ctrl.
And try to define the variable in the controller itself.
.controller('mystate2Ctrl', function($scope, $stateParams, $localstorage, $rootScope, $ionicHistory) {
$scope.getamt = 0;
// your code
})
HTH

Categories

Resources