Blake Blackwell
Blake Blackwell

Reputation: 7795

How do I use a directive to toggle a slide animation on an element from my controller?

I am confused on the following scenario. Let's say I have a table with rows. When a user clicks a button in the table I want a user form to slide down with jQuery and display the form with the selected row values. Here is what I am currently doing that doesn't quite make sense:

View

<tr ng-click="setItemToEdit(item)" slide-down-form>

...

<form>
   <input type="test" ng-model={{itemToEdit.Property1}} >
   <button ng-click=saveEditedItem(item)" slide-up-form>
<form>

Control

$scope.itemToEdit = {};

$scope.setItemToEdit = function(item) {
    $scope.itemToEdit = item;
});

$scope.saveEditedItem = function(item) {
   myService.add(item);
   $scope.itemToEdit = {};
}

Directive - Slide-Up / Slide-Down

var linker = function(scope, element, attrs) {
    $(form).slideUp(); //or slide down           
}

It seems the my directive and my control logic are too disconnected. For example, what happens if there is a save error? The form is already hidden because the slideUp event is complete. I'd most likely want to prevent the slideUp operation in that case.

I've only used AngularJS for about a week so I'm sure there is something I'm missing.

Upvotes: 5

Views: 4221

Answers (1)

Ben Lesh
Ben Lesh

Reputation: 108491

Sure, it's a common problem... here's one way to solve this: Basically use a boolean with a $watch in a directive to trigger the toggling of your form. Outside of that you'd just set a variable on your form to the object you want to edit.

Here's the general idea in some psuedo-code:

//create a directive to toggle an element with a slide effect.
app.directive('showSlide', function() {
   return {
     //restrict it's use to attribute only.
     restrict: 'A',

     //set up the directive.
     link: function(scope, elem, attr) {

        //get the field to watch from the directive attribute.
        var watchField = attr.showSlide;

        //set up the watch to toggle the element.
        scope.$watch(attr.showSlide, function(v) {
           if(v && !elem.is(':visible')) {
              elem.slideDown();
           }else {
              elem.slideUp();
           }
        });
     }
   }
});

app.controller('MainCtrl', function($scope) {
   $scope.showForm = false;
   $scope.itemToEdit = null;

   $scope.editItem = function(item) {
       $scope.itemToEdit = item;
       $scope.showForm = true;
   };
});

markup

<form show-slide="showForm" name="myForm" ng-submit="saveItem()">
    <input type="text" ng-model="itemToEdit.name" />
    <input type="submit"/>
</form>
<ul>
   <li ng-repeat="item in items">
         {{item.name}}
        <a ng-click="editItem(item)">edit</a>
   </li>
</ul>

Upvotes: 6

Related Questions