Frage

I have a list of items, and the current (selected) one is shown in more detail on a different part of the screen. In the more detailed part, you can edit parts of the selected item using contenteditable.

Now when the user adds an item to the list, I'd like to trigger the focus event on an element so the user can edit e.g. the title right away.

A very simplified version of what I have is this:

function ListCtrl($scope) {
  $scope.list = [
    "one",
    "two"
  ];
  $scope.add = function() {
    $scope.list.push("new item");
    jQuery("li:last").trigger("focus");
  };
}

Using jQuery works in this example. Using angular.element fails with:

Looking up elements via selectors is not supported by jqLite!

At this point, I've familiarized myself with Angular enough to consider this usage of jQuery a code smell. It was written elsewhere:

when solutioning, first "think in AngularJS"; if you can't think of a solution, ask the community; if after all of that there is no easy solution, then feel free to reach for the jQuery.

So here I am, asking the community: Is there a better way to let users edit an element right away without triggering focus as if the user clicked on a contenteditable element?

War es hilfreich?

Lösung

To my knowledge, there is no better/shorter way to let users edit an element right away without triggering focus, so I would work on improving what you have to meet Angular's application design principles.

According to the "Angular Way", DOM manipulation must happen within a directive, business logic should be contained within controllers.

The solution is to "get the directive and controller to talk". Your example should be:

The controller:

function ListCtrl($scope) {
     var count = 1;
     $scope.list = [
         "one",
         "two"
     ];

     $scope.add = function() {
         $scope.list.push("new item " + count);
         $scope.$broadcast("newItemAdded");
         count++;
     };
  }

The directive:

  function ListDirective($timeout) {
      return {
           link: function(scope, element, attr) {
               scope.$on("newItemAdded", function() {
                   $timeout(function() {
                       var elements = element.find("li");
                       elements[elements.length - 1].focus();
                   });
               });
           }
      };
  }

JsFiddle: http://jsfiddle.net/kxUR9/8/

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top