Persist data across views AngularJS with vs-google-autocomplete

658 Views Asked by At

I am building my first Angular App, which allows users to search a database of vendors based on a number of criteria. One of these criteria is their location and the distance to the vendor.

I have used the vs-google-autocomplete directive, which has been a great way to link into the google maps API. However, I have a problem around the persistency of this location data across views in the app.

To explain how it works at the moment. A user inputs their search criteria, a snapshot of all potential vendors is shown based on the users search criteria (this has been achieved through a custom directive). The user can then click to read more about a vendor, this takes them to the vendors full page (with more details etc.). It is at this stage that the location data is lost.

I have already created a service to store the information from other aspects of the search query, which is persisting just fine (except for the location data).

It appears that the problem is that the location input field automatically resets when a user leaves the page, thereby resetting the location field to null. But, I can't see where it is doing that in the code.

Does anyone have any thoughts about how to tackle this?

Code Below (unfortunately I could not get the custom directive actually working in JSFiddle, but hopefully it gives a good idea of what I am trying to achieve):

App.factory("searchquery", function() {
  return {};
});

App.controller('searchController', ['$scope', '$routeParams', '$rootScope', 'searchquery',
  function($scope, $routeParams, $rootScope, searchquery) {

    //Create a search query object

    $scope.searchquery = {};

    //Inject the searchquery service to ensure data persistency when in searchController pages

    $scope.searchquery = searchquery;

    //DEAL WITH GOOGLE AUTOCOMPLETE ADDRESSES
    //Restricts addresses to South Africa only

    $scope.options = {
      componentRestrictions: {
        country: 'ZA'
      }
    };

    //Creates an object to store the address information and parses it into its consitutent parts
    $scope.searchquery.address = {
      name: '',
      components: {
        streetNumber: '',
        street: '',
        city: '',
        state: '',
        countryCode: '',
        country: '',
        location: {
          lat: '',
          long: ''
        }
      }
    };
  }
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form name="Search">
  <!-- LOCATION -->
  <!-- ask the user to specify their location -->
  <div class="form-group">
    <label for="address">Address</label>
    <input vs-google-autocomplete="options" ng-model="searchquery.address.name" vs-street-number="searchquery.address.components.streetNumber" vs-street="searchquery.address.components.street" vs-city="searchquery.address.components.city" vs-state="searchquery.address.components.state"
    vs-country-short="searchquery.address.components.countryCode" vs-country="searchquery.address.components.country" vs-latitude="searchquery.address.components.location.lat" vs-longitude="searchquery.address.components.location.long" type="text" name="address"
    id="address" class="form-control">
  </div>
</form>

Thanks!

Jack

1

There are 1 best solutions below

4
On

I don't know your location data but you can persist data across views with two ways:

  • Service as you mentioned
  • Nested views

Please have a look at the demo below or here at jsfiddle.

The service data are not shared in the demo but that's also possible by injecting it in other views.

If the data are asynchronous you should have a look at resolve of ui-router. Then the data are loaded before the controller of the view is called.

angular.module('demoApp', ['ui.router'])
    .config(AppConfig)
    .factory('demoService', DemoService)
    .controller('demoController', DemoController);


function AppConfig($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('/');
    $stateProvider.state('home', {
        url: '/',
        template: 'HELLO from home route <input ng-model="text"/>'+
        '<div ui-view=""></div'
    })
        .state('home.profile', {
        url: '/profile',
            template: 'Hello from profile <input ng-model="text"/>'
    })
    .state('otherView', {
        url: '/other',
        controller: 'demoController',
        /*resolve: {
            text: function(demoService) {
                console.log(demoService);
                return demoService.get();
            }
        },*/
        template: 'Hello from other scope <input ng-model="text" ng-change="updateService(text)"/>'
    });
}

AppConfig.$inject = ['$stateProvider', '$urlRouterProvider'];

function DemoService() {
    return {
        _text: 'I am stored in service.',
        set: function(text) {
            this._text = text;
        },
        get: function() {
            return this._text;
        }
    }
}

function DemoController($scope, demoService) {
    $scope.text = demoService.get();
    $scope.updateService = function(newValue) {
        console.log(newValue);
        demoService.set(newValue);
    };
}

DemoController.$inject = ['$scope', 'demoService'];
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
<div ng-app="demoApp">
    <div ui-view=""></div> 
    <a ui-sref="home">home</a>
 <a ui-sref="home.profile">profile</a>
 <a ui-sref="otherView">other</a>
</div>