How to trigger a directive when updating a model in AngularJS?

All we need is an easy explanation of the problem, so here it is.

I found a good solution for inline editing content in angular js that is created by running ng-repeat on a model: https://stackoverflow.com/a/16739227/2228613

To expand on that solution I added a button to the page that has a ng-click directive as so:

<button ng-click="addCategory()" class="btn btn-large btn-primary" type="button">
<i class="icon-white icon-plus"></i> Add Category
</button>

The addCategory function is defined in my controller:

$scope.addCategory = function(){
    var newCategory = {id:0, name:"Category Name"};
    $scope.categories.unshift(newCategory);
}

The goal here is to allow the user to add a new record and automatically trigger the inline-edit directive once the view is updated with the new row. How can I trigger the inline-edit directive in such a manner?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

One technique that i’ve used is to have a boolean change values and have a $watch on it inside the directive that needs to be triggered.

myApp.directive('myDirective', function () {
    return function (scope, element, attr) {
            scope.$watch('someValue', function (val) {
                if (val)
                    // allow edit
                else
                    // hide edit
            });
     }
});

Then in your controller you’d set $scope.someValue = true; in your ng-click for the button.

plunker: http://plnkr.co/edit/aK0HDY?p=preview


UPDATE

I’ve gone a bit further with the above answer. I’ve made something more along the lines with what you’re after.

Here’s the plunk for it: http://plnkr.co/edit/y7iZpb?p=preview

This is the new directive:

  .directive('editCar', function ($compile) {
      return {
        restrict: 'E',
        link: function (scope, element, attr) {
          var template = '<span class="car-edit">'+
          '<input type="text" ng-model="car.name" />' +
          '<button ng-click="someValue = false" class="btn btn-primary">Save</button></span>';
          scope.$watch('someValue', function (val) {
              if (val) {
                  $(element).html(template).show();
                  $compile($('.car-edit'))(scope);
              }
              else
                  $(element).hide();
          });
        }
      }
  })

It replaces the <edit-car></edit-car> element with the above template. The save button adds the values to an array called editedCars. I’ve left in some dummy code for submitting the entire thing using $http.post()

Method 2

I have one possible solution for you: http://plnkr.co/edit/uzuKki (I worked on the original plunk as you mentioned.)

My idea is

  1. Add “editMode” property to TODO model
  2. Instead of passing in just todo.title to directive’s scope, passing in the whole TODO object, which is inline-edit="todo" in index.html
  3. In inline-edit.html, change every editMode to model.editMode (and every model to model.title to display title correctly)
  4. In your controller’s add method, create new object with editMode = true, e.g.

    var newTodo = {id:0, name:"TODO Name", editMode: true};
    $scope.todos.unshift(newTodo);
    

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply