1

i'm trying to automatically update the END-DATE of my ui bootstrap datepicker when the START-DATE is greater than the END-DATE. The datepickers are inside a modal, and the function is done in AngularJS.

All the examples i've seen use $watch with $scope (i.e $scope.$watch), but the code I have doesn't have $scope, not sure what the syntax would be in my case.

I'm getting: Error: vm.event.$watch is not a function

Html (min-date is set to "vm.event.startsAt" on the END-DATE

      <div class="row">

                <div class="col-md-6">
                START DATE:<br />
                <p class="input-group" style="max-width: 250px">
                <input type="text" class="form-control" readonly datepicker-popup="medium" ng-model="vm.event.startsAt" is-open="vm.event.startOpen" close-text="Close" />
                <span class="input-group-btn">
                <button type="button" class="btn btn-default" ng-click="vm.toggle($event, 'startOpen', vm.event)"><i class="glyphicon glyphicon-calendar"></i></button>
                </span>
                </p>
                <timepicker ng-model="vm.event.startsAt" hour-step="1" minute-step="15" show-meridian="true"></timepicker>
                </div>

                <div class="col-md-6">
                END DATE:<br />
                <p class="input-group" style="max-width: 250px">
                <input type="text" class="form-control" readonly datepicker-popup="medium" ng-model="vm.event.endsAt" min-date="vm.event.startsAt" is-open="vm.event.endOpen" close-text="Close" />
                <span class="input-group-btn">
                <button type="button" class="btn btn-default" ng-click="vm.toggle($event, 'endOpen', vm.event)"><i class="glyphicon glyphicon-calendar"></i></button>
                </span>
                </p>
                <timepicker ng-model="vm.event.endsAt" hour-step="1" minute-step="15" show-meridian="true"></timepicker>
                </div>
      </div>     

AngularJS

'use strict';

angular
  .module('demo', ['mwl.calendar', 'ui.bootstrap', 'ngTouch', 'ngAnimate', 'ui.bootstrap.demo'])

  .controller('MainCtrl', function ($modal, moment, $http, $location) {

/* 
******************************************
****  Show Event Modal
******************************************
*/
    function showEventModal(action, event, events) {

      var modalInstance;

        modalInstance = $modal.open({
        templateUrl: 'modalEventContent.html',
        controller: function() {
          var vm = this;
          vm.action = action;
          vm.event = event;

          vm.events = events;

          vm.toggle = function($event, field, event) {
                $event.preventDefault();
                $event.stopPropagation();
                vm.event[field] = !vm.event[field];
          };

          // ----------------------------             
          // ------  Problem HERE -------
          // ----------------------------                         
          // ------  Update END DATE based on the START DATE 
          vm.event.$watch('startsAt', function (newVal, oldVal) {
            if(!newVal) return;

            // if the new start date is greater than the current end date .. update the end date
            if(vm.event.endsAt){
              if( +vm.event.endsAt < +vm.event.startsAt ){
                vm.event.endsAt = newVal;
              }
            } else {
              // just set the end date
              vm.event.endsAt = newVal;
            }
          });   


          vm.eventSaved = function(event) { 

               $http.put(urlapievents + event.eventid, vm.event).success(function(eventsuccess){
               }).error(function(err){
                    /* do something with errors */
               });

               modalInstance.close();
          };

          modalInstance.close();
          };

        },
        controllerAs: 'vm'
      });
    }

update#1

Added the $scope dependency to my controller, the error is gone but the function doesn't react to the change

      // ------  Update END DATE based on the START DATE (only valid for calendar view)
      $scope.$watch('vm.event.startsAt', function (newVal, oldVal) {
        if(!newVal) return;

        // if the new start date is greater than the current end date .. update the end date
        if(vm.event.endsAt){
          if( +vm.event.endsAt < +vm.event.startsAt ){
            vm.event.endsAt = newVal;
          }
        } else {
          // just set the end date
          vm.event.endsAt = newVal;
        }
      });   

2 Answers 2

2

add the $scope dependency to your controller:

.controller('MainCtrl', function ($scope, $modal, moment, $http, $location) { ..}

that's why the $watch couldn't be found, because it belongs to a scope object which did not exist.

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

2 Comments

Thanks @bosch, I added the $scope dependency to my controller, the error is gone, but the function doesn't seem to react to the date changes. Any idea? I've added an update in my question
Try watching with a top-bottom approach to see exactly what the watcher sees, like $scope.$watch('vm', function(){}); and then drill down through the object hierarchy. I cannot predict what you should see as I don't really understand your setup (modals, controller, directives,etc). Keep us updated...
0

So the reason why you are having an issue here is because $watch lives only on the $scope object. Because you are using the bindToController syntax you do not use scope and therefore it doesn't exist.

If you wanted to use a $watch in your controller (which is not recommended), you can do so by injecting $scope with Dependency injection. Then you can attach the $watch with $scope.$watch

If you want to use a $watch, it is better to use in a directive. It can be hard to test overall.

There are certain timepickers like ui-bootstraps uib-timepicker which support the ng-change directive for event handling.

So if your <timepicker></timepicker> element can use ng-change you can add that on your element and then call the same validation function you are using in your controller.

Here is a plunker using the ng-change of a timepicker

3 Comments

Thanks, would you have a better solution (than using $watch) to update my END-DATE automatically when the START_DATE gets greater than END-DATE?
Is this <timepicker> element a custom input or part of a bootstrap library?
I'm using the timepicker, but the datepicker is were I have my problem

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.