1

I'm writing a directive.

This is the code i'm using:

angular.module('weather', []).directive('myWeather', [
  '$ionicSideMenuDelegate', function($ionicSideMenuDelegate) {
    var createWeatherConditionLabel, linkFunction;

    createWeatherConditionLabel = function(type) {
      var label;
      label = '';
      debugger;
      switch (type) {
        case 0:
          label = 'Clear';
          break;
        case 1:
          label = 'Clear';
          break;
        case 2:
          label = 'Light Cloud';
          break;
        case 3:
          label = 'Light Cloud';
          break;
        case 5:
          label = 'Windy';
          break;
        case 6:
          label = 'Foggy';
          break;
        case 7:
          label = 'Cloudy';
          break;
        case 15:
          label = 'Rain';
          break;
        case 18:
          label = 'Sleet';
          break;
        case 21:
          label = 'Hail';
          break;
        case 27:
          label = 'Snow';
          break;
        case 30:
          label = 'Showers';
      }
      return label;
    };

    linkFunction = function(scope, el, attr) {
      console.log("scope:", scope);
      scope.showWeatherDetails = false;
      scope.evtClickExpandMenuWeather = function() {
        if (scope.showWeatherDetails === false) {
          return scope.showWeatherDetails = true;
        } else {
          return scope.showWeatherDetails = false;
        }
      };
      scope.$watch((function() {
        return $ionicSideMenuDelegate.isOpenRight();
      }), function(isOpen) {
        if (!isOpen) {
          return scope.showWeatherDetails = false;
        }
      });
      return scope.weatherLabel = createWeatherConditionLabel(scope.weatherType);
    };
    return {
      restrict: 'E',
      replace: true,
      templateUrl: './directives/tpl.html',
      scope: {
        weatherData: "=",
        weatherType: "="
      },
      link: linkFunction
    };
  }
]);

and the directive is called like this:

<my-weather weather-data="zones[0].weatherData" weather-type="zones[0].weatherData.weather_type"></my-weather>

I need to call a function to create weatherLabel and use this in the directive template, but I can't because scope.weatherType is undefined.

How can I wait for scope to be defined before calling the link function?

or, is there a better and efficient (performance wise) way to do this? thanks a lot for any help

Nick
  • 13,493
  • 8
  • 51
  • 98

2 Answers2

1

1st way: <my-weather ng-if="zones[0].weatherData.weather_type" ... so just your directive is not launched untill variable is resolved. 2nd way: use watch on 'weatherType' in directive and update your label.

P.S. your switch is awesome, but better init map i.e.

var LABELS = {0 : '...', 1 : '...', ...}

and just retrieve label from it.

Petr Averyanov
  • 9,327
  • 3
  • 20
  • 38
  • Thanks for the suggestions. Do you think it's better with the IF or with the watch? which one is more efficient and fast? And yes, maybe you're right. I change it to map, thanks for that as well :) – Nick Jun 14 '16 at 14:58
  • I used the IF at the end. Thanks again for the suggesitons – Nick Jun 14 '16 at 15:09
  • Actually ng-if uses watch, so it more or less the same - your own watch is a bit more flexible, when ng-if is fast and easy. – Petr Averyanov Jun 14 '16 at 15:18
0

You're using the bidirectional binding isolate scope. The doc says:

= or =attr - set up a bidirectional binding between a local scope property and an expression passed via the attribute attr. The expression is evaluated in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name.

What is the value of zones[0].weatherData.weather_type in your controller? If this property is undefined, scope.weatherType in your directive is undefined too.

I wrote an example on plunker. You see how bidirectional binding works.

https://plnkr.co/edit/qK70Z1t1CLI0o5bV7a0Y

script.js

var appModule = angular.module('myApp', [])
  .controller('testCtrl', ['$scope', function($scope) {
    $scope.controllerScope = {
      "message": "I am a two ways binding isolate scope"
    };
  }])
  .directive('testDirective', function() {
    return {
      templateUrl: "directive-tpl.html",
      replace: true,
      restrict: "E",
      scope: {
        directiveScope: "="
      },
      link: function(scope) {
        console.log(scope.directiveScope.message);
      }
    }
  });

index.html

<!DOCTYPE html>
<html ng-app='myApp'>

  <head>
    <script data-require="angularjs@1.5.5" data-semver="1.5.5" src="https://code.angularjs.org/1.5.5/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller='testCtrl'>
    <p>TEST ISOLATE SCOPE</p>
    <p>This is controllerScope:</p>
    <p>{{controllerScope}}</p>
    <test-directive directive-scope='controllerScope'></test-directive>
  </body>

</html>

directive-tpl.html

<div>
  <p>Hello! I am the template of test-directive</p>
<p>In my scope i have this: </p>
<p>{{directiveScope}}</p>
</div>
user3083618
  • 270
  • 1
  • 4
  • 16