0

In the following code sample, accordion directive ensures that angular finishes first and then allow the JQueryUI to render the accordion with provided values in tags. But it's not working as expected. I'm following this link.

<div accordion>
  <h3 ng-repeat-start="user in users" >
    <a href="#">{{user.name}}</a>
  </h3>
  <div ng-repeat-end>
      Name: {{user.name}}<br>
      Type: {{user.type}}<br>
  </div>
</div>


The following is the accordion directive implementation`

app.directive('accordion', function ($timeout) {
  return {
    restrict: 'A',
      link: function ($scope, $element, attrs) {
        $(document).ready(function () {
          $scope.$watch('users', function () {
            if ($scope.users != null) {
              $timeout(function(){
                $element.accordion();
              });
            }
          });
        });
      }
  };
});

JS Fiddle https://jsfiddle.net/7028yLdh/1/

Community
  • 1
  • 1
Adarsh Singhal
  • 362
  • 1
  • 3
  • 12

1 Answers1

1

$scope.$watch('users', /* ... */) won't get called unless the Array changes to a different object. So your elem.accordion() is not running after the DOM is compiled. Instead you can watch users.length to detect new elements in the Array.

Also, $(document).ready is not needed inside Angular directive link functions.

One more pitfall is that you must call elem.accordion('destroy') and re-build the accordion on subsequent changes to the array. My solution will only build the accordion once by default, unless you supply a watch="someVariable" to watch for changes.

Fiddle: https://jsfiddle.net/hk6wro4y/

HTML:

<!-- Will not update -->
<div accordion><!-- content --></div>

<!-- Will update -->
<div accordion watch="users.length"><!-- content --></div>

JS:

app.directive('accordion', function ($timeout) {
    return {
        link: function (scope, elem, attrs) {          
          if (attrs.watch) {
            scope.$watch(attrs.watch, function () {
              if (elem.hasClass('ui-accordion')) { 
                elem.accordion('destroy'); 
              }
              elem.accordion();
            });
          }
          else {
            $timeout(function () {
              elem.accordion();
            });
          }
        }
    };
});
William B
  • 1,411
  • 8
  • 10
  • Thanks William B. Can you plz fix the js fiddle you provided. On clicking new user, it's not added to Accordion. I'll need that. – Adarsh Singhal Nov 03 '16 at 05:49
  • @AdarshSinghal I mentioned in my comment that by default it will not update. You need to supply the `watch="users"` if you want it to explicitly watch and update on change of the list – William B Nov 03 '16 at 16:14
  • @WilliamB Thankyou very much... you made my day. – Adarsh Singhal Nov 03 '16 at 16:27
  • I have made a small change to remove the need for an isolate scope to be more flexible & semantic. – William B Nov 04 '16 at 18:53