Search code examples
javascriptangularjshtml-tabledraggableangular-directive

Add "A"-directive to parent node and execute


I'm a newbie in Angular.js and I stuck with one problem.

I want to integrate this plugin (https://github.com/pratyushmittal/angular-dragtable) to be able to drag columns in my table.
The whole table is a directive. Each <th> also renders by a directive.

   <table>
     <thead>
       <tr>
         <th ng-repeat="col in table.columns" my-column></th>
       </tr>
     </thead>
   </table>

According to plugin documentation I need to set draggable directive to table. If I set it manually it doesn't grab my columns properly, because this columns is not rendered at that moment, and this doen't work. In my-column directive I'm waiting for last < th >

.directive('myColumn', ['$timeout', function($timeout) {
  return {
    restrict: 'A',
    templateUrl: 'templates/column.html',
    link: function(scope, element, attrs) {
      if (scope.$last)
        $timeout(function() {
            //scope.$emit('lgColumnsRendered');
            angular.element(element).closest('table').attr('draggable', 'draggable');
        });
    }
  }
}])

And when last th is rendered I going up to my table and set this directive. For sure it is stupid and doesn't work. I also read about $compile but I need add attribute-directive to already existing table in my DOM.

Maybe I go wrong way and don't understand concept of doing this, but you catch the idea? How can I do this?


Solution

  • The problem is that angular-dragtable doesn't expect that table columns will be dynamic. And I think it is logical assumption - in most cases table rows will be dynamic (which is OK for the dragtable), but columns are usually static.

    The solution to this is to add a special event to the dragtable to ask it for re-initialization when your columns are created, here is the modification I made to dragtable (see the link to the full source below):

    project.directive('draggable', function($window, $document) {
        function make_draggable(scope, elem) {
            scope.table = elem[0];
            scope.order = [];
            scope.dragRadius2 = 100;
    
            var headers = [];
            init();
    
            // this is the event we can use to re-initialize dragtable 
            scope.$on('dragtable.reinit', function() {
                init();
            });
    
            function init() {
                headers = scope.table.tHead.rows[0].cells;
                for (var i = 0; i < headers.length; i++) {
                    scope.order.push(i);
                    headers[i].onmousedown = dragStart;
                }
            }
    
            function dragStart($event) {
    

    Now in your code you can do this:

        .directive('myColumn', ['$timeout', '$rootScope', function($timeout, $rootScope) {
          return {
            restrict: 'A',
            templateUrl: 'templates/column.html',
            link: function(scope, element, attrs) {
              if (scope.$last)
                $rootScope.$broadcast('dragtable.reinit');
            }
          }
    

    Here is a full code of the example I tested the issue on.