Simon H
Simon H

Reputation: 21007

Angular Directive using '=' scope & controllerAs

I'm trying to write a Directive to decode and encode some information. Basically I am storing 5 binary pieces of information in a database using an Int (giving each bit a value of 16, 8, 4, 2, 1).

I need to ways of editing the data: as an Int, and as bits. But I have lots of problems connecting them up, and these are (deliberately) compounded by using controllerAs notation.

1) When I change the Int nothing changes in the bits. This is because the link function only seems to load once - how can I have a change in a model update information in a Directive?

<input ng-model="c.int" type="text" />
<testdir score="c.int"></testdir>

My Directive includes:

scope: {
  score: '='
},
controller: function() {
  var vm = this;
  vm.recChange = function() {
    // convert bits to score
  }
},
controllerAs: 'd',
link: function(scope, elem, attrs) {
  // convert score to bits

and a link function that converts score into scope.recommendations, which is an array 5 bits.

2) When I change the bits (and have controllers using $scope) then the Int does change. But I cannot find a way to use controllerAs - the link function uses scope whereas my controller needs a d. prefix.

template: "<label ng-repeat='(key, recommendation) in recommendations' class='checkbox-inline'>

// template: "<label ng-repeat='(key, recommendation) in d.recommendations' class='checkbox-inline'> \

Plnkr

Upvotes: 3

Views: 179

Answers (2)

Peter Morris
Peter Morris

Reputation: 23224

After your "controllerAs" value you need to add bindToController:true

Upvotes: 1

ryeballar
ryeballar

Reputation: 30108

You have to use scope.score instead of using the attribute value of the score since you're using the two-way data binding notation = in your scope declaration for score. Additionally, when changes for a certain exists, then simply place watcher for that value and apply your changes therein.

UPDATE: Simply add your directive's name in the require key value of your directive definition, and you should be able to access your controller in your link function as the fourth argument.

FORKED PLUNKER

.directive('testdir', function() {
  var recommendationCategories = ['16RotM', '8Top5', '4Price', '2Cuisine', '1Area'];

  return {

    require: 'testdir',

    scope: {
      score: '='
    },

    controller: function () {
       // .....
    },

    controllerAs: 'd',

    link: function(scope, elem, attrs, ctrl) {

      console.log(ctrl);

      scope.$watch('score', function() {
        scope.recommendations = {};
        var score = parseInt(scope.score);
        // decode recommendations
        // convert to binary string
        var bitVal = score.toString(2);
        //pre-pad with "0"
        var e = recommendationCategories.length - bitVal.length;
        bitVal = "0".repeat(e) + bitVal;

        recommendationCategories.forEach(function (cat, idx) {
          scope.recommendations[cat] = {checked: (bitVal[idx]=="1") ? true : false};
        });

        // add a field for closed too
        scope.recommendations.closed = {checked : (score < 0)};
      });
    },
    template: "<label ng-repeat='(key, recommendation) in recommendations' class='checkbox-inline'> \
                <input type='checkbox' ng-model='recommendation.checked' ng-change='d.recChange()'/>{{key}} \
      -        </label>"
    // template: "<label ng-repeat='(key, recommendation) in d.recommendations' class='checkbox-inline'> \
  }

});

Upvotes: 1

Related Questions