1

Im trying to pass the date from a date picker value into a $http session parameter (like "2017-12-7"), but the date my datepicker Date variable is 'undefined'

angular.module('MyApp', ['ngMaterial']).controller('MyController',
            function($scope, $http) {                   

                  this.myDate = new Date();
                  this.minDate = new Date("December 4, 2017");
                  this.maxDate = new Date("December 10, 2017");

                  $scope.getDataFromServer = function() {

                      var dt = this.myDate;

                        $http({

                            method : 'GET',
                            url : 'myurl',
                            params : {
                                pdate : this.myDate
                            }
                        }).then(function mySuccess(response) {
                            $scope.datacontainer= response.data;
                        }, function myError(response) {

                        });
                    };

        });

The $scope.getDataFromServer method is called when you click a button. The following line var dt = this.myDate; was to look at the myDate object in chrome DevTools (F12) and it says 'undefined'.

The date picker HTML is as follows:

<div flex="20">
  <md-datepicker ng-model="myDate" md-placeholder="Enter date" md-min-date="ctrl.minDate" md-max-date="ctrl.maxDate">
  </md-datepicker>
</div>
beaumondo
  • 4,862
  • 7
  • 29
  • 42
  • 1
    try preserving parent this before using like `var myContext = this;` and get `myContext.myDate` – Gurkan Yesilyurt Jan 01 '18 at 14:22
  • 1
    @beaumondo - You probably defined the controller like `MyApp as ctrl` in the view, so you need to set the modal like this: `ng-model="ctrl.myDate"`. In the controller itself, put on the very top line of the controller function this: `var ctrl = this;` and then change all the current `this` and `$scope` to `ctrl` so your code will be more readable. Don't forget the add the `ctrl.` prefix for any other controller properties in the VIEW – Alon Eitan Jan 01 '18 at 14:41

2 Answers2

3

this.myDate is evaluated to undefined here because this is in different context when getDataFromServer is executed. The problem here is you have initialized myDate inside MyController and function is defined inside $scope. Read more about the difference here.

getDataFromServer cannot see myDate as its created inside MyController.

Solution:

Define them both in same context.

angular.module('MyApp', ['ngMaterial']).controller('MyController',
        function($scope, $http) {                   
              var ctrl = this;
              ctrl.myDate = new Date();
              ctrl.minDate = new Date("December 4, 2017");
              ctrl.maxDate = new Date("December 10, 2017");

              ctrl.getDataFromServer = function() {

                  var dt = ctrl.myDate;

                    $http({

                        method : 'GET',
                        url : 'myurl',
                        params : {
                            pdate : ctrl.myDate
                        }
                    }).then(function mySuccess(response) {
                        ctrl.datacontainer= response.data;
                    }, function myError(response) {

                    });
                };

    });

Example:

angular.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache']).controller('AppCtrl', function($scope, $http) {
  var ctrl =this;
  ctrl.myDate = new Date();
  ctrl.value="No Date Selected";
  ctrl.getDataFromServer = function() {
    ctrl.value = ctrl.myDate;
  }
});
<link href="https://material.angularjs.org/1.1.5/docs.css" rel="stylesheet"/>
<link href="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.5/angular-material.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-114/svg-assets-cache.js"></script>
<script src="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.5/angular-material.js"></script>

<md-content ng-controller="AppCtrl as ctrl" layout-padding="" ng-cloak="" class="datepickerdemoBasicUsage" ng-app="MyApp">
  <div layout-gt-xs="row">
    <div flex-gt-xs="">
      <h4>Standard date-picker</h4>
      <md-datepicker ng-model="ctrl.myDate" md-placeholder="Enter date"></md-datepicker>
    </div>
    <md-button class="md-raised" ng-click="ctrl.getDataFromServer()">Print</md-button>
  </div>
  {{ctrl.value}}
</md-content>
Raghu
  • 909
  • 7
  • 23
  • 1
    I would recommend to save a reference to `this` at the first line of the controller (i.e `var ctrl = this;` or `var vm = this;`) and use that reference throughout the controller, this will ensure that you don't lose the reference to the controller in inner functions, so you could change `$scope.datacontainer= response.data;` to `ctrl.datacontainer= response.data;` in the success callback of the ajax call – Alon Eitan Jan 01 '18 at 15:08
  • 3
    @AlonEitan Thanks for suggestion. Modified answer to reflect the changes.`this` reference is one of the easily confused aspect of JS. – Raghu Jan 01 '18 at 15:33
  • Good call, solution worked well. I thought because it was a nested function inside the controller all local variable were accessible – beaumondo Jan 01 '18 at 17:50
0
angular.module('MyApp', ['ngMaterial']).controller('MyController',
        function($scope, $http) {                   
              var that = this;
              that.myDate = new Date();
              that.minDate = new Date("December 4, 2017");
              that.maxDate = new Date("December 10, 2017");

              $scope.getDataFromServer = function() {
                  var dt = that.myDate;

                    $http({

                        method : 'GET',
                        url : 'myurl',
                        params : {
                            pdate : that.myDate
                        }
                    }).then(function mySuccess(response) {
                        $scope.datacontainer = response.data;
                    }, function myError(response) {

                    });
                };

    });
  • 2
    What is this, an answer or what? Read [answer], explain what you changed, the OP is not supposed to guess your explanation. And BTW, you have a bug in your answer, and it shouldn't solve anything at all – Alon Eitan Jan 01 '18 at 14:33