I have been googling and none of the solutions have worked for me. I have an AngularJS page that simply has a small set of data with no paganation or anything and I just want to be able to delete an entry and have the table update. However my call to $scope.tableParams.reload() just doesn't do anything.
Here is my controller:
app.controller('viewVersion', ['$scope', '$filter', '$RestService', 'NgTableParams', '$cookies', '$routeParams', '$q', 'Flash', '$location', function($scope, $RestService, NgTableParams, $cookies, $routeParams, $q, Flash, $location) {
$scope.version = {id:null, version:null, comment:null, states:[]};
$scope.permissions=$cookies.get('permissions');
var promise = $RestService.StateList(); //Get the list of states to use to map state ids to their names (BOI, REQ, etc).
promise.success(function(data) {
$scope.stateList = data;
});
promise.then(function(){
var inprom = $RestService.GetVer($routeParams.verid); //Get the version from the API given the version id.
inprom.success(function(data){
data.forEach(function(ver) {
$scope.version['id'] = ver.id;
$scope.version['version'] =ver.version;
$scope.version['platform'] =ver.platform;
$scope.version['comment'] = ver.comment;
if (ver.state!=null) {
var state_info = _.where($scope.stateList, {state_id:ver.state})[0];
$scope.version.states.push({state:state_info.state_name, state_id:ver.state, launch:ver.launch});
}
});
})
inprom.error(function(errorData) {
$cookies.set('flash_message', "Error getting version with ID "+$routeParams.verid);
});
inprom.then(function() {
$scope.tableParams = new NgTableParams({
sorting: { launch: "desc" }
}, {
counts:[],
total: $scope.version.states.length,
filterDelay: 0,
dataset: angular.copy($scope.version.states)
});
});
});
$scope.delete = function(row) {
_.remove($scope.tableParams.settings().dataset, function(item) {
return row.state_id === item.state_id;
});
$scope.tableParams.total($scope.tableParams.settings().dataset.length);
$scope.tableParams.reload();
};
}]);
And the matching html:
<table ng-table="tableParams" class="table table-bordered table-hover table-condensed editable-table" ng-form="tableForm">
<tr ng-repeat="state in version.states" ng-form="stateForm">
<td title="'State'" sortable="'state'">{{state.state}}</td>
<td title="'Launch Date'" sortable="'launch'" ng-switch="state.isEditing" ng-form="launch">
<span ng-switch-default class="editable-text">{{state.launch | date:'medium':'UTC'}}</span>
<div class="controls" ng-class="stateForm.$invalid ? 'has-error' : ''" ng-switch-when="true">
<input type="text" name="name" ng-model="state.launch" class="editable-input form-control input-sm" required />
<p ng-show="stateForm.$invalid && !stateForm.$pristine" class="help-block">Enter a valid date and time.</p>
</div>
</td>
<td>
<button class="btn btn-primary btn-sm" ng-show="permissions.indexOf('admin') > -1" ng-click="save(state, stateForm)" ng-if="state.isEditing" ng-disabled="stateForm.$pristine || stateForm.$invalid"><span class="glyphicon glyphicon-ok"></span></button>
<button class="btn btn-default btn-sm" ng-show="permissions.indexOf('admin') > -1" ng-click="cancel(state, stateForm)" ng-if="state.isEditing"><span class="glyphicon glyphicon-remove"></span></button>
<button class="btn btn-default btn-sm" ng-show="permissions.indexOf('admin') > -1" ng-click="state.isEditing = true" ng-if="!state.isEditing"><span class="glyphicon glyphicon-pencil"></span></button>
<button class="btn btn-danger btn-sm" ng-show="permissions.indexOf('admin') > -1" ng-click="delete(state)" ng-if="!state.isEditing"><span class="glyphicon glyphicon-trash"></span></button>
</td>
</tr>
</table>
Any help would be very appreciated. Thanks!
Your rows are coming directly from your data,
<tr ng-repeat="state in version.states">
...but your delete function is removing rows from ng-table's copy of the data:
$scope.delete = function(row) {
_.remove($scope.tableParams.settings().dataset, function(item) {
return row.state_id === item.state_id;
});
$scope.tableParams.total($scope.tableParams.settings().dataset.length);
$scope.tableParams.reload();
};
You want to pull your rows from ng-table's copy instead:
<tr ng-repeat="state in $data">
Here is a simplified demo: http://plnkr.co/edit/kuAdN3ToKDZtp338E6Hp?p=preview
Related
I would like to know, how to pass params to function dynamically inside AngularJS template.
I have many rows in table and each row has a button Add deposit. I would like to pass row number to this button's ng-click function.
Here is snippet of my template:
<div id="documentsTable" class="table-responsive">
<table class="table">
<thead>
...
</thead>
<tbody ng-repeat="document in data">
<tr>
...
<td>
...
<button ng-show="document.depositCheckbox" ng-click="addDeposit({id: document.number})" id="addDepositBtn"
type="submit" class="btn btn-primary">Add deposit</button>
</td>
</tr>
</tbody>
</table>
Directive:
.directive('documentDirective', ['$compile', '$templateCache', function () {
return {
templateUrl: 'templates/documentTemplate.html',
scope: {
data: '=',
addDeposit: '&'
},
restrict: 'E'
}}]);
And in my HTML file I have:
<document-directive data="documents" add-deposit="addDeposit()"></document-directive>
Function addDeposit in my controller:
$scope.addDeposit = function(documentId) {
for(var i=0; i<$scope.documents.length; i++) {
if($scope.documents[i].number == documentId) {
var depositLength = $scope.documents[i].deposit.length;
var deposit = {'number': depositLength, 'value': 0, 'paymentDate': new Date(), 'firstRow': false};
$scope.documents[i].deposit.push(deposit);
break;
}
}
}
Thanks!
Ok so as I understand it, you are trying to get which row that you are getting the post request from?
I think you should be able to do that with the $index property of the ng-changed.
So something like:
<button ng-show="document.depositCheckbox" ng-click="addDeposit({id: document.number, rowNumber: $index})" id="addDepositBtn"
type="submit" class="btn btn-primary">Add deposit</button>
EDIT:
Try this instead then:
<button ng-show="document.depositCheckbox" ng-click="addDeposit()(document.number)" id="addDepositBtn" type="submit" class="btn btn-primary"> Add deposit</button>
And where you pass the function in:
<document-directive data="documents" add-deposit="addDeposit"></document-directive>
Passing in method as parameter:
https://stackoverflow.com/a/26244600/1958344
I am using code form a tutorial and modifying it a bit. I have run into an issue with the edit feature. I keep getting a "ReferenceError: $modal is not defined" here is my code.
postCtrl:
app.filter('startFrom', function() {
return function(input, start) {
if(input) {
start = +start; //parse to int
return input.slice(start);
}
return [];
}
});
app.filter('dateToISO', function() {
return function(input) {
input = new Date(input).toISOString();
return input;
};
});
app.controller('postsCtrl', function ($scope, $log, $http, $timeout, Data) {
Data.get('posts').then(function(data){
$scope.posts = data.data;
$scope.currentPage = 1; //current page
$scope.filteredItems = $scope.posts.length; //Initially for no filter
$scope.totalItems = $scope.posts.length;
$scope.list_pages = [
{
id: '5',
name: '5'
}, {
id: '10',
name: '10'
}, {
id: '20',
name: '20'
}, {
id: '50',
name: '50'
}, {
id: '100',
name: '100'
}
];
$scope.maxSize = 5;
});
$scope.setPage = function(pageNo) {
$scope.currentPage = pageNo;
};
$scope.filter = function() {
$timeout(function() {
$scope.filteredItems = $scope.filtered.length;
}, 10);
};
$scope.sort_by = function(predicate) {
$scope.predicate = predicate;
$scope.reverse = !$scope.reverse;
};
$scope.changePostStatus = function(post){
post.approved = (post.approved=="1" ? "0" : "1");
Data.put("posts/"+post.id,{approved:post.approved});
};
$scope.changePostAnnounce = function(post){
post.announce = (post.announce=="1" ? "0" : "1");
Data.put("posts/"+post.id,{announce:post.announce});
};
$scope.trashPost = function(post){
//$log.log(post);
if(confirm("Are you sure to remove the post")){
Data.delete("posts/"+post.id).then(function(result){
$scope.posts = _.without($scope.posts, _.findWhere($scope.posts, {id:post.id}));
});
}
};
$scope.open = function (p,size) {
var modalInstance = $modal.open({
templateUrl: 'views/postsEdit.html',
controller: 'postsEditCtrl',
size: size,
resolve: {
item: function () {
return p;
}
}
});
modalInstance.result.then(function(selectedObject) {
if(selectedObject.save == "insert"){
$scope.posts.push(selectedObject);
$scope.posts = $filter('orderBy')($scope.posts, 'id', 'reverse');
}else if(selectedObject.save == "update"){
p.description = selectedObject.description;
p.price = selectedObject.price;
p.stock = selectedObject.stock;
p.packing = selectedObject.packing;
}
});
};
});
app.controller('postsEditCtrl', function ($scope, $modalInstance, item, Data) {
$scope.post = angular.copy(item);
$scope.cancel = function () {
$modalInstance.dismiss('Close');
};
$scope.title = (item.id > 0) ? 'Edit Post' : 'Add Post';
$scope.buttonText = (item.id > 0) ? 'Update Post' : 'Add New Post';
var original = item;
$scope.isClean = function() {
return angular.equals(original, $scope.post);
}
$scope.saveProduct = function (post) {
post.uid = $scope.uid;
if(post.id > 0){
Data.put('posts/'+post.id, post).then(function (result) {
if(result.status != 'error'){
var x = angular.copy(post);
x.save = 'update';
$modalInstance.close(x);
}else{
console.log(result);
}
});
}else{
post.status = 'Active';
Data.post('posts', post).then(function (result) {
if(result.status != 'error'){
var x = angular.copy(post);
x.save = 'insert';
x.id = result.data;
$modalInstance.close(x);
}else{
console.log(result);
}
});
}
};
});
html:
<div class="container">
<div class="row" align="center">
<div class="stats"><i class="fa fa-thumb-tack"></i> Total Posts (<span class="attendStat">{{ totalItems }}</span>)<span class="seperator"> | </span><i class="fa fa-trash-o"></i> Trash (<span class="attendStat">X</span>)</div>
</div>
<div class="row">
<div class="col-md-1">PageSize:
<select ng-model="entryLimit" class="form-control" ng-options="obj.id as obj.name for obj in list_pages" ng-init="entryLimit='10'">
</select>
</div>
<div class="col-md-5"><span class="">Filtered: {{ filtered.length }} of {{ totalItems }} total posts</span>
<input type="text" ng-model="search" ng-change="filter()" placeholder="Filter" class="form-control" />
</div>
<div class="col-md-4 pull-right text-right" ng-show="filteredItems > 0">
<uib-pagination total-items="filteredItems" items-per-page="entryLimit" boundary-link-numbers="true" max-size="maxSize" ng-model="currentPage" class="pagination-sm"></uib-pagination>
</div>
</div>
<br/>
<div class="row">
<div class="table-responsive" ng-show="filteredItems > 0">
<table class="table table-striped table-bordered">
<thead>
<th>Publish Date <a ng-click="sort_by('publishdate');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th>GUID <a ng-click="sort_by('guid');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th>Platform <a ng-click="sort_by('platform');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th>Link Title <a ng-click="sort_by('title');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th>Redirect Url (Base) <a ng-click="sort_by('redirect');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th>Announce <a ng-click="sort_by('announce');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th>Approve <a ng-click="sort_by('approve');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th></th>
</thead>
<tbody ng-repeat="data in filtered = (posts | filter:search | orderBy : predicate :reverse) | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit">
<tr>
<td class="posts-publishdate">{{data.publishdate | dateToISO | date:'MMM d, y h:mm a' }}</td>
<td>{{data.guid}}</td>
<td>{{data.platform}}</td>
<td>{{data.title}}</td>
<td>{{data.redirect}}</td>
<td>
<button class="btn btn-sm" ng-class="{1:'btn-success', 0:''}[data.announce]" ng-click="changePostAnnounce(data);">{{data.announce == '1' ? "Active" : "Inactive"}}</button>
</td>
<td>
<button class="btn btn-sm" ng-class="{1:'btn-success', 0:''}[data.approved]" ng-click="changePostStatus(data);">{{data.approved == '1' ? "Active" : "Inactive"}}</button>
</td>
<td style="width:100px">
<div class="btn-group">
<button type="button" class="btn btn-default fa fa-edit" ng-click="open(data);"></button>
<button type="button" class="btn btn-danger fa fa-trash-o" ng-click="trashPost(data);"></button>
</div>
</td>
</tr>
<tr>
<td></td>
<td colspan="8">
<table class="table table-striped table-bordered">
<thead>
<th>Image Url <a ng-click="sort_by('img');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th>Link Description <a ng-click="sort_by('description');"><i class="glyphicon glyphicon-sort"></i></a></th>
<th>Tweet <a ng-click="sort_by('dynamic_content');"><i class="glyphicon glyphicon-sort"></i></a></th>
</thead>
<tbody>
<tr>
<td><img src="{{data.img}}" width="200"></td>
<td>{{data.description}}</td>
<td>{{data.dynamic_content}}</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-12" ng-show="filteredItems == 0">
<div class="col-md-12">
<h4>No customers found</h4>
</div>
</div>
</div>
</div>
Any help would be much appreciated.
You missed to inject $modal dependency inside postsCtrl controller
app.controller('postsCtrl', function ($scope, $log, $http, $timeout, Data, $modal) {
Make sure you have injected particular dependency before getting
access to it. Assuming you have already added ui.bootstrap module
dependency too.
UPDATE
If you are using latest version of angular ui bootstrap which is 0.14.X would need to inject $uibModal instead of $modal. As they rename all boostrap directive and serviec name prepends with uib prefix.
Same thing will happen with $modalInstance dependency, which need to change to $uibModalInstance
I have managed to create a table using AngularJS. In this table I show products from my datbase which can be filtered on category or some other keywords. Now the user should be able to alter this data in this table to update the data in the database.
AngularJS
categorieFilter = angular.module("categorieFilter", [])
categorieFilter.controller("catFilter", ["$scope", "store", function($scope, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
store.getCategories().then(function(data){
$scope.categories = data;
})
store.getProducts().then(function(data){
$scope.products = data;
})
$scope.filterProductsByCats = function(category){
$scope.search = category;
};
}])
categorieFilter.factory('store', function($http, $q){
function _getCategory (){
var deferred = $q.defer();
$http.get('api/categories').success(function (data) {
deferred.resolve(data);
})
return deferred.promise;
}
function _getProducts (){
var deferred = $q.defer();
var prods = [];
$http.get('api/products').success(function (data) {
for(var i = 0;i<data.length;i++)
{
prods[i] = {name: data[i][0], category: data[i][2], price: data[i][1]};
}
deferred.resolve(prods);
})
return deferred.promise;
}
return {
getCategories: _getCategory,
getProducts : _getProducts
};
});
HTML table
<div ng-app="categorieFilter" ng-cloak="" ng-controller="catFilter">
<div class="input-group">
<input type="text" name="table_search" class="form-control input-sm pull-right" ng-model="search" placeholder="Search"/>
<div class="input-group-btn">
<button class="btn btn-sm btn-default">
<i class="fa fa-search"></i>
</button>
</div>
</div>
<div>
<input type="submit" class="btn btn-success" style="margin:10px; width:30%;" ng-repeat="cat in categories" ng-click="filterProductsByCats(cat.categoryName)" value="{{cat.categoryName}}">
</div>
<table class="table table-hover">
<tr style="background-color:#ddd;">
<th colspan="4" style="text-align:left; font-size:16px;"> Category </th>
<th colspan="4" style="text-align:left; font-size:16px;"> Product </th>
<th colspan="4" style="text-align:left; font-size:16px;"> Price </th>
</tr>
<tr ng-repeat="product in products | filter:search | orderBy: 'category'">
<td colspan="4">{{product.category}}</td>
<td colspan="4">{{product.name}}</td>
<td colspan="4">{{product.price}}</td>
</tr>
</table>
Any ideas or reccomendations to get this done?
A library I like to use to achieve the editing of data, is angular xeditable. http://vitalets.github.io/angular-xeditable/
Then save it by posting it back to the webapi
I am quite new to java script, so I must apologise if this seems basic.
How can I edit rows tables in Smart-Table with Angularjs? There doesn't seem to be a tutorial with the new Smart-Table. I would like to create a simple form for users to enter the hours open for a particular place.
I have created buttons which can add and remove rows on the table, but when I add in contenteditable="true" none of the changes are persisted when I update the object. I understand that the contenteditable is a specific html5 parameters independent of smart-table, but I don't understand how else I can update the data or how I could retrieve the updated data.
The data is retrieved from the angularjs controller via the mean.js routes.
<div class="controls">
<table st-table="place.openHours" class="table table-striped">
<thead>
<tr>
<th>Day</th>
<th>Opening Time</th>
<th>Closing Time</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in place.openHours" contenteditable="true" >
<td>{{row.day}}</td>
<td>{{row.open}}</td>
<td>{{row.close}}</td>
<button type="button" ng-click="removeOpenHour(row)" class="btn btn-sm btn-danger">
<i class="glyphicon glyphicon-remove-circle">
</i>
</button>
</tr>
</tbody>
</table>
<button type="button" ng-click="addOpenHour(row)" class="btn btn-sm btn-success">
<i class="glyphicon glyphicon-plus">
</i> Add new Row
</button>
</div>
Inside the javascript:
$scope.removeOpenHour = function removeOpenHour(row) {
var index = $scope.place.openHours.indexOf(row);
if (index !== -1) {
$scope.rowCollection.splice(index, 1);
}
}
$scope.addOpenHour = function addOpenHour() {
$scope.place.openHours.push(
{
day: 'Monday',
open: 540,
close: 1080
});
};
Thanks I had a look around and used the code from here http://jsfiddle.net/bonamico/cAHz7/ and merged it with my code.
HTML file:
<tr ng-repeat="row in place.openHours">
<td><div contentEditable="true" ng-model="row.day">{{row.day}}</div></td>
<td><div contentEditable="true" ng-model="row.open">{{row.open}}</div></td>
<td><div contentEditable="true" ng-model="row.close">{{row.close}}</div></td>
<td>
<button type="button" ng-click="removeOpenHour(row)" class="btn btn-sm btn-danger">
<i class="glyphicon glyphicon-remove-circle">
</i>
</button>
</td>
JS file:
myApp.directive('contenteditable', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
// view -> model
elm.bind('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(elm.html());
});
});
// model -> view
ctrl.render = function(value) {
elm.html(value);
};
elm.bind('keydown', function(event) {
console.log("keydown " + event.which);
var esc = event.which == 27,
el = event.target;
if (esc) {
console.log("esc");
ctrl.$setViewValue(elm.html());
el.blur();
event.preventDefault();
}
});
}
};
});
My solution is it:
Angular directive :
app.directive("markdown", function() {
return {
restrict: 'EA',
scope: {
value: '='},
template: '<span ng-click="edit()" ng-bind="value"></span><input ng-blur="blur()" ng-model="value"></input>',
link: function($scope, element, attrs) {
// Let's get a reference to the input element, as we'll want to reference it.
var inputElement = angular.element(element.children()[1]);
// This directive should have a set class so we can style it.
element.addClass('edit-in-place');
// Initially, we're not editing.
$scope.editing = false;
// ng-click handler to activate edit-in-place
$scope.edit = function() {
$scope.editing = true;
// We control display through a class on the directive itself. See the CSS.
element.addClass('active');
// And we must focus the element.
// `angular.element()` provides a chainable array, like jQuery so to access a native DOM function,
// we have to reference the first element in the array.
inputElement[0].focus();
};
// When we leave the input, we're done editing.
$scope.blur = function() {
$scope.editing = false;
element.removeClass('active');
}
}
};
});
HTML:
<table st-table="displayedCollection" st-safe-src="rowCollection" class="table table-striped">
<thead>
<tr>
<th st-sort="sku">SKU</th>
<th st-sort="skuSupplier">SKU proveedor</th>
<th st-sort="name">DescripciĆ³n</th>
<th st-sort="cantidad">Cantidad</th>
<th st-sort="precio">Precio unitario</th>
<th st-sort="total">Total</th>
</tr>
<tr>
<th colspan="5"><input st-search="" class="form-control" placeholder="Buscar producto ..." type="text"/></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in displayedCollection">
<td><markdown value="row.sku"></markdown></td>
<td><markdown value="row.skuSupplier"></markdown></td>
<td><markdown value="row.name"></markdown></td>
<td><markdown value="row.cantidad"></markdown></td>
<td><markdown value="row.precio"></markdown></td>
<td><markdown value="row.total"></markdown></td>
<td>
<button type="button" ng-click="removeItem(row)" class="btn btn-sm btn-danger">
<i class="glyphicon glyphicon-remove-circle"></i>
</button>
</td>
</tr>
</tbody>
</table>
I'm new to Angular JS, and I'm trying to implement a page to display, add, edit and delete objects from a REST API. I have functions to add, edit and delete items bound to ng-click, but the edit and delete events are not firing. The only difference between the add and edit/delete bindings seems to be that the edit/delete ng-clicks are inside an ng-repeat.
JavaScript code:
process_errors = function(rejection) {
// Error processing code
}
var exampleApp = angular.module('exampleApp', ['ngResource']);
exampleApp.factory('Example', ['$resource', function($resource) {
return $resource('/api/v1/example/:example_id', {example_id:'#id'});
}]);
exampleApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.headers.common['X-CSRFToken'] = $.cookie('csrftoken');
}]);
exampleApp.controller('exampleListCtrl', ['$scope', 'Example',
function($scope, Example) {
$scope.examples = Example.query();
$scope.newExample = new Example();
$scope.add = function() {
$scope.newExample.$save().then(function(result){
$scope.examples.push(result);
}).then(function() {
$scope.newExample = new Example();
}, process_errors);
}
$scope.editExample = function(example) {
console.log('editing');
var idx = $scope.examples.indexOf(example);
$scope.examples[idx].$save().then(function(result) {
}, function(rejection) {
process_errors(rejection);
$scope.editMode = true;
});
}
$scope.deleteExample = function(example) {
console.log('deletion');
example.$delete().then(function(){
var idx = $scope.examples.indexOf(example);
$scope.examples.splice(idx, 1);
});
}
}]);
HTML:
<div id="content-container" ng-app="exampleApp">
<table class="table table-striped" ng-controller="exampleListCtrl">
<thead>
<!-- Table headers -->
</thead>
<tbody>
<tr>
<form class="form-inline" role="form">
<td><input type="text" class="form-control" ng-model="newExample.start_date" placeholder="2013-11-25"></input></td>
<!-- more fields in the same format -->
<td><button class="btn btn-primary" ng-click="add()">Add</button></td>
</form>
</tr>
</tbody>
<tbody>
<tr ng-repeat="example in examples">
<form class="form-inline" role="form">
<td>
<span ng-hide="editMode">{{example.start_date}}</span>
<input ng-show="editMode" type="text" class="form-control" ng-model="example.start_date" value="{{example.start_date}}"></input>
</td>
<!-- more fields in the same format -->
<td>
<button ng-hide='editMode' class="btn btn-default" ng-click="editMode = true;">Edit</button>
<button ng-show='editMode' class="btn btn-primary" ng-click="editExample(example); editMode = false">Save</button>
</td>
<td><button class="btn btn-danger" ng-click="deleteExample(example)"><span class="glyphicon glyphicon-remove"></span></td>
</form>
</tr>
<tbody>
</table>
</div>
I've also tried binding the functions to $parent.editExample(example).