0

Goal

Use ng-repeat to create multiple directive instances.

Problem

{{box}} isn't evaluating like I expected in the following code:

<div ng-controller='ClickboxCtrl' ng-repeat="box in lmfOptionset.boxes">
    <div lmf-clickbox='{{box}}' class='lmf-clickbox'></div>
</div>

Relevent Code (I think.)

ClickboxCtrl

.controller('ClickboxCtrl', ['$scope', function($scope){
    $scope.traditional =    {
                            title           : 'Traditional',
                            description     : 'This is the description',
                            background_img  : ''
                            };
    $scope.cross_slot =     {
                            title           : 'Cross Slot',
                            description     : 'This too.',
                            background_img  : ''
                            };
}])

OptionsetCtrl

.controller('OptionsetCtrl', ['$scope', function($scope){
    $scope.traditional_or_cross_slot =  {
                                            boxes : ['traditional', 'cross_slot'],
                                            header: 'Would you prefer?'
                                            };

lmfOptionset

.directive('lmfOptionset', function() {
return {
    scope: {
        'lmfOptionset' : '='
    },
    link: function(scope){

    },
    templateUrl: 'option_set/option_set.html'
}
})

lmfClickbox

.directive('lmfClickbox', ['State', function(State) {
return {
    scope: {
        lmfClickbox: '@'
    },
    link: function($scope, element, attrs){

        element.on('click', function(){
            //When a clickbox is clicked, add it to the state.
            State.add_option(attrs.lmfClickbox);
        });
    },
    templateUrl: 'clickbox/clickbox.html'
};
}])

What I've Tried

I have only been using Angular for about four days now, so I am still learning a lot about it. It has lots of new terms (transclusion, directive, etc.) to get used to. However, my research has led me to many ideas.

Initially, I thought it was a scope problem and that I needed to look at the way I was using isolate scopes ('=', '&', '@') but my combinations of these didn't lead anywhere.

After that, I realized that after refreshing the page, I was getting the following code:

<div lmf-clickbox="{{box}}" class="lmf-clickbox ng-isolate-scope"><div class="lmf-title ng-binding"></div>

So I thought, maybe it's a timing issue? So I tried adding some code to evaluate it using code from this stackoverflow question but I didn't find any luck there.

Finally I've tried adding transclusion: true to my directive because, well, I just needed to try something else.

Any help would be appreciated with this problem!

6
  • lmfOptionset is not declared/set anywhere in the code you provided. Also I would recommend not putting the ng-repeat on the same element as the ng-controller. I don't know for sure if this works or not works, it just feels wrong. Commented May 21, 2015 at 23:25
  • @SamuelNeff Thanks, I added the lmfOptionset directive code. Must have spaced out on that. I'm not sure about the ng-repeat either, I saw it in some code somewhere and went with it, but I think I'll move it to its own div. Looks cleaner anyway. Commented May 21, 2015 at 23:29
  • 1
    I see the edit with the lmfOptionset directive but now i'm even more confused than before. ng-repeat needs to refer to a property set on$scope, so you would need $scope.lmfOptionset= somewhere inside ClickboxCtrl Commented May 21, 2015 at 23:30
  • @SamuelNeff I'm pretty new to Angular, so I'm likely misunderstanding how isolate scopes work. My intention was to be able to say lmf-optionset="traditional_or_cross_slot" and the isolate scope would then be equal to $scope.traditional_or_cross_slot. From what you're saying, this isn't correct? Commented May 21, 2015 at 23:38
  • Well, lmfOptionset is its own directive, so it has its own isolated scope. You're not actually using this directive anywhere, so it's never instantiated and the scope variable is never set anywhere. I'm sorry to say I think you're really far from the solution. Can you take a step back from angular, and describe (irrespective of angular) what you want to do? i.e., what data do you have, and what html do you want to generate, and what parts do you want to abstract out to be reusable? Commented May 21, 2015 at 23:43

1 Answer 1

2

I see a number of issues.

First, as Samuel Neff pointed out, if you want to access lmfOptionset in an ng-repeat, it needs to be a scope variable, not a directive. So you would need something like this:

.controller('ClickboxCtrl', ['$scope', function($scope) {
    $scope.lmfOptionset = { boxes: ['box1', 'box2', 'etc'] };
}])

Alternatively, based on your code you have shown, you could use the following in your HTML (assuming you have instantiated OptionsetCtrl somewhere before this):

<div ng-controller='ClickboxCtrl' ng-repeat="box in traditional_or_cross_slot.boxes">

Second, if you want to access a scope variable in an attribute, you don't need the {{}} braces. Just type the variable name. Angular will interpret the contents of the attribute more-or-less as javascript (as long as you configure the directive correctly), which brings us to the third point...

Third, if you want to pass a scope variable to a directive, use the = sign.

.directive('lmfClickbox', ['State', function(State) {
    return {
        scope: {
            lmfClickbox: '='
        }
    };
}

Fourth, if you want to access that scope variable in the link function, use $scope, not attrs.

.directive('lmfClickbox', ['State', function(State) {
    return {
        scope: {
            lmfClickbox: '='
        },
        link: function($scope, element, attrs){

            element.on('click', function(){
                //When a clickbox is clicked, add it to the state.
                State.add_option($scope.lmfClickbox);
            });
        },
        templateUrl: 'clickbox/clickbox.html'
    };
}])
Sign up to request clarification or add additional context in comments.

1 Comment

Hello AJ, and thanks for your time on this. I think I need to spend some time going over what I'm done, hopefully your answers can help me get back on track.

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.