Ionic dynamically update $scope of controller based on service function called from another controller


#1

Hey,

I’m stuck with this for two days now and can’t wrap around the problem. I first try to show what I have so far and at the bottom of the post I describe my problem:

What I have:
I have two states: (1) a state with a simple form that allows for geodata input and (2) a state that retrieves a list of post from a server.

/* startseite, auswahl ort */
  .state('tab.suche', {
    url: '/suche',
    views: {
      'tab-unterkuenfte': {
        templateUrl: 'templates/tab-suche.html',
        controller: 'SearchHomeCtrl'
      }
    }
  })

  /* merkliste / favoriten */
  .state('tab.ergebnisse', {
      url: '/unterkuenfte',
      views: {
        'tab-ergebnisse': {
          templateUrl: 'templates/tab-ergebnisse.html',
          controller: 'ErgebnisseCtrl'
        }
      }
    })

I have a service that uses stored vars to do an ajax call

.service('nubiiSearch', function($http) {
  searchVars = {
    location_name : null,
    location_lat : null,
    location_lng : null,
    checkin : null,
    checkout : null,
  };

  posts = [];

  this.getSearchVars = function() {
    return searchVars;
  };

  this.setSearchVar = function(property, value) {
    searchVars[property] = value;
  }

  this.getPosts = function() {
    return $http({
            method: 'GET',
            url: 'http://localhost/nubii2/wp-admin/admin-ajax.php',
            params: {
                action: 'nubii_app_get_objects',
                location_lat: searchVars.location_lat,
                location_lng: searchVars.location_lng,
                checkin: searchVars.checkin,
                checkout: searchVars.checkout,
            },
        }).then(function(response){
            posts = response.data;
            return posts;
        });
  }
})

Then for each state I have my controller. For the first state the controller takes the form input and stores it in my service. When user hits the search button he’s redirected to second state that shows the results

.controller('SearchHomeCtrl', function($scope, $state, nubiiSearch) {
  $scope.search = {};

  $scope.autocompleteOptions = {
      componentRestrictions: { country: 'de' },
  }

  $scope.searchInit = function() {
    nubiiSearch.setSearchVar('location_name', $scope.search.location.formatted_address);
    nubiiSearch.setSearchVar('location_lat', $scope.search.location.geometry.location.A);
    nubiiSearch.setSearchVar('location_lng', $scope.search.location.geometry.location.F);
    $state.go('tab.ergebnisse');
  }

  /*
  * geolocation – get current lat and lng
  */
  $scope.getCurrentLocation = function() {
    ionic.Platform.ready(function() {
      var position = navigator.geolocation.getCurrentPosition(function(position) {
        $scope.search.location.lat = position.coords.latitude;
        $scope.search.location.lng = position.coords.longitude;
      });

    });
  };
})

My controller for the second state uses my service to fetch the data from the server and store it in §scope.posts

.controller('ErgebnisseCtrl', function($scope, $stateParams, nubiiSearch) {
  /*
  * get posts
  */

  nubiiSearch.getPosts().then(function(posts){
    $scope.posts = posts;
  },function(error){
    //Something went wrong!
  });

})

in my template for second state I iterate through scope with ng-repeat likes this

<ion-list class="list">
      <ion-item class="item-remove-animate item-avatar item-icon-right" ng-repeat="post in posts" type="item-text-wrap" href="#/tab/unterkuenfte/{{post.ID}}">
        <h2>{{post.title}}</h2>
        <p>{{post.ID}}</p>
      </ion-item>
    </ion-list>

The problem:

This works fine when I enter a location in the first state. The results are properly displayed on the second state. But when I go back to the first state and change the location, the second state doesn’t get updated. I think I miss some very basic thing here… the getPosts function in my service gets called when I updated the form input and the result get fetched (I can console.log it). But the $scope.posts doesn’t get update and so my view stays the same. Any help would be appreciated.

Thanks,
Florian


#2

keep in mind ionic has a built in view-cache.
Did you activate the forward cache?
http://ionicframework.com/docs/api/provider/$ionicConfigProvider/
views.forwardCache(value)

is your second controller called the second time you enter the state? … add a console log.
If you want to be sure that some code is executed everytime you enter a view you can use ionic-view events:
http://ionicframework.com/docs/api/directive/ionView/
–> $ionicView.enter


#3

Thank you so much for your help. I appreciate it.

forwardCache is not activated. My second controller is not called the when I enter the state second time (only the first time).

When I deactivated the caching (cache-view=“false”) it works basically as expected.

But when I deactivate the caching the ajax call gets run even when there is no change on the form input in the first state. So I hoped there would be a possibility to only rund the code on the second controller when the form input from the first state has changed.


#4

okay strange… maybe you have some issues with your routing… because if caching is active… forward views are not cached.

Okay so

  1. use the ionicView events to rerun your code
  2. if you trigger the search in state1 you need a flag to be sure the view form has changed, a simple solution -

your first search --> set flag that something changed --> set the form to pristine
second search --> before navigate to second state check if the form is pristine if not the form has changed in other cases the form is the same --> set the flag again

But maybe you can identify it easier because i do not know how complex your form is


#5

Thanks a lot! I must have been blind…simple flag. Your are right. That’s the solution

Solution
I set a property in my searchVars whether form object has changed as bengtler suggested. Then in my second controller I check on view enter $on('$ionicView.afterEnter', whether form input has changed and if so rerun the function from the service. So I can stick to cached view if not.


#6

Kein Problem, immer wieder gern :wink: