Question

I'm pretty new to AngularJS and I'm trying to migrate the following piece of jQuery code to AngularJS.

$('#someid').on('click', 'someclass', function() {
  $(this).next().slideToggle('fast');
});

My HTML that I began converting to AngularJS looks something like

<ul id='someid'>
  <li ng-repeat="...">
    <ul>
      <li class="someclass">{{ ... }}</li>
      <li style="display:none">the part that will be slideToggle'd</li> 
    </ul>
  </li>
</ul>

Elements are added to the ng-repeat list dynamically when the user interacts with the app, hence the jQuery.on(). I'm OK using an unstable version of AngularJS if it helps.

How should I rewrite the jQuery fragment in AngularJS? I've tried a few things now including adding a new directive, playing with ng-animate, etc. But when I added jQuery code into my ng controller, that started to look ugly -- I'd like to avoid anything hybrid.

Thanks a lot!

Was it helpful?

Solution

One way to do that would be by writing a directive but ideally you should use ng-animate along with ng-show:

Firstly, toggle a property inside ng-click that you would keep on the "li" with the class "someclass":

<li class="someclass" ng-click="item.isVisible = !item.isVisible;">{{item.name}}</li>

and then use ng-show along with ng-animate on the part that would be slideToggle'd.

<li ng-show="item.show" ng-animate="'animate'" style="display:none">the part that will be slideToggle'd</li>

You would also need to write the animation css class for ng-animate to work.

Hope this helps.

OTHER TIPS

Angularjs best practices suggest you don't do DOM manipulation inside your controller. The way of doing this would be with a directive. You won't even need to include jQuery itself as far as I see. The angular offers a jQuery subset (see http://docs.angularjs.org/api/angular.element for available functionality), which they call jQlite.

Roughly you should do something like:

var app = angular.module('myApp', []);

app.directive('clickunfold', function () {
    return {
        restrict: 'C',
        link: function (scope, element, attr) {
            element.bind('click', function () {
                element.next().removeClass('noShow').addClass('show');
            }
        }
    }
});

And your HTML will be:

<ul>
    <li class="clickunfold">{{ ... }}</li>
    <li class="noShow">the part that will be slideToggle'd</li> 
</ul>

And your CSS will be:

.noShow { display: none }
.show { /* Css Transitions to make the unfold effect or simply a display: block */ }

The above directive is defined as a class (restrict: 'C') and the element that has this directive as a class, when clicked, it causes a class remove && class add on the next() sibling of this element.

Hope that helps.

The angular way to do this can be:

<li class="someclass" ng-click="slider_open = !slider_open">..</>
<li ng-show="slider_open">...</li>

If you want to animate it, use ng-class instead of ng-show and use css transitions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top