Click to Edit with AngularJS

Every time I use AngularJS I love it a little more. One of my favourite things about it is how greatly it reduces ceremony and separation. When I'm writing front-end interactions, the last thing I want to be doing is jumping between files and maintaining state in two different places, especially for simple things like "click to edit" behaviour. That's what I'll show you now, done powerfully and directly in Angular:

<div ng-app>
  <div ng-controller="ClickToEditCtrl">
    <div ng-hide="editorEnabled">
      {{title}}
      <a href="#" ng-click="editorEnabled=!editorEnabled">Edit title</a>
    </div>
    <div ng-show="editorEnabled">
      <input ng-model="title">
      <a href="#" ng-click="editorEnabled=!editorEnabled">Done editing?</a>
    </div>
  </div>
</div>

Try this jsfiddle to see it in action. What we're doing is showing some text (an article's title in this example) and then revealing a field to edit it upon clicking an "Edit" link.

To achieve this, we use an Angular editorEnabled model (really just a flag here) that we check with ng-show and ng-hide directives to hide and show the various parts of the interface. We change this value using an ng-click directive on the hide and show links. Angular's data binding keeps everything in sync. As soon as editorEnabled flips between true and false, the interface reacts accordingly. And the best thing? Everything you need can be written directly in the markup.

The only bit of JavaScript is just the most basic setup for the Angular controller, providing an initial value for the title:

function ClickToEditCtrl($scope) {
  $scope.title = "Welcome to this demo!";
}

For some more sophisticated behaviour, you can put some more code in the controller. Let's change the interface to show "save" and "cancel" links when editing the title, and only update the title if the "save" link is pressed:

<div ng-app>
  <div ng-controller="ClickToEditCtrl">
    <div ng-hide="editorEnabled">
      {{title}}
      <a href="#" ng-click="enableEditor()">Edit title</a>
    </div>
    <div ng-show="editorEnabled">
      <input ng-model="editableTitle" ng-show="editorEnabled">
      <a href="#" ng-click="save()">Save</a>
      or
      <a href="#" ng-click="disableEditor()">cancel</a>.
    </div>
  </div>
</div>

See it in this jsfiddle.

The code in the corresponding controller doesn't need to worry about the interface at all, it just operates on the scope, and the interface updates itself accordingly.

function ClickToEditCtrl($scope) {
  $scope.title = "Welcome to this demo!";
  $scope.editorEnabled = false;

  $scope.enableEditor = function() {
    $scope.editorEnabled = true;
    $scope.editableTitle = $scope.title;
  };

  $scope.disableEditor = function() {
    $scope.editorEnabled = false;
  };

  $scope.save = function() {
    $scope.title = $scope.editableTitle;
    $scope.disableEditor();
  };
}

If you wanted to extend this even further and make it a reusable component for different parts of your interface, you would make it a custom directive.

One of the other great things about AngularJS is that you can use it as much or as little as you like. We've used it for the entirety of The Thousands' admin interface, so adding bits of behaviour like this is no problem. But even if you're not already using it, you can just as easily attach an ng-app to any one of your HTML elements and get started.