Can I avoid the object variable name in ng-repeat loop?

angularjs, angularjs-ng-repeat, angularjs-scope, javascript

Solution

I've decided to combine the informative answers of Mathew Berg and ganaraj with my newfound knowledge to create a helpful answer to this.

The short answer is You really don't want to do that.

The longer answer is this:

When using `ng-repeat="block in blocks`" , a new scope is created for each block element, and the properties of every block object are create in `scope.block` of each block. This is a good thing, because this means all properties can be accessed by reference, updated or $watched.

If `ng-repeat` wouldn't have done that, and all properties would just be slapped unto the block's scope, then all primitives in `block` (strings, ints, etc) would just be copied from the block object to the block scope object. A change in one will not reflect on the other, and that's bad. More info on that here.

Ok so now that we've decided that's a good thing rather than a bad thing, how do we overcome the semantic issue? I've decided to use the `friendData` object container as the object on the scope of my directive, and so the directive expects the `friend-data` attribute to hold the relevant properties

angular.module('myApp',[])
.directive("lookActions", function(){
    return {              
        restrict: 'E',        
        template: "<input value='Kill -{{ friendData.name }}-' type='button'>",
        scope : {
            friendData : '='            
        }
    }
});

This way I can assign this object regardless of which context I'm calling my directive template.

Given these controller contexts:

function gridCtrl($scope) {    
    $scope.blocks = [{ type: "cat", name: "mitzi"},{ type: "friend", name: "dave"},{ type: "guitar", name: "parker"}];
}


function friendCtrl($scope) {    
    $scope.data={
        name: "dave"
    }
}

How to call the directive -

Within an `ng-repeat`:

    <div class="block" ng-repeat="block in blocks" >            
        <look-actions friend-data="block" />
    </div>

Or in a difference context:

    <div ng-controller="friendCtrl">  
         <look-actions friend-data="data" />
     </div>

Here's the solution Fiddle

Thanks for all the help!

Problem

When defining an ng-repeat directive to iterate over an array, the syntax specifies `ng-repeat="friend in friends"`, and then within the template you use the interoplation operator like so `{{friend.name}}`. Is it possible to have the properties assigned to the current item scope, rather than a variable in it? So I could call just `{{name}}` instead of `{{friend.name}}`? The reason being is that my directive is being used in the scope of two different templates - for example I might have a directive `"userActions"` that is used in both a repeater, and also inside an unrelated template where `{{friend.name}}` doesn't make sense. I would like to avoid artificially manufacturing the `friend` object where it doesn't have a semantic meaning. My use case is something like this: I have a grid that renders blocks of various types. Some psuedo code: ``` <div ng-repeat="block in blocks"> < cat block /> < friend block > <userActions directive /> </ friend block > < guitar block /> .... more blocks </div> ``` I also have a friend page, that contains the exact same user actions: ``` ..fragment of friend page.. <element ng-control="friend"> <userActions directive /> </element> ``` Now, if I want to user a property of the block inside the repeater, the syntax is `{{block.name}}`. So the template for `userActions` contains this. However, once I use this template in the friend page, I must create `{{block.name}}` inside the scope of the friend controller. This does not make sense though, because the block only exists in the context of the block grid. I shouldn't have to create this `block`. What I want to be able to do, is just to call `{{name}}` from within the `userActions` directive template, since both the block scope and the controller contain it. I don't want to create a `block` object, then artificially set `block.name` in each scope where I want to use the `userActions` directive. Here's a jsFiddle to illustrate the cause

Original source