1

I am trying to give default values to a directive that has optional attributes. I am giving the default values in scope.init() method shown below. I dont see my default values reflected in the view. If I try to do scope.$apply(), it says it is already digesting :) What am I doing wrong?

angular.module('noi.questionOptions', ['noi.filters'
  //'ui.bootstrap'
]).directive('noiQuestionOptions', ['$filter', '$log', function($filter, $log){
    'use strict';

    var letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
    var romans = ['i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix','x'];
    return {
        restrict: 'EA',
        scope: {
            // have .text attribute and optionall index 
            options: "=noiOptions",
            // default ) 
            separator: '@?noiSeparator',
            // one of alpha, numeric, roman, defaults to numeric
            indexType: '@?noiIndexType',
            // vertical or horizaontal, default horizontal
            orientation: '@?noiOrientation',
            // upper or lower, default upper
            indexCase: '@?noiIndexCase'
        },
        templateUrl: 'noi.questionOptions.html',
        controller: function($scope, $element, $attrs){
            var scope = $scope;            
            scope.isIndexUpper = function(){
                return scope.indexCase == 'lower' ? false : true;
            };
            scope.isHorizontal = function(){
                return scope.orientation == 'vertical' ? false : true;
            };
            scope.init = function(){
                if (!angular.isDefined($scope.indexCase)) {
                    $scope.indexCase = 'upper';               
                };

                if (!angular.isDefined($scope.separator)) {
                    $scope.separator = '.';
                    //scope.separator = ')';
                }

                if (!angular.isArray($scope.options)) {
                    //$log.log('not array');
                    return;
                }
                angular.forEach($scope.options, function(opt, i){
                    if (angular.isDefined(opt.index)) {
                        //return;
                    }                    
                    if ($scope.indexType == 'roman') {
                        opt.index = romans[i];
                    } else if ($scope.indexType == 'alpha') {
                        opt.index = letters[i];
                    } else {
                        opt.index = i;
                    }                    
                });
            };
            scope.init();
            //$log.log("aaa" + scope.options); 

            $log.log(scope.options);
            //scope.$apply();
        },
        link: function(scope, element, attrs) {



        }
    };
}]);

Here is the template

<ul class="list-unstyled " ng-class="{'list-inline':isHorizontal()}">
    <li ng-repeat="opt in options"> {{opt}}
        <span ng-class="{'text-uppercase':isIndexUpper(), 'text-lowercase':!isIndexUpper()}"
              >{{opt.index}} {{ separator}}</span> {{opt.text}}
    </li>
</ul>
{{separator}} - {{indexType}} - {{orientation}} - {{indexCase}} - {{options}}  

these expressions below /ul (except {{options}}) show nothing. {{options}} does not show the .index attribute that i add in forEach loop above. However, I can see it on console that options have .index attributes

--- actual template js file --- (no issue with loading template)

angular.module('erdal').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('noi.questionOptions.html',
    "<ul class=\"list-unstyled\" ng-class=\"{'list-inline':isHorizontal()}\"><li ng-repeat=\"opt in options\">{{opt}} <span ng-class=\"{'text-uppercase':isIndexUpper(), 'text-lowercase':!isIndexUpper()}\">{{opt.index}} {{ separator}}</span> {{opt.text}}</li></ul>{{separator}} - {{indexType}} - {{orientation}} - {{indexCase}} - {{options}}"
  );

}]);

This is the dom that includes the directive

<div data-noi-question-options     
     noi-options="[{text:'ankara'}, {text:'Istanbul'}, {text:'Antalya'}, {text:'Izmir'}]" 
                 ></div>
10
  • Can you update your code so that template includes 'noiQuestionOptions' directive? I suspect you list below UL is not in scope of 'noiQuestionOptions' directive. Commented Jun 27, 2014 at 11:15
  • Which area of the DOM is the directive being applied to? You did not indicate that in your template above. Commented Jun 27, 2014 at 11:17
  • That template is injected, no issue with loading the template. I am putting the javascript version of template as it is added (by grunt) Commented Jun 27, 2014 at 11:17
  • Could you try wrapping your template in a <div></div>? Probably your scope is being isolated to the first DOM element. Commented Jun 27, 2014 at 11:21
  • 1
    Maybe it's not linked on the parent scope due to it not existing at the time of directive linking. So it's created only as a local directive scope but not getting into the attribute? Commented Jun 27, 2014 at 11:40

1 Answer 1

3

I removed the whole scope.init() ... and replaced it with these

scope.$watch('indexType', function(newVal, oldVal, scope){
        //console.log(newVal + ' ' + oldVal);
        if (!angular.isDefined(newVal)){
            scope.indexType = 'upper';
        }
    });
    scope.$watch('separator', function(newVal, oldVal, scope){
        //console.log(newVal + ' ' + oldVal);
        if (!angular.isDefined(newVal)){
            scope.separator = ')';
        }
    });

    scope.$watch('options', function(newVal, oldVal, scope){
        if (!angular.isArray(scope.options)) {
            //$log.log('not array');
            return;
        }
        angular.forEach(scope.options, function(opt, i){
            if (angular.isDefined(opt.index)) {
                return;
            }                    
            if (scope.indexType == 'roman') {
                opt.index = romans[i];
            } else if (scope.indexType == 'alpha') {
                opt.index = letters[i];
            } else {
                opt.index = i;
            }                    
        });
    });

Very good explanation on this page about same problem.. https://groups.google.com/forum/#!msg/angular/lA2oXI8-PdY/N-0dAQ4c1G4J

In short, interpolated attributes are set after the digest cycle and it was overwriting my default value.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.