Reputation: 3579
$watch doesn't triggered then I change my datepicker. Why?
Update: I've noticed that my departDate and returnDate doesn't change when I select a new date. What could be a reason?
var app = angular.module("fly");
(function(){
function Controller($scope, searchData) {
$scope.$watch('departDate', function(newValue, oldValue){
$scope.departDate = newValue;
searchData.setDateFrom(newValue);
if(searchData.getDateFrom() > searchData.getDateTo()) {
searchData.setDateFrom(newValue);
searchData.setDateTo(newValue);
$scope.returnDate = newValue;
}
});
$scope.$watch('returnDate', function(newValue, oldValue){
$scope.returnDate = newValue;
searchData.setDateTo(newValue);
if(searchData.getDateFrom() > searchData.getDateTo()) {
searchData.setDateFrom(newValue);
searchData.setDateTo(newValue);
$scope.departDate = newValue;
}
});
$scope.datePickerStates = {
open1:false,
open2:false
};
$scope.open = function($event, opened) {
$event.preventDefault();
$event.stopPropagation();
$scope.datePickerStates[opened] = true;
};
$scope.today = function() {
$scope.dt = new Date();
};
$scope.today();
$scope.clear = function () {
$scope.dt = null;
};
$scope.toggleMin = function() {
$scope.minDate = $scope.minDate ? null : new Date();
};
$scope.toggleMin();
$scope.dateOptions = {
formatYear: 'yyyy',
startingDay: 1
};
$scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
$scope.format = $scope.formats[0];
}
app.controller('DatePickerController', Controller);
})();
HTML:
<div class="col-md-2">
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" min-date="minDate" ng-model="departDate" is-open="datePickerStates.open1" ng-required="true" close-text="Close" />
<span ng-click="open($event, 'open1')" class="btn btn-default input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="col-md-2">
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" min-date="minDate" ng-model="returnDate" is-open="datePickerStates.open2" ng-required="true" close-text="Close" />
<span ng-click="open($event, 'open2')" class="btn btn-default input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
UPDATE:
This where I declare my nested controllers and using directives.
<div ng-controller="DatePickerController">
<div ng-controller="PassengerController as pd">
<div ng-controller="PlaceController as pc">
<search-bar-md></search-bar-md>
<search-bar-sm></search-bar-sm>
<search-bar-xs></search-bar-xs>
<pre>{{departDate}}</pre>
<pre>{{returnDate}}</pre>
</div>
</div>
</div>
app.js
var app = angular.module("fly", ['ui.bootstrap', 'ngAnimate']);
app.factory('searchData', function () {
var data = {
travelFrom: '',
travelTo: '',
dateToday: new Date(),
dateFrom: new Date(),
dateTo: new Date()
};
return {
getTravelFrom : function() {
return data.travelFrom;
},
setTravelFrom : function(travelFrom){
data.travelFrom = travelFrom;
},
getTravelTo : function(){
return data.travelTo;
},
setTravelTo : function(travelTo){
data.travelTo = travelTo;
},
/*** Travel dates ***/
getTodayDate : function(){
return data.dateToDay;
},
getDateFrom : function(){
return data.dateFrom;
},
setDateFrom : function(dateFrom){
data.dateFrom = dateFrom;
},
getDateTo : function(){
return data.dateTo;
},
setDateTo : function(dateTo){
data.dateTo = dateTo;
}
};
});
app.directive('navBar', function() {
return {
restrict: 'E',
templateUrl: 'templates/navbar/navbar.html'
};
});
app.directive('searchBar', function() {
return {
restrict: 'E',
templateUrl: 'templates/search-bar/search-bar.html'
};
});
app.directive('searchBarMd', function() {
return {
restrict: 'E',
templateUrl: 'templates/search-bar/search-bar-md.html'
};
});
app.directive('searchBarSm', function() {
return {
restrict: 'E',
templateUrl: 'templates/search-bar/search-bar-sm.html'
};
});
app.directive('searchBarXs', function() {
return {
restrict: 'E',
templateUrl: 'templates/search-bar/search-bar-xs.html'
};
});
Upvotes: 0
Views: 406
Reputation: 1034
Creating a wrapper object should solve it: http://plnkr.co/edit/o8iwrVIYJq9wG74f0uR0?p=preview
Main change is adding the wrapper object in DatePickerController
:
$scope.dates = {}
Then use that object to store the dates as follows:
<div ng-controller="DatePickerController">
<div class="col-md-2">
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" min-date="minDate" ng-model="dates.departDate" is-open="datePickerStates.open1" ng-required="true" close-text="Close" />
<span ng-click="open($event, 'open1')" class="btn btn-default input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class="col-md-2">
<div class="input-group">
<input type="text" class="form-control" datepicker-popup="{{format}}" min-date="minDate" ng-model="dates.returnDate" is-open="datePickerStates.open2" ng-required="true" close-text="Close" />
<span ng-click="open($event, 'open2')" class="btn btn-default input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
The reason why this works is because ng-model replaces the instances of the referenced objects with others. Each controller has it's own scope but it inherits from it parent scope, but when using nested controllers with ng-model, only the inmediate $scope's object is modified. For example if we have controller1 and a nested controller2:
//Initial state:
controller1Scope.property='initial'
controller2Scope.property='initial' //Inherited from controller1 scope
//After ng-model="property" input is changed to 'new_value':
controller1Scope.property='initial'
controller2Scope.property='new_value'
If you use a wrapper object then it's shared in all the scopes, and when some of it's properties is changed, it affects all of them:
//Initial state:
controller1Scope.wrapper={property:'initial'}
controller2Scope.wrapper={property:'initial'} //Inherited from controller1 scope
//After ng-model="wrapper.property" input is changed to 'new_value':
controller1Scope.wrapper={property:'new_value'}
controller2Scope.wrapper={property:'new_value'} //Inherited from controller1 scope
Upvotes: 1
Reputation: 6257
Initialize $scope.departDate
and $scope.returnDate
in controller with some default value.
JS:
function Controller($scope, searchData) {
$scope.departDate = ''; //you can set your own default value
$scope.returnDate = ''; //you can set your own default value
... }
Upvotes: 0