How to edit contents in Angular js Smart Table - javascript

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>

Related

smart-table slow performance while displaying large data set

Im trying to display large data set using smart-table. Im contacting server with $http request and when I assign response data to $scope.rowCollection, application stuck for nearly 40 second until all data is displayed on page. In response json i got nearly 18000 results to display. I dont know if I do something wrong. I get response from server in 600 ms but after assign application stuck. It looks like smart-table is trying to make a copy of response in displayedCollection array and this operation take long time but its only my opinion. Please help. Thanks in advance.
HTML
<table st-table="displayedCollection" st-safe-src="rowCollection" class="table">
<thead>
<tr>
<th colspan="8"><input st-search="" class="form-control" placeholder="global search ..." type="text" /></th>
</tr>
<tr>
<th st-sort="TestEndDate">Test Date</th>
<th st-sort="Workplace">Workplace</th>
<th st-sort="Tester">Worker</th>
<th st-sort="SerialNo">Serial Number</th>
<th st-sort="TestProgram">Testing program</th>
<th st-sort="TestResult">Test Result</th>
<th>Download</th>
<th>Detail</th>
</tr>
</thead>
<tbody>
<tr st-select-row="row" st-select-mode="multiple" ng-repeat="row in displayedCollection">
<td>{{row.TestEndDate | date}}</td>
<td>{{row.Workplace}}</td>
<td>{{row.Tester}}</td>
<td>{{row.SerialNo}}</td>
<td>{{row.TestProgram}}</td>
<td>{{row.TestResult}}</td>
<td>
<button type="button" ng-click="downloadItem(row)" class="btn btn-sm btn-success">
<i class="glyphicon glyphicon-download">
</i>
</button>
</td>
<td>
<button type="button" ng-click="detailItem(row)" class="btn btn-sm btn-primary">
<i class="glyphicon glyphicon-eye-open">
</i>
</button>
</td>
</tr>
</tbody>
</table>
Javascript
app.controller('AppController', ['$scope', '$http', '$modal', function ($scope, $http, $modal) {
var search = this;
search.serials = [];
$scope.rowCollection = [];
$scope.init = function () {
waitingDialog.show();//show loading
getTestResults();
};
var getTestResults = function () {
$http({
method: 'GET',
url: "http://sqldev/api/testresults"
}).then(function successCallback(response) {
$scope.rowCollection = response.data;//after assign response.data into rowCollection application stuck
waitingDialog.hide();//hide loading
}, function errorCallback(response) {
console.log('Error: ' + response);
waitingDialog.hide();//hide loading
$scope.open()//open modal with error message
});
};
}]);

Pass params to function inside AngularJS template

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

AngularJS: new object not showing in table

I am using dir-paginate library to paginate my data on the page. The issue I am having is when I am adding a new object to the list and viewing this on the page instantly. On the controller side every thing seems to work just alright.
Here is my controller
/**
* Array of all the items
*/
$scope.allItems = [];
$scope.postResource = function() {
ProjectsFactory.save($scope.newProject)
.success(function(data) {
$scope.allItems.push(data);
console.log($scope.allItems);
$scope.newProject = ''
ToastService.show('Added successfully!');
})
.error(function(data) {
sweetAlert("Oops...", "Something went wrong!", "error");
console.log(data);
});
}
Notice the log I am doing right there. On the console page I can see the new object is being added to the rest of the objects. I believe the issue is occurring on the view side which looks just like this.
<table class="table table-bordered table-hover table-condensed bg-white" st-table="rowCollectionBasic">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="item in allItems | filter: search.query | itemsPerPage : itemPerPage" total-items="totalProjects" current-page="currentPage">
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td style="width:150px">
<button class="btn btn-info btn-sm" ng-click="showEditDialog($event, item)">
<i class="glyphicon glyphicon-edit"></i>
</button>
<button class="btn btn-danger btn-sm" ng-click="deleteResource(item, $index)">
<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="20" class="text-center">
<dir-pagination-controls on-page-change="pageChanged(newPageNumber)" boundary-links="true"></dir-pagination-controls>
<md-progress-circular md-mode="indeterminate" ng-if="AjaxInProgress"></md-progress-circular>
</td>
</tr>
</tfoot>
To see the new created object on the page, I need to either refresh the page or click somewhere else and return to the same page again.
Someone has an idea what I am doing wrong?
Update #1
The project service has $http
// save a new resource
save: function(data) {
return $http({
url: $rootScope.baseUrl + 'projects',
method: 'POST',
data: data
});
},
Thanks!

Angular Smart table doesn't works

I am trying to use Angular Smart table. But I get this error message in the browser.
Error: [ng:areq] http://errors.angularjs.org/1.3.9/ng/areq?p0=safeCtrl&p1=not%20aNaNunction%2C%20got%20undefined
at Error (native)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:6:416
at Qb (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:19:417)
at sb (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:20:1)
at $get (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:76:95)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:57:257
at s (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:7:408)
at v (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:57:124)
at g (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:52:9)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js:51:118
This is my HTML
<div ng-controller="safeCtrl">
<button type="button" ng-click="addRandomItem(row)" class="btn btn-sm btn-success">
<i class="glyphicon glyphicon-plus">
</i> Add random item
</button>
<table st-table="displayedCollection" st-safe-src="rowCollection" class="table table-striped">
<thead>
<tr>
<th st-sort="firstName">first name</th>
<th st-sort="lastName">last name</th>
<th st-sort="birthDate">birth date</th>
<th st-sort="balance">balance</th>
</tr>
<tr>
<th colspan="5"><input st-search="" class="form-control" placeholder="global search ..." type="text" /></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in displayedCollection">
<td>{{row.firstName}}</td>
<td>{{row.lastName}}</td>
<td>{{row.birthDate}}</td>
<td>{{row.balance}}</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>
</div>
<script src="~/Scripts/CustomerView.js"></script>
and this is my Javascript:
angular.module('customerDetailTableApp', ['smart-table']).controller('safeCtrl', ['$scope', function($scope) {
var firstnames = ['Laurent', 'Blandine', 'Olivier', 'Max'];
var lastnames = ['Renard', 'Faivre', 'Frere', 'Eponge'];
var dates = ['1987-05-21', '1987-04-25', '1955-08-27', '1966-06-06'];
var id = 1;
function generateRandomItem(id) {
var firstname = firstnames[Math.floor(Math.random() * 3)];
var lastname = lastnames[Math.floor(Math.random() * 3)];
var birthdate = dates[Math.floor(Math.random() * 3)];
var balance = Math.floor(Math.random() * 2000);
return {
id: id,
firstName: firstname,
lastName: lastname,
birthDate: new Date(birthdate),
balance: balance
}
}
$scope.rowCollection = [];
for (id; id < 5; id++) {
$scope.rowCollection.push(generateRandomItem(id));
}
//copy the references (you could clone ie angular.copy but then have to go through a dirty checking for the matches)
$scope.displayedCollection = [].concat($scope.rowCollection);
//add to the real data holder
$scope.addRandomItem = function addRandomItem() {
$scope.rowCollection.push(generateRandomItem(id));
id++;
};
//remove to the real data holder
$scope.removeItem = function removeItem(row) {
var index = $scope.rowCollection.indexOf(row);
if (index !== -1) {
$scope.rowCollection.splice(index, 1);
}
}
}]);
I have tried with several ways, but couldn't find any solution. I have used ng-app inside html tag <html ng-app="myapp"> and controller in body tag <body ng-app="customerDetailTableApp">
You need to use only one ng-app into your view, and include(inject) your second dependency module into your first ng-app.
Multiple ng-app directives on a page
How many ng-App can be declared in in Angular JS?
angular.module('myapp', ['customerDetailTableApp']);

Angular.js ng-click event not firing

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).

Categories

Resources