1
votes

I'm having a problem which seems completely crazy! I use a directive that takes some attributes bound to its scope, that take a value from a parent scope variable. All very normal.. ...except when I do console.log(scope), the attributes are displayed normally as scope object's properties with the expected value, but when I do console.log(scope.myAttr) then I get undefined!!

Has anyone encountered something like this before??

   // In parent directive:


scope.datepickerOptions.enableTime = false;




// In directive:

angular.module('myModule')
	.directive('datepicker', function() {
		return {
			require: 'ngModel',
			restrict : 'A',
			scope: {
				format: '@',
				enableTime: '=',
				minDate: '@',
				maxDate: '@',
				mode: '@'
			},
			link : function(scope, element, attrs, ngModel) {
				console.log("scope")
				console.log(scope)
				// displays all properties with expected values
                //=> scope.enableTime: false

				console.log("enableTime")
				console.log(scope.enableTime)
        // undefined (!!!)
        
        
        ...
   // In parent template:

...

<input
  type="text"
  id="events_date"
  name="events_date"
  ng-model="events.selectedDate"
  placeholder="Select Date Range"
  ng-change="setQueryDate()"
  format="d M Y"
  mode="range"
  enable-time="datepickerOptions.enableTime"
  max-date="today"
  datepicker>
  
  
  ...

I also tried: enable-time="{{datepickerOptions.enableTime}}" with enableTime: '@'

and I get the same craziness when I do console.log(attrs) and console.log(attrs.enableTime)

Same thing when I put a controller with $scope argument: console.log($scope) displays everything normally, but console.log($scope.enableTime) gives undefined

3
Try using 'attrs'. When the link function is executed, the scope properties aren't set yet. It gets set afterwards. That is why you get 'undefined' when you try to reference it directly. The scope object in your console displays the final state of the scope. - Hoyen
If you really need to use the 'scope' object, do it with the directive's controller function instead of the link function. - Hoyen
But won't the attrs.enableTime have "datepickerOptions.enableTime" as a value? And why all the other directives in the project function normally? Is it the restrict: 'A' that does this behaviour ? - Dimitris Papazacharias
Do you need a new scope without a controller? Why not just scope: false so it is in the same scope as the variables already? - Dillon
Can you once please try enable-time="true" in directive html and check whether its is getting logged in console - Srinivas ML

3 Answers

1
votes

I think what is happening is that you are setting enableTime after the directive is created. If that is the case you can use the 'ng-if' directive to check if it is defined first before loading it.

Here's an example of what I think is happening:

var app = angular.module('test', []);

app.controller('MainCtrl', function($scope, $timeout) {
  $scope.datepickerOptions = {}
  $timeout(function() {    
    $scope.datepickerOptions.enableTime = false;
  }, 500);
});
app.directive('datepicker', function() {
  return {
    restrict: 'A',
    scope: {
      enableTime: '='
    },
    link: function(scope, element, attrs, ngModel) {
      console.log("scope")
      console.log(scope)
        // displays all properties with expected values
        //=> scope.enableTime: false

      console.log("enableTime")
      console.log(scope.enableTime)
    }
  }
});
<!DOCTYPE html>
<html ng-app="test">

<head>
  <script data-require="[email protected]" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <input datepicker ng-if="datepickerOptions.enableTime != null" enable-time="datepickerOptions.enableTime" />
</body>
</html>
0
votes

I don't see any scope variables in your directive. If you want to keep any attribute value as scope variable, just do something like this:

scope.yourVariable = attrs.yourAttribute;
0
votes

It seems that if I do

$timeout(function(){
  console.log(scope.enableTime)
}, 600)

//and in parent directive

$timeout(function(){
  scope.datepickerOptions.enableTime = true //or whatever
}, 500)

everything falls into place. But it doesn't seem to me like a clean solution. After all, I've never encountered something like this before, and how can anyone be sure when his/her directive will load and render??