I've come across a quite a few similar questions and tried them all with no success. I'm not sure if I'm doing this the "Angular way" so I might need to change my approach. In short I'm initialising a scoped variable from within a controller, the variable is then shared with the directive's scope. However when this value is changed as part of a user interaction the new value is not being synchronised with the controllers variable. My abbreviated code follows:
Controller
The $watch method is only called once i.e. when the page loads.
.controller('NewTripCtrl', ['$scope', function($scope) {
$scope.pickupLocation;
$scope.dropoffLocation;
$scope.$watch('dropoffLocation', function(oldVal, newVal) {
console.log('dropofflocation has changed.');
console.log(oldVal);
console.log(newVal);
});
}])
HTML
<div class="padding">
<input ion-google-place type="text" class="ion-google-place" autocomplete="off" service="places" placeholder="Pickup Address" location="pickupLocation"></input>
</div>
<div class="padding">
<input ion-google-place type="text" class="ion-google-place" autocomplete="off" service="places" placeholder="Dropoff Address" location="dropoffLocation"></input>
</div>
Directive
angular.module('ion-google-place', [])
.directive('ionGooglePlace', [
'$ionicTemplateLoader',
'$ionicBackdrop',
'$q',
'$timeout',
'$rootScope',
'$document',
function ($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $document) {
return {
restrict: 'A',
scope: {
location: '=location'
},
link: function (scope, element, attrs) {
scope.locations = [];
console.log('init');
console.log(scope);
console.log(attrs);
// var geocoder = new google.maps.Geocoder();
var placesService = new google.maps.places.AutocompleteService();
var searchEventTimeout = undefined;
var POPUP_TPL = [
'<div class="ion-google-place-container">',
'<div class="bar bar-header item-input-inset">',
'<label class="item-input-wrapper">',
'<i class="icon ion-ios7-search placeholder-icon"></i>',
'<input class="google-place-search" type="search" ng-model="searchQuery" placeholder="' + 'Enter an address, place or ZIP code' + '">',
'</label>',
'<button class="button button-clear">',
'Cancel',
'</button>',
'</div>',
'<ion-content class="has-header has-header">',
'<ion-list>',
'<ion-item ng-repeat="l in locations" type="item-text-wrap" ng-click="selectLocation(l)">',
'{{l.formatted_address || l.description }}',
'</ion-item>',
'</ion-list>',
'</ion-content>',
'</div>'
].join('');
var popupPromise = $ionicTemplateLoader.compile({
template: POPUP_TPL,
scope: scope,
appendTo: $document[0].body
});
popupPromise.then(function (el) {
var searchInputElement = angular.element(el.element.find('input'));
// Once the user has selected a Place Service prediction, go back out
// to the Places Service and get details for the selected location.
// Or if using Geocode Service we'll just passing through
scope.getDetails = function (selection) {
//console.log('getDetails');
var deferred = $q.defer();
if (attrs.service !== 'places') {
deferred.resolve(selection);
} else {
var placesService = new google.maps.places.PlacesService(element[0]);
placesService.getDetails({
'placeId': selection.place_id
},
function(placeDetails, placesServiceStatus) {
if (placesServiceStatus == "OK") {
deferred.resolve(placeDetails);
} else {
deferred.reject(placesServiceStatus);
}
});
}
return deferred.promise;
};
// User selects a Place 'prediction' or Geocode result
// Do stuff with the selection
scope.selectLocation = function (selection) {
// If using Places Service, we need to go back out to the Service to get
// the details of the place.
var promise = scope.getDetails(selection);
promise.then(onResolve, onReject, onUpdate);
el.element.css('display', 'none');
$ionicBackdrop.release();
};
function onResolve (details) {
console.log('ion-google-place.onResolve');
scope.location = details;
$timeout(function() {
// anything you want can go here and will safely be run on the next digest.
scope.$apply();
})
if (!scope.location) {
element.val('');
} else {
element.val(scope.location.formatted_address || '');
}
}
// more code ...
};
}
]);
The $watch function only detects a change when the page loads but never again. What is the correct way to provide the controller with the value that the user enters into the directive's input element?
anonymous function. Something like$scope.$watch(function(){return $scope.dropoffLocation}, function(){})..... Maybe it helps.