Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular.js inline-editing

I'm trying to find the best approach of inline-editing with angularjs. In my case it's kind of a data-grid with an "edit" button. So it's inside ng-repeat.

What I've seen people do is have both actual data and editing inputs in the same row, with editing inputs being hidden and shown on click of the edit button.

But it doesn't seem right. It's a lot of useless DOM in my opinion.

So I thought I would be better to do something like this. You click on the edit button, which is gonna have a directive, which would 1) hide the <td> with data 2) find buttons' parent, which should be the <tr>, and inject a template with into it 3) on save remove those editing <td>s and show the data <td>s again.

So I started with making the directive, inside I had element.click() function, which

// found the parent
var parent = element.closest('tr');
// found all the data tds
var tds = parent.find('td');
// hidden them  
tds.hide();

Now here's the problem, next I thought about doing something like this

// append input with editing tds into parent
parent.append('<td><input type="text" ng-model="entry.name" /> {{entry.name}} </td>');

But then it wouldn't bind or even parse the {{}} would it? What method would I have to use instead of jquery's append?

Docu on directives says this

template element - The element where the directive has been declared. It is safe to do template transformation on the element and child elements only.

So I can't use template transoformation on the element.parent()

Would it help if I made the directive on the <tr> and even if I did, I would then transform my whole <tr>, which means I'd lost the original template and I'd have to have another directive or something that would transform it back to the original state.. wouldn't I?

Edit

Since this questions seems pretty popular.. firstly my original worry of rendering additional element with each ng-repeat iteration is unfounded because 1) you can use ng-if, which means it's not gonna be rendered at all until the condition is true 2) you could append a template just as I intended, then just use $compile and it's gonna work just fine, it's definitely not gonna be "expensive", since you are doing it just for the one element. There are many many ways to approach this, but ng-if is the simpliest, if supermasher's way doesn't suit you, that is.

like image 262
fxck Avatar asked Apr 03 '13 10:04

fxck


2 Answers

Injecting a fresh template is quite an expensive way of doing things, especially if you have lots on instances of your inline editor.

There are lots of ways to do it, but the cleanest (and easiest) is to use the same element to edit and display your data, and simply toggle it's CSS using a directive to change how it appears in both states, like so:

myApp.directive('inlineEdit', function () {

return function (scope, element, attrs) {
    element.bind('click', function () {

        if (element.hasClass('inactive')) {
            element.removeClass('inactive');
        } else {
            element.addClass('inactive');
            $(element).blur()
        }
    });
};

});

Check out this fiddle for a full working example: http://jsfiddle.net/3EaY8/.

like image 125
supermasher Avatar answered Nov 15 '22 20:11

supermasher


Hi there I know that there is an accepted answer already but I have stumble upon this

http://vitalets.github.io/angular-xeditable/

recently, and I believe it is a very decent project that deals with editable controls in general.

Hope it helps some one.

like image 31
Byron Avatar answered Nov 15 '22 21:11

Byron