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?
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.
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/.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With