Adarsh Singhal Adarsh Singhal - 29 days ago 7
Javascript Question

How to populate data in JQueryUI accordion using Angular?

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/

Answer

$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();
            });
          }
        }
    };
});
Comments