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
Related
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'm trying to use Angularjs to get data from a row in a table when it is clicked and display it in an editable dialog box. How can I do this? Here's what I have so far:
<table>
<thead>
<tr>
<th>ID No.</th>
<th>Firstname</th>
<th>Lastname</th>
<th>Gender</th>
<th>Time</th>
<th>Date</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="walkin_member in data | filter:searchFilter">
<td><a class="click">{{walkin_member.id}}</a></td>
<td>{{walkin_member.firstname}}</td>
<td>{{walkin_member.lastname}}</td>
<td>{{walkin_member.gender}}</td>
<td>{{walkin_member.time}}</td>
<td>{{walkin_member.datestamp}}</td>
<td>{{walkin_member.type}}</td>
</tr>
</tbody>
</table>
This is my dialog box markup:
<div id="dlgbox">
<div id="dlg-header">Information</div>
<div id="dlg-body">
Firstname <input type="text" value="{{walkin_member.firstname}}"><br/>
Lastname <input type="text" value="{{walkin_member.lastname}}"><br/>
Gender <input type="text" value="{{walkin_member.gender}}"><br/>
Type <input type="text" value="{{walkin_member.type}}"><br/>
</div>
<div id="dlg-footer">
<button onclick="dlgUpdate()">Update</button>
<button onclick="dlgExit()">Exit</button>
</div>
</div>
Here's my controller:
myApp.controller('loglistController', ['$scope', '$http', function ($scope, $http) {
$http.get("../php/loglistajax.php")
.success(function(data){
$scope.data = data;
})
.error(function() {
$scope.data = "error in fetching data";
});
}]);
the dialog box is hidden, it will just show if the function is triggerd onclick
here's my javascript.
function showDialog(){
var whitebg = document.getElementById("white-background");
var dlg = document.getElementById("dlgbox");
whitebg.style.display = "block";
dlg.style.display = "block";
var winWidth = window.innerWidth;
dlg.style.left = (winWidth/2) - 480/2 + "px";
dlg.style.top = "150px";
}
Add an ng-click event to the anchor tag in each row and pass the current member to the method.
<tr ng-repeat="walkin_member in data | filter:searchFilter">
<td>
<a class="click" href="#"
ng-click="showInEdit(walkin_member)">{{walkin_member.id}}</a>
</td>
</tr>
Now in your controller, Add a new property to hold the selected member and a method called showInEdit()
myApp.controller('loglistController', ['$scope', '$http', function ($scope, $http) {
$scope.data=[];
$scope.selectedMember={ firstname:"",lastname:"",gender:"",type:"" }; //new property
$http.get("../php/loglistajax.php")
.success(function(data){
$scope.data = data;
})
.error(function() {
$scope.data = "error in fetching data";
});
$scope.showInEdit=function(member){
$scope.selectedMember = member;
};
}]);
And in your model dialog, you will use the selectedMember property.
<div id="dlgbox">
<div id="dlg-header">Information</div>
<div id="dlg-body">
Firstname <input type="text" ng-model="selectedMember.firstname" />
</div>
</div>
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
I want to add data to my database using AngularJS. First I have to choose a category from a list of categories which I get from my server. After that a user can add a product to the database. I tried accomplishing this using:
AngularJS
categories = angular.module('categories', []);
categories.controller("category",function($scope, $http){
var serviceBase = 'api/';
$http.get(serviceBase + 'categories').then(function (results) {
$scope.categories = results.data;
for(var i = 0; i < $scope.categories.length; i++){
var categories = $scope.categories[i];
}
$scope.product = function($scope, $http, $catID){
$http.post(serviceBase + 'productadd/3/1/Icetealemon/5').then(function(results){
});
}
});
});
HTML
<table id="app2" ng-app="categories" ng-cloak="" class="table table-hover">
<tr >
<th colspan="5">Add product</th>
</tr>
<tr ng-form name="addproductForm" novalidate ng-controller="category">
<td colspan="1">
<select class="form-control m-b-10">
<option ng-repeat= "c in categories">{{c.categoryName}}</option>
</select>
</td>
<td colspan="1">
<select class="form-control m-b-10">
<option>Antwerpen</option>
<option>Leuven</option>
</select>
</td>
<td colspan="1">
<input type="text" class="form-control" placeholder="Name" ng-model="catID"></input>
</td>
<td colspan="1">
<input type="text" class="form-control" placeholder="Price" width="10%"></input>
</td>
<td colspan="1">
<input type="submit" class="btn btn-success" ng-click="product()"></input>
</td>
</tr>
</table>
I am not even using the ng-models to use the data of my html. It's still hard coded because it doesn't even work then. I am getting en error:
TypeError: Cannot read property 'post' of undefined
What am i doing wrong with my $http.post?
categories = angular.module('categories', []);
categories.controller("category",function($scope, $http){
var serviceBase = 'api/';
$http.get(serviceBase + 'categories').then(function (results) {
$scope.categories = results.data;
for(var i = 0; i < $scope.categories.length; i++){
var categories = $scope.categories[i];
}
$scope.product = function($scope, $http, $catID){
// NOTE: This '$http' is $scope.product function parameter
// variable `$http` not angular '$http'
$http.post(serviceBase + 'productadd/3/1/Icetealemon/5').then(function(results){
});
}
});
});
Remove $http parameter from $scope.product function.
Also, look at https://docs.angularjs.org/tutorial/step_05 about angular dependency issue during minification and how to solve it.
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).