Bound variable not updating view automatically


#1

I have a $scope variable that is bound to the results of a database query. When the view loads, the query runs and the variable is updated but the view does not refresh.

When I touch/click the navigation bar the view appears to reload and the list is drawn correctly with the expected data.

Controller

.controller("MyTicketsCtrl", ['$scope','$http','$stateParams','$ionicLoading',function($scope,$http,$stateParams,$ionicLoading) { 
	
	$scope.tickets = [];
	
	var init = function() {

		var db = window.sqlitePlugin.openDatabase("Tickets", "1.0", "Ticket Storage", -1);
		
		
		db.transaction(function(tx) {

			tx.executeSql("SELECT * FROM TICKETS",[], function(tx, results) {
	 		   for(i=0;i<results.rows.length;i++) {
				   var ticket = results.rows.item(i);
				   $scope.tickets.push(ticket);
	 		   }
			});

		}, function(e) {
	      console.log("ERROR: " + e.message);
	    });
	}
	
	init();
}])

View

<ion-view title="My Tickets">	
	<ion-content class="has-header">
		{{ tickets }}
		<ion-list >
			<ion-item class='item-icon-right' ng-repeat='ticket in tickets' href='#/app/tickets/{{ticket.id}}'>
				<h2>{{ ticket.event_name.truncate() }} @ {{ticket.venue_name}}</h2>
				<h3>{{ ticket.event_date }}</h3>
				{{ ticket.quantity}} x {{ ticket.ticket_type }}
				<i class="pink icon ion-chevron-right icon-accessory"></i>
			</ion-item>
		</ion-list>
	</ion-content>
</ion-view>

Can anyone tell me what is going wrong here?

I have added a success callback to the transaction and can see that $scope.tickets holds an array of tickets as expected, but the view still does not refresh until the nag bar is clicked or touched.

Thanks!


#2

Yes! You should read up to angulars’ $.apply function… You should very rarely use it! Except for the situation where you have timers or other asynchronous functions in a non-angular way. Using angulars $timeout or $http already wraps with $.apply on their own. I’ve found this article very thorough: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

Basically, using your piece of code:

Controller:

.controller("MyTicketsCtrl", ['$scope','$http','$stateParams','$ionicLoading',function($scope,$http,$stateParams,$ionicLoading) { 

$scope.tickets = [];

var init = function() {

	var db = window.sqlitePlugin.openDatabase("Tickets", "1.0", "Ticket Storage", -1);


	db.transaction(function(tx) {

		tx.executeSql("SELECT * FROM TICKETS",[], function(tx, results) {
/*****************/$scope.$apply(function(){
 		     for(i=0;i<results.rows.length;i++) {
			   var ticket = results.rows.item(i);
			   $scope.tickets.push(ticket);
 		     }
    /*************/});
		});

	}, function(e) {
      console.log("ERROR: " + e.message);
    });
}

init();
}])

Hopefully I made the changes clear this way :slight_smile:


#3

Thanks iwantwin,

I saw Jim’s article and tried a few approaches.

I have tried to implement your suggestion, but am left with the same situation, nothing being rendered to the screen.

Adam


#4

If you create an alert in the success handler of your executeSql, do you receive the alert? I can only think about the code not being executed then… But I’m pretty new to angular myself, so I might not see something that’s happening :wink: