Why doesnt ngTable accept my dataset? - angularjs

I have a simple piece of data that I'm trying to test with Ng-Table. I followed the example on ng-table but I'm assuming dataset is expecting a promise instead of an array. The only difference Im seeing is how Im handling $scope.
My example works if I put the data variable on scope and dont pass it to tableParams from my js file but then I lose the functionality of filters.
Ng-Table example:
https://github.com/esvit/ng-table/blob/master/examples-old/demo15.html
My Code
HTML
<div ng-app="Pulse">
<div ng-controller="MainController as main">
<table ng-table="main.groupTable" class="table" show-filter="true">
<tr ng-repeat="user in $data"
<td title="'Name'" filter="{ name: 'text'}" sortable="'name'">
{{user.name}}</td>
</tr>
</table>
</div>
Js
var app = angular.module("Pulse", ['ngTable'])
.controller("MainController", MainController );
function MainController ($scope, NgTableParams) {
var self = this;
var data = [{name: "Moroni", age: 50}];
$scope.groupTable = new NgTableParams({}, { dataset: data});
};

Currently, ng-table use 'data' property instead of 'dataset'. I guess they've just forgot to update the documentation. So just write:
$scope.groupTable = new NgTableParams({}, { data: data});
and it should work.

New version(1.x) is using 'dataset' property but the old version(0.8.3 tested) is using 'data' property

Related

ng-click, ng-model not working in angularjs datatable

I have a datatable with column filters made with AngularJS.
Here is the HTML:
<body ng-app="myApp" ng-controller="appController as Ctrl">
<table class="table table-bordered table-striped table-hover dataTable js-exportable" datatable="ng" dt-options="Ctrl.dtOptions" dt-columns="Ctrl.dtColumns">
<thead>
<tr>
<th></th>
<th>Name</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Name</th>
</tr>
</tfoot>
<tbody>
<tr ng-repeat="user in userList">
<td>
<input type="checkbox" id="user-{{ $index }}" ng-model="Ctrl.checkboxValue[$index]" ng-click="Ctrl.checkValue(user.id)" ng-true-value="{{user.id}}" />
<label for="user-{{ $index }}"></label>
</td>
<td>
<a href="#">
{{ ::user.name }}
</a>
</td>
</tr>
</tbody>
</table>
Here's the script:
angular.module('myApp', ['ngAnimate', 'ngSanitize', 'datatables', 'datatables.columnfilter'])
.controller('appController', function($scope, $compile, DTOptionsBuilder, DTColumnBuilder){
$scope.userList = [
{
id: '1',
name: 'hello'
},
{
id: '2',
name: 'hi'
}
];
var vm = this;
vm.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withOption('createdRow', function (row, data, dataIndex) {
$compile(angular.element(row).contents())($scope);
})
.withColumnFilter({
aoColumns: [{
}, {
type: 'text',
bRegex: true,
bSmart: true
}]
});
vm.dtColumns = [
DTColumnBuilder.newColumn('').withTitle(''),
DTColumnBuilder.newColumn('name').withTitle('Name'),
];
vm.checkboxValue = [];
vm.checkValue = function(id){
console.log(id);
}
});
Issues:
id of the user does not get passed to checkValue function. Hence, the console.log is undefined.
Suppose if the checkbox of 1st user is checked, the value of checkboxValue array is [undefined: '1']. If checkbox of 2nd user is checked the value of checkboxValue array becomes [undefined: '2'].
Only one checkbox gets checked. Why is that?
Demo: https://plnkr.co/edit/A3PJfBuwtpUQFAIz8hW7?p=preview
You kill your code with redundancy. Look at this :
When using the angular way, you CANNOT use the dt-column directive.
Indeed, the module will render the datatable after the promise is
resolved. So for DataTables, it's like rendering a static table.
You are in fact using the "angular way" along with dt-columns. You could switch to use DTColumnDefBuilder but why define the columns when you already have a <thead> section? It would only make sense if you need to use sorting plugins etc on specific columns. And / or not is specifying the header in the markup.
Moreover, when you are rendering with angular it is not necessary to $compile anything, in fact is is very wrong, angular already does that. So
remove your dt-columns or replace it with a dt-column-defs literal
remove your $compile from the createdRow callback
Then it works. I would also remove the ng-true-value="{{user.id}}" attribute. You want an array representing the checkboxes state, why set the state to the user.id and not true or false?
vm.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withColumnFilter({
aoColumns: [{
}, {
type: 'text',
bRegex: true,
bSmart: true
}]
});
and
<input type="checkbox" id="user-{{ $index }}" ng-model="Ctrl.checkboxValue[user.id]" ng-click="Ctrl.checkValue(user.id)" />
Is really all you need.
forked plunkr -> https://plnkr.co/edit/Z82oHi0m9Uj37LcdUSEW?p=preview

Construct json from dynamic key and values in angularjs

i am developing a web application where am creating textboxes dynamically using the attributes from server. I am successfull in displaying the attribute values as html table inside modal. I need to create json object using the attributes in controller and make two way binding using angularjs. I am very new to angularjs.I need a json using the key and values like
{"NAME": "",
"TYPE: "forest"} and make two way binding for this dynamically created textboxes.
<tr ng-repeat="(key, value) in prop['properties']">
<td ><label>{{ key}}</label></td>
<td><input type="text" ng-value="value"></td>
</tr>
Just put ng-model in your input text element and bind the value to it
html
<table>
<tr ng-repeat="(key,value) in prop">
<td ><label>{{key}}</label></td>
<td><input type="text" ng-model="prop[key]"></td>
</tr>
</table>
<div>
{{prop | json}}
</div>
in controller
$scope.prop = {"NAME": "", "TYPE": "forest"} ;
demo codepen
Use ng-modal for two way binding.
HTML:
<div ng-repeat="item in items">
<input ng-model="item.value" type="text" size="40">
</div>
JavaScript:
app.controller('MainCtrl', function($scope) {
$scope.items = [
{value:'First Item'},
{value: 'Second Item'}
];
$scope.addInputItem = function() {
$scope.items.push({value:''});
};
});
Working code here: http://plnkr.co/edit/KIR7AyoF553STjOx
<div ng-app="myApp" ng-controller="controller">
Name: <input ng-model="details.name">
</div>
<script>
var app = angular.module('myApp', []);
app.controller('controller', function($scope) {
$scope.details = {};
$scope.details.name = "John Doe";
});
</script>
This might i think you were asking for

ng-repeat value is not visible inside nested tag

I am new to angularjs and trying to work with ng-repeat but somehow ng-repeat's key/value is not visible if I am trying to print it in nested tags
working:
<div>
<table>
<tr ng-repeat="prop in array">
<td><span ng-bind-html="prop.field1"></span></td>
</tr>
</table>
</div>
And below code is not working:-
<div ng-repeat="prop in array">
<table>
<tr>
<td><span ng-bind-html="prop.field1"></span></td>
</tr>
</table>
</div>
Updated:
var $app = angular.module('apps', ['ngSanitize']);
$app.controller('cntr', ['$scope', function($scope) {
$scope.guestList = [{
dob: '12/12/12'
}];
}]);
For html to show properly in angular js you have to 'sanitize' it, using the $sce provider from AngularJS. Read here: https://docs.angularjs.org/api/ng/service/$sce
In principle, before you bind your variable to html output, you have to sanitize it like this:
$scope.guest.sanitizedInput = $sce.trustAsHtml($scope.guest.res_addr1);
and html:
<td class="table-column-value res-addr1-value"><span ng-bind-html="guest.sanitizedInput"></span>

Displaying Json Data from ng-repeat in multiple containers

Hey I have a question about using ng-repeats. I'm trying to display user data from a large json file in two separate containers. When a user clicks on a row it displays the other piece of the ng-repeat in a different section. If someone could take a look at this fiddle and maybe give me a direction to go in that would be awesome. Thanks!
I'm also using ngTable for the table params, but I don't think that has much to do with the issue.
http://jsfiddle.net/cL5aE/1/
HTML:
<body>
<div ng-controller="myController">
<div class="col-md-6">
<table>
<tr ng-repeat="user in $data" ng-click="loadDetails()">
<td>{{user.name}}</td>
<td>{{user.id}}</td>
</tr>
</table>
</div>
<div class="col-md-6">
<tr ng-repeat="user in $data" ng-show="loadDetails()">
<td>{{user.foo}}</td>
<td>{{user.bar}}</td>
</tr>
</div>
</div>
</body>
Controller:
angular.module('app', ['ngTable']);
app.controller('myController', function ($scope, $http, ngTableParams) {
$http.get('http://myjson.com/data.json')
.success(function (data, status) {
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
CompleteDate: 'asc' // initial sorting
}
}, {
total: data.length, // length of data
getData: function ($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ? $filter('orderBy')(data, params.orderBy()) : data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
$scope.loadDetails = function(data) {
//???
}
});
I would pass the user object as a parameter to a function and assign it a model. That way you don't need to use the ng-repeat in both sections leading to a cleaner and more readable code.
Pass the object you're displaying on the ng-repeat:
<tr ng-repeat="user in $data" ng-click="loadDetails(user)">
Function to load the object to a model property:
$scope.loadDetails = function(user) {
$scope.viewModel.selectedUser = user;
}
And finally assign the model property to the view:
<table>
<tr ng-show="viewModel.selectedUser">
<td>{{viewModel.selectedUser.foo}}</td>
<td>{{viewModel.selectedUser.bar}}</td>
</tr>
</table>
http://jsfiddle.net/jimenezjrs/5Cd32/

Calculate total over repeated cart item totals with angular

I've a simplified shopping cart like the following with a controller for each cart item:
<!DOCTYPE HTML>
<html ng-app="cart">
<div ng-controller="cartCtrl">
<table>
<tr><th>qty</th><th>prize</th><th>total</th></tr>
<tr ng-repeat="item in cartItems" ng-controller="cartItemCtrl">
<td>
<input ng-model="item.qty"/>
</td>
<td>
<input ng-model="item.prize" />
</td>
<td>
{{total}}
</td>
</tr>
</table>
total: {{cartTotal}}
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.js"></script>
<script>
(function(){
var cart = angular.module('cart', []);
cart.controller('cartCtrl', ['$scope', function($scope){
$scope.cartItems = [{},{},{},{}];
}]);
cart.controller('cartItemCtrl', ['$scope', function($scope){
$scope.$watchCollection('item', function(){
$scope.total = $scope.item.qty * $scope.item.prize;
});
}]);
}());
</script>
</html>
I couldn't make it work in JSFiddle: http://jsfiddle.net/XY3n8/1/
Now I want to to calculate the cart total but I do not want to recalculate the item totals. Instead I want to reuse the already calculated item totals. How? (In my use case the item total calculation is a bit more complex.)
You need to do a "deep" watch on the collection and object to get sub-totals and totals. $watchCollection is better for knowing when things get added/removed. $watch will look for changes in the existing object(s).
For encapsulating the item's total, there are several ways to do this, but I'd probably create an Item model (probably a better name) and inject it via a factory. It removes the need for one of the controllers in this example, but requires you to create a module (which is best practice anyway)
How about this?
var ShoppingCart = angular.module('shoppingCart', []);
ShoppingCart.factory('Item', function() {
function Item() {
this.total = function() {
return (this.qty * this.prize) || 0;
}
}
return Item;
});
ShoppingCart.controller('cartCtrl', function($scope, Item) {
$scope.cartItems = [new Item(), new Item(), new Item(), new Item()];
$scope.$watch('cartItems', function() {
var cartTotal = 0;
$scope.cartItems.forEach(function(item) {
cartTotal += item.total();
});
$scope.cartTotal = cartTotal;
}, true);
});
And the HTML updates slightly. You reference the module name in the ng-app, get rid of the sub-controller, and reference item.total() directly in the view.
<div ng-app="shoppingCart" ng:controller="cartCtrl">
<table>
<tr><th>qty</th><th>prize</th><th>total</th></tr>
<tr ng:repeat="item in cartItems">
<td>
<input ng:model="item.qty"/>
</td>
<td>
<input ng:model="item.prize" />
</td>
<td>
{{item.total()}}
</td>
</tr>
</table>
total: {{cartTotal}}
</div>
Here is a working codepen.
This is an approach using the ng-init directive to extend the model and do the calculations.
http://www.ozkary.com/2015/06/angularjs-calculate-totals-using.html

Resources