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/

4
  • How so "This is the wrong place.."? Looking at your first html example, your ng-repeat-end looks good to me Commented Nov 2, 2016 at 8:21
  • because it's not setting name & type in div. Commented Nov 2, 2016 at 8:25
  • It should, can you provide a jsfiddle for reproduction? Commented Nov 2, 2016 at 8:26
  • @devqon, you're correct. It's problem with the directive, I guess. Please fix so that I can have the data in accordion. Commented Nov 2, 2016 at 18:06

1 Answer 1

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();
            });
          }
        }
    };
});
Sign up to request clarification or add additional context in comments.

4 Comments

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.
@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
@WilliamB Thankyou very much... you made my day.
I have made a small change to remove the need for an isolate scope to be more flexible & semantic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.