Maksim Vi.
Maksim Vi.

Reputation: 9235

Access directive element from a controller

On my page I have a table with a custom directive that shows row item's detailed view when a user click on details button :

 <table ng-controller="MyController">
      <tr ng-repeat="item in controller.items">
        <td>{{item.name}}</td>
        <td> <a href="#" ng-click="controller.loadDetails(item.id)">details</a>
        </td>
      </tr>
      <tr ng-details details-colspan="2" ng-model="controller.details"></tr>
 </table>

Directive:

.directive('ngDetails', function() {
    return {
        restrict: 'A',
        require: "^ngModel",
        replace: true,
        template: '<tr class="detailsTemplate {{ngModel.cssClass}}"> \
                      <td colspan="{{detailsColspan}}" ng-bind-html="ngModel.data"></td> \
                    </tr>',
        scope: {
          detailsColspan: '@',
          ngModel: '='
        }
    }
});

Here's a demo.

Right now item details section is showing fine, but it's always at the bottom of the table. I would like to move my directive row element under the corresponding item row, but I'm not sure how to access the directive element inside of my controller.

Upvotes: 0

Views: 90

Answers (2)

Gabriel C. Troia
Gabriel C. Troia

Reputation: 3340

You shouldn't access your element inside your controller. If you have to do that, than there's something wrong with either your design of the application or your understanding of Angular itself.

At a general level, you should start thinking of your directives as the glue between HTML and business logic (your actual JS code inside your services, libraries, models, etc...) and be very strict of keeping it this way.


In this particular case, you could think of the whole ng-repeat as part of one directive, and incorporate the detail row between each item rows.

Even better, if showing the detail row requires some action from the user, like a click on the item row, you can dynamically append/remove the detail row just under the clicked item row. This will be a little bit more optimal since the detail data will be "lazy" compiled.

Upvotes: 0

Zimzat
Zimzat

Reputation: 664

Rather than having the details row appear only once and be moved around, let the ng-repeat include it for every row. You can do this using ng-repeat-start on the first <tr> and ng-repeat-end on the last <tr>. This special syntax allows arbitrary sets of elements to be repeated without being contained in the same repeating element. Then you can include a ng-hide, ng-show, or possibly ng-if on the directive element to only be displayed when the appropriate row has been clicked.

More information about the ng-repeat-start/end syntax can be found here.

Upvotes: 1

Related Questions