1

I have have an input field which is attached an Angular UI datepicker. Below that, I added 2 buttons to change date, "day by day".

Here is the input part (just after in my page):

<p class="input-group">
    <span class="input-group-addon hidden-xs">From</span>
    <input type="text" class="form-control text-center" datepicker-popup="{{format}}" ng-model="parent.dtFrom"   ng-change="refresh(0)" show-button-bar="false" is-open="opened1" max-date="maxDate" datepicker-options="dateOptions" ng-required="true" close-text="Close" readonly />
    <span class="input-group-btn">
        <button type="button" class="btn btn-default" ng-click="open($event, 'opened1')"><i class="glyphicon glyphicon-calendar"></i></button>
    </span>
</p>

And here are my button to change it:

 <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 btn-group" role="group" >
   <div class="text-center" >
     <button type="button" class="btn btn-default btn-outline glyphicon glyphicon-chevron-left text-center previousdate" ng-click="addDayFrom(-1)"></button>
     <button type="button" class="btn btn-default btn-outline glyphicon glyphicon-home text-center todaydate"  ng-click="DateFromToday()"></button>
     <button type="button" class="btn btn-default btn-outline glyphicon glyphicon-chevron-right text-center nextdate" ng-click="addDayFrom(1)" ng-show="parent.dtFrom < todate" ></button>
   </div>
 </div>

Here is how I init my dtFrom at the begin of my controller:

$scope.parent={
    dtFrom : new Date(),
    dtTo : new Date()
};

And this is my function for change dtFrom:

$scope.addDayFrom=function(day){
    $scope.parent.dtFrom.setDate($scope.parent.dtFrom.getDate() +  parseInt(day));
    console.log($scope.parent.dtFrom);
};

It change value in $scope.parent.dtFrom but model isn't updated into input.

Example: Today we are 12/05/2015.

If I click one time on previous button, $scope.parent.dtFrom will be 11/05/2015.

And that's what is displayed all but the input.

I suppose that's a scope issue, but can't figure out where it is. Have you any clue to fix this ?

Edit: Picture here : http://hpics.li/4e0fab6

6
  • Try printing {{parent.dtFrom}} before the input and see if the value is changing as you expect. Commented May 12, 2015 at 12:51
  • It changes, that's why i don't get where is the problem Commented May 12, 2015 at 12:57
  • Is it calling refresh(0)? Commented May 12, 2015 at 13:12
  • Nope, I guess it should. Then it implies that Angular didn't caught the change $scope.parent.dtFrom ? Should I add a $watch ? Commented May 12, 2015 at 13:29
  • I found a solution but it's more hack than Angular way's. Commented May 12, 2015 at 14:05

2 Answers 2

1

Change your code from:

$scope.addDayFrom=function(day){
    $scope.parent.dtFrom.setDate($scope.parent.dtFrom.getDate() +  parseInt(day));
    console.log($scope.parent.dtFrom);
};

To this:

$scope.addDayFrom=function(day){
    $scope.parent.dtFrom = ($scope.parent.dtFrom.getDate() +  parseInt(day));
    console.log($scope.parent.dtFrom);
};

Looking at the Angular UI datepicker documentation, you can see that you don't need to access parent. I thought you were trying to access the parent scope, but actually you were accessing the parent attribute that you have set here:

$scope.parent={
    dtFrom : new Date(),
    dtTo : new Date()
};

Angular UI datepicker is watching by reference, as we can see in their source code, what makes perfect sense, since that's the most efficient watching strategy. To understand more about that, read Scope $watch Depths on Angular core documentation:

Scope $watch Depths

Dirty checking can be done with three strategies: By reference, by collection contents, and by value. The strategies differ in the kinds of changes they detect, and in their performance characteristics.

  • Watching by reference (scope.$watch (watchExpression, listener)) detects a change when the whole value returned by the watch expression switches to a new value. If the value is an array or an object, changes inside it are not detected. This is the most efficient strategy.
  • Watching collection contents (scope.$watchCollection (watchExpression, listener)) detects changes that occur inside an array or an object: When items are added, removed, or reordered. The detection is shallow - it does not reach into nested collections. Watching collection contents is more expensive than watching by reference, because copies of the collection contents need to be maintained. However, the strategy attempts to minimize the amount of copying required.
  • Watching by value (scope.$watch (watchExpression, listener, true)) detects any change in an arbitrarily nested data structure. It is the most powerful change detection strategy, but also the most expensive. A full traversal of the nested data structure is needed on each digest, and a full copy of it needs to be held in memory.

    enter image description here

That's why it wasn't detecting $scope.parent.dtFrom.setDate(newDate) usage, and the model wasn't being updated. So, just change that piece of code to $scope.parent.dtFrom = newDate, and it should work (as it has already worked with your global variable approach).

Sign up to request clarification or add additional context in comments.

Comments

0

It's a bit of hack but, it works ... so I share it with you

When i start my app i create a local date variable that i change when i click on my button. when it's done, i do that :

$scope.parent.dtFrom = new Date(localDateVariable);

Not the best solution, but a solution.

2 Comments

Maybe $scope.parent.dtFrom.setDate($scope.parent.dtFrom.getDate() + parseInt(day)); isn't correct. How do you set locaDateVariable?
When app start, I init $scope.parent.dtFrom and my localDateVariable as date object. Then, on click event on previous day button, i fire a function which remove one day to localDateVariable with localDateVariable.setDate(localDateVariable.getDate() + parseInt(day));, Then i just assign it to $scope.parent.dtFrom = new Date(localDateVariable); For keeping updated my local variable, when i catch change event from datepicker on my input, I do that : localDateVariable = $scope.parent.dtFrom;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.