lanierhall
lanierhall

Reputation: 550

AngularJS and nesting Directives

I want to create a directive that roughly represents a table. Also I want to create a directive that defines the columns in that table. The table directive ng-repeats on the tr and displays the custom columns per row.

I'm pretty new to angular. Any help would be appreciated, here is the code and jsfiddle link.

As you can see from the fiddle this doesn't work yet.

http://jsfiddle.net/P6Nq4/

HTML:

<div ng-app='myApp' ng-controller='myController'>
    Table of People:
    <my-table>
        <my-td my-data-name='Name'></my-td>
        <my-td my-data-name='Description'></my-td>
    </my-table>
    <button>done</button>
</div>

Javascript:

angular.module('myApp', [])
.controller('myController',function($scope){
    $scope.items = [{Name: 'John', Description: 'Awesome'},
                    {Name: 'Pat', Description: 'Ambiguous'}];
})
.directive('myTable', function(){
    return {
        link: function(scope,element,attrs){
        },
        transclude:true,
        template: '<table><tr ng-repeat="item in items" ng-transclude>'
                    +'<td>static column at the end</td></tr></table>'
    };
}).directive('myTd', function(){
    return {
        link: function (scope,element,attrs){
            scope.data = attrs.myDataName;
        },
        template: '<td><input ngModel="eval(\'item.\' + data)" /></td>'
    }});

Upvotes: 1

Views: 127

Answers (1)

Ed_
Ed_

Reputation: 19138

A few things you need to change:

  1. restrict property of the directive definition object. By default, directives are restricted to being html attributes - if you want to use an element (like you have), you need to set restrict to include an E. Link to docs.

  2. You had ngModel="eval(\'item.\' + data)". First issue with this is that in html, angular uses a hyphenated form, and not camelCase, so change ngModel to ng-model. Secondly, the ng-model attribute is automatically evaluated against the scope, so you don't need to use eval. The better approach is to use javascript's bracket notation to access the property. So your ng-model binding becomes:

  3. Finally, if you are re-using a directive, you almost always want to create a new scope, if not an isolate scope, otherwise scopes can interfere with eachother. In your case, the data from the second column overwrites the first column. To fix this, force the creation of a new scope with scope: true

You can see all of the changes in the updated fiddle. I would suggest commenting out the scope line and making sure you understand what happens if you don't have separate scopes, as it's a little bit subtle.

EDIT

Regarding your static column, I think it makes more sense (and it's much simpler) if you include your static column as static html. So instead of putting it in your my-table template, you add it like so:

<my-table>
    <my-td my-data-name='Name'></my-td>
    <my-td my-data-name='Description'></my-td>
    <td>static column</td>
</my-table>

I think this is simpler, and also keeps the html semantic, and representative of what it will be compiled into. This shows it working

Upvotes: 1

Related Questions