Ng-show Does Not Work with Custom Directive

advertisements

I've just started using AngularJS and wanted to create a custom template directive for creating "in-place" editable tables. The idea would be to have something like:

    <tr ng-repeat="customer in model.customers">
        <ng-template ng-hide="customer === model.selectedCustomer"> <!-- display template-->
            <td>{{customer.name}}</td>
        </ng-template>
        <ng-template ng-show="customer === model.selectedCustomer"> <!-- edit template -->
            <td><input type="text" ng-model="customer.name"/></td>
        </ng-template>
    </tr>

It could then also be extended to specify a templateUrl e.g. <ng-template template-url="foo.html"></ng-template>

When I apply the ng-show directive to my custom directive it does not work. Here's the code for my directive:

var demo = angular.module("demo", [])
.directive("ng-template", function() {
    return {
        restrict: "E",
        replace: true,
        transclude: true
    }
});

and HTML (http://jsfiddle.net/benfosterdev/ASXyy/):

<div ng-app="demo">
    <table>
        <tr ng-repeat="name in ['jane', 'john', 'frank']">
            <ng-template ng-show="name !== 'frank'">
                <td>{{name}}</td>
            </ng-template>
        </tr>
    </table>
</div>

Furthermore, when I look at the generated HTML my custom directive doesn't even appear in the table:

<div ng-app="demo" class="ng-scope">
    <ng-template ng-show="name !== 'frank'" class="">
    </ng-template>
    <table>
        <tbody>
          ...
        </tbody>
    </table>
</div>

Essentially I'm trying to avoid writing code like this (setting the ng-show directive on every <td> element):

<table>
    <tr ng-repeat="customer in customers">
        <ng-template>
            <td ng-hide="isSelected">{{customer.name}}</td>
            <td ng-hide="isSelected">{{customer.age}}</td>
            <td ng-hide="isSelected"><button ng-click="edit(customer)"</td>
            <td ng-show="isSelected"><input type="text" ng-model="customer.name"/></td>
            <td ng-show="isSelected"><input type="text" ng-model="customer.age"/></td>
            <td ng-show="isSelected"><button ng-click="save(customer)"</td>
        </ng-template>
    </tr>
</table>


A couple of things occur to me when I look at your code.

  1. ng-include offers very similar functionality to your proposal for extending ng-template. If you're going to load a view based on the state of the underlying model then I think this would be the way to go.
  2. If you're not going to be loading the template from a separate view file, why not just use ng-show (or ng-if / ng-switch, which I prefer in most cases) on your td element?

Here is some example code using ng-include:

<table>
    <thead>
        <th>One</th>
        <th>Two</th>
        <th>Three</th>
        <th></th>
    </thead>
    <tbody>
        <tr ng-repeat="item in items" ng-include="getTemplate(item)"></tr>
    </tbody>
</table>

Here is the full JSFiddle: http://jsfiddle.net/qQR6j/2.