javascript - Getting $watch is not a function error in AngularJS - Stack Overflow

i'm trying to automatically update the END-DATE of my ui bootstrap datepicker when the START-DATE

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;
        }
      });   

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;
        }
      });   
Share Improve this question edited Nov 18, 2015 at 15:43 user3489502 asked Nov 18, 2015 at 14:41 user3489502user3489502 3,61110 gold badges44 silver badges69 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 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.

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 remended), 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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745176903a4615234.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信