I pull some objects from my api using ngResource an then I show them in a table. Thats ok.. the problem bee when I try to make 'tags' attribute editable using angular-xeditable but are treated as string and there isn't something like "ngList" on angular-xeditable. The only solution I can think of is serialize that "tags" attribute to "tagsString" on my service and unserialize it once $save() was called.. there is a more elegant solution?
Object:
{
"id": "yP8",
"uploadDate": "2012-10-03T12:52:59-0300",
"statusChangeDate": "2012-10-03T12:52:59-0300",
"status": 0,
"type": 1,
"mimeType": "JPEG",
"title": "title-36868",
"tags": [
'some-tag',
'fancy-tag'
],
"language": "en",
"interactions": {
"likes": 12371,
"dislikes": 15,
"ments": 81
},
"published": true
}
Controller:
app.controller( 'ContentsCtrl', function CommentsCtrl( $scope, Contents ) {
$scope.contents = Contents.query();
});
Template:
<tr ng:repeat="content in contents.content">
<td>{{content.id}}</td>
<td ng:click="content.images.showFull=!content.images.showFull">
<img src="{{content.images.thumbnail.url}}" ng:show="!content.images.showFull">
<img src="{{content.images.medium.url}}" ng:show="content.images.showFull">
</td>
<td>{{content.status}}</td>
<td>
<span editable-text="content.title" e-required>{{content.title}}</span>
</td>
<td>
<span editable-text="content.tags">{{content.tags}}</span>
</td>
<td>{{content.language}}</td>
</tr>
EDIT:
Demo (by Sebastian Gärtner):
I pull some objects from my api using ngResource an then I show them in a table. Thats ok.. the problem bee when I try to make 'tags' attribute editable using angular-xeditable but are treated as string and there isn't something like "ngList" on angular-xeditable. The only solution I can think of is serialize that "tags" attribute to "tagsString" on my service and unserialize it once $save() was called.. there is a more elegant solution?
Object:
{
"id": "yP8",
"uploadDate": "2012-10-03T12:52:59-0300",
"statusChangeDate": "2012-10-03T12:52:59-0300",
"status": 0,
"type": 1,
"mimeType": "JPEG",
"title": "title-36868",
"tags": [
'some-tag',
'fancy-tag'
],
"language": "en",
"interactions": {
"likes": 12371,
"dislikes": 15,
"ments": 81
},
"published": true
}
Controller:
app.controller( 'ContentsCtrl', function CommentsCtrl( $scope, Contents ) {
$scope.contents = Contents.query();
});
Template:
<tr ng:repeat="content in contents.content">
<td>{{content.id}}</td>
<td ng:click="content.images.showFull=!content.images.showFull">
<img src="{{content.images.thumbnail.url}}" ng:show="!content.images.showFull">
<img src="{{content.images.medium.url}}" ng:show="content.images.showFull">
</td>
<td>{{content.status}}</td>
<td>
<span editable-text="content.title" e-required>{{content.title}}</span>
</td>
<td>
<span editable-text="content.tags">{{content.tags}}</span>
</td>
<td>{{content.language}}</td>
</tr>
EDIT:
Demo (by Sebastian Gärtner): http://plnkr.co/edit/ttPNgHXUZKmaJZ9IuB2N?p=preview
Share Improve this question edited Jan 24, 2017 at 15:51 Mosh Feu 29.4k18 gold badges93 silver badges141 bronze badges asked Dec 4, 2013 at 19:19 neikerneiker 8,9915 gold badges32 silver badges32 bronze badges 3- 1 Can you wire up an example using jsfiddle? – Mathew Berg Commented Dec 9, 2013 at 11:42
- Contents.query() looks like a promise. If it is, this will break in newer versions of Angular as it does not unwrap promises automatically anymore FYI. – Kenneth Lynne Commented Dec 9, 2013 at 22:00
- You can submit an enhancement to angular-xeditable or even better a pull request ;) – Bastien Caudan Commented Dec 10, 2013 at 18:40
3 Answers
Reset to default 2What about solving it with another directive. Not with xeditable.
Like: http://decipherinc.github.io/angular-tags/
You do want to have the tags editable? What input mechanism do you want to have?
What about another ng-repeat for the tags to make them each an single input field and maybe an mechanism for add and delete tags.
You can do something like the following:
<div ng-repeat="tag in content.tags track by $index">
<span editable-text="content.tags[$index]">{{tag}}</span>
</div>
The trick is to wire up the correct model-value with the editable-text directive (using the $index iterator in this case).
The Editable Table example on the angular x-editable page has something that almost acplishes this. By wrapping each string in you list in an object, you can apply arbitrary properties to it - in this case, temporary values which you can key save/delete functionality off of in onCancel and onBeforeSave handlers.
Object:
{
tags: [
{name: 'some-tag'},
{name: 'fancy-tag'}
]
};
HTML:
<form editable-form name="tagForm" onBeforeSave="cleanBeforeSave()" onCancel="cleanOnCancel()">
<ul>
<li ng-repeat="tag in contents.tags | filter:filterDeleted">
<span editable-text="tag.name" e-name="name"> {{tag.name}} </span>
<button ng-click="deleteTag($index)" ng-show="tagForm.$visible">x</button>
</li>
</ul>
<span ng-show="tagForm.$visible">
<button type="button" ng-click="addTag()">New</button>
<button type="submit">Save</button>
<button type="button" ng-click="tagForm.$cancel()">Cancel</button>
</span>
<span ng-hide="tagForm.$visible">
<button type="button" ng-click="tagForm.$show()">Edit</button>
</span>
</form>
Controller:
app.controller( 'TagCtrl', function TagCtrl( $scope, Contents ) {
$scope.contents = Contents.query();
$scope.filterDeleted = function(obj) {
return obj.isDeleted !== true;
};
$scope.addTag = function() {
$scope.contents.tags.push({name:"", isNew:true});
};
$scope.removeTag = function(index) {
$scope.contents.tags[index].isDeleted = true;
};
$scope.cleanBeforeSave = function() {
// go backwards, so deleting doesn't mess up i's count
for (var i = $scope.contents.tags.length; i--;) {
var tag = $scope.contents.tags[i];
if (tag.isDeleted) {
$scope.contents.tags.splice(i, 1);
}
if (tag.isNew) {
delete tag.isNew;
}
}
};
$scope.cleanOnCancel = function() {
// go backwards, so deleting doesn't mess up i's count
for (var i = $scope.contents.tags.length; i--;) {
var tag = $scope.contents.tags[i];
if (tag.isDeleted) {
delete tag.isDeleted;
}
if (tag.isNew) {
$scope.contents.tags.splice(i,1);
}
}
};
});