我遇到了很多类似的问题并尝试了所有这些问题都没有成功。我不确定我是否正在以“Angular方式”这样做,所以我可能需要改变我的方法。简而言之,我正在从控制器中初始化一个范围变量,然后该变量与指令的范围共享。但是,当此值作为用户交互的一部分更改时,新值不会与controllers变量同步。我的缩写代码如下:
$ watch方法只调用一次,即页面加载时。
.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);
});
}])
<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>
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 ...
};
}
]);
$ watch功能仅在页面加载时检测到更改,但从不再检测到。向控制器提供用户输入指令输入元素的值的正确方法是什么?
答案 0 :(得分:1)
以下是您的选择
选项#1使用ng-model 在父控制器中使用监视功能
<input ion-google-place type="text" class="ion-google-place" autocomplete="off" service="places" placeholder="Dropoff Address" ng-model="dropoffLocation"></input>
并在指令
中scope: {
location: '=ngModel'
},
你在这里不需要Watch
。
选项#2通过对象字面
.controller('NewTripCtrl', ['$scope', function($scope) {
$scope.locationChanged = function(location){
//you watch code goes here
}
}
<input ion-google-place type="text" class="ion-google-place" autocomplete="off" service="places" placeholder="Dropoff Address" location="dropoffLocation" location-changed="locationChanged(location)" ></input>
//指令范围
scope: {
location: '=',
locationChanged: '&'
}
//在链接函数中调用父控制器方法为
scope.locationChanged({location:scope.location});
选项#3通过功能参考
controllect和指令范围与选项#2相同
<input ion-google-place type="text" class="ion-google-place" autocomplete="off" service="places" placeholder="Dropoff Address" location="dropoffLocation" location-changed="locationChanged" ></input>
//in link function invoke parent controllers method as
scope.locationChanged()(scope.location);
建议选项#2以提高可读性。
应尽可能避免观察变量。
答案 1 :(得分:1)
正如angular docs所说:
范围继承通常很简单,你甚至不需要知道它正在发生......直到你尝试双向数据绑定(即表单元素,ng-模型)到一个原语(例如,数字,字符串,布尔值)在子范围内从父范围定义。
使用基元进行双向数据绑定时,这是一个常见问题。尝试这样做,但尝试共享一个对象而不是原始。
即:
.controller('NewTripCtrl', ['$scope', function($scope) {
$scope.pickupLocation = {location: ''};
$scope.dropoffLocation = {location: ''};
...