1

This is an AngularJS widget which replaces a tag with an editable text field. Clicking the text replaces it with an input field, and hitting enter on the input updates an existing resource.

I am not happy with the code I produced. Are all of these evals and applys really necessary? How can I improve this?

To use

editable-text(model="activeCustomer.phone_number", resource="Customer", field="phone_number")

The Directive Code

.directive("editableText", function($injector){
  return {
    restrict: "E",
    templateUrl: document.views.directivePartials.editableText,
    link: function(scope, elem, attrs){
      $(elem).find(".noEdit").click(function(){
        scope.showEdit = true;
        scope.$apply();
      });

      var ENTER = 13;
      $(elem).find('.edit').keyup(function(event){
        if(event.keyCode == ENTER){
          var resource = $injector.get(attrs.resource);

          var params = {};
          params[attrs.field] = scope.value
          resource.update(params);
          scope.showEdit=false;
        }
      });

      scope.showEdit = false;
      scope.$watch(attrs.model, function(){
        scope.value = scope.$eval(attrs.model);
      });
    },
  };
})

The Template

span.editableTextField
input.edit(type="text", ng-show="showEdit", ng-model="value")
span.noEdit(ng-show="!showEdit") {{value}}

3 Answers 3

2

I would recommend not using jQuery with Angular, especially as you're learning. None of what you're doing requires it.

  1. You can get rid of the first use of click callback by using ngClick in your template:

    <span class="editableTextField" ng-click="showEdit = true">
    
  2. You can get rid of the keyup callback buy using Angular-UI:

    <input class="edit" ... ui-keypress="{enter: 'handleEnter()'}">
    
  3. I'd recommend using a two-way binding so you can write data back to the scope properly.

  4. When you wire up $watch, you get the new value as the first argument. That will save you another $eval.

Here's a fiddle for you... http://jsfiddle.net/maU9t/

Sign up to request clarification or add additional context in comments.

Comments

0

Fiddle! http://jsfiddle.net/pvtpenguin/25cqs/17

Changes:

  1. Create an on-enter directive that the editable-text directive uses in the template. The new on-enter directive can be reused anywhere.

    <input ... on-enter="update()" ... /> 
    
  2. Use the ng-click directive to toggle showEdit state instead of relying on jquery and a function.

    <input ... on-click="showEdit = true" ... /> 
    
  3. Binds value on the directive's isolate scope to the value of the directive's model attribute. This lets us remove the scope.$watch and creates a two-way binding between the local value and activeCustomer.phone_number

    <editable-text model="activeCustomer.phone_number"></editable-text>
    <input ... ng-model="value" />
    <span>{{value}}</span>
    
    ...
    
    scope: { 
        // give `value` and `activeCustomer.phone_number two-way binding
        value: '=model' 
    }
    

These changes completely remove the jQuery dependency. Resulting directive:

myApp.directive("editableText", function($injector){
  return {
    restrict: "E",
    scope: { 
        value: '=model' // Bind `value` to what is declared on the `model` attribute
    },
    templateUrl: "/tpl.html",
    link: function(scope, elem, attrs){
      scope.update = function() {
          var resource = $injector.get(attrs.resource);
          var params = {};
          params[attrs.field] = scope.value;
          resource.update(params);
          scope.showEdit=false;
      };
      scope.showEdit = false;
    }
  };
});

Comments

0

Here is one version of inline editor. http://jsfiddle.net/pUMer/

Key features:

  • Configure the initial mode of the inline editor
  • Seperate scope for each inline editor, so that it wont interfere with the parent scope
  • View the model of all the inline editors

If you want only on inline editor, pls. reduce the array element to size of one.

HTML:

<inline-editor inline-editor-mdl="inlineEditor"></inline-editor>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.