I am trying to make a table which has sorting as well as a button to select which columns are to be displayed.
Both these features work when used alone but fail when I try to use them together.
JS
angular.module('test', []);
angular.module("test").controller("sessionCtrl", sessionCtrl);
function sessionCtrl() {
var vm = this;
vm.testvar= "HELLO";
vm.sortType = 'name';
vm.sortReverse = false;
vm.columnVisiblity = {
name: true,
specification: true,
type: true,
};
vm.TableData = [{
name: "2017/03/01-14",
specification: "IDB-idb-1wk",
type: "Full"
}, {
name: "2017/03/01-17",
specification: "Set-04",
type: "Full"
}, {
name: "2017/03/04-11",
specification: "IDB-idb-1wk",
type: "Full"
}];
}
HTML
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-controller="sessionCtrl as vm">
{{vm.testvar}}
<table>
<thead>
<tr>
<th ng-click="vm.sortType='name'; vm.sortReverse=!vm.sortReverse" ng-if="vm.columnVisiblity.name">NAME
</th>
<th ng-click="vm.sortType='specification'; vm.sortReverse=!vm.sortReverse" ng-if="vm.columnVisiblity.specification">SPECIFICATION
</th>
<th ng-click="vm.sortType='type'; vm.sortReverse=!vm.sortReverse" ng-if="vm.columnVisiblity.type">TYPE
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in vm.TableData | orderBy:vm.sortType:vm.sortReverse">
<td ng-if="vm.columnVisiblity.name">{{item.name}}</td>
<td ng-if="vm.columnVisiblity.specification">{{item.specification}}</td>
<td ng-if="vm.columnVisiblity.type">{{item.type}}</td>
</tr>
</tbody>
</table>
TOGGLE NAME
TOGGLE SPECIFICATION
TOGGLE TYPE
</body>
Basically I'm making a table whose columns are visible on the basis of the columnVisibility object.
And I'm using orderby filter to sort the table.
Problem is TOGGLE NAME here spelling of columnVisibility doesnt match with that in controller
vm.columnVisiblity = {
name: true,
specification: true,
type: true,
};
It is a typing mistake, correct the spelling and it will work
Demo : https://jsfiddle.net/m7a74L8f/
angular.module('test', []);
angular.module("test").controller("sessionCtrl", sessionCtrl);
function sessionCtrl() {
var vm = this;
vm.testvar= "HELLO";
vm.sortType = 'name';
vm.sortReverse = false;
vm.columnVisiblity = {
name: true,
specification: true,
type: true,
};
vm.TableData = [{
name: "2017/03/01-14",
specification: "IDB-idb-1wk",
type: "Full"
}, {
name: "2017/03/01-17",
specification: "Set-04",
type: "Full"
}, {
name: "2017/03/04-11",
specification: "IDB-idb-1wk",
type: "Full"
}];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="sessionCtrl as vm">
{{vm.testvar}}
<table>
<thead>
<tr>
<th ng-click="vm.sortType='name'; vm.sortReverse=!vm.sortReverse" ng-if="vm.columnVisiblity.name">NAME
</th>
<th ng-click="vm.sortType='specification'; vm.sortReverse=!vm.sortReverse" ng-if="vm.columnVisiblity.specification">SPECIFICATION
</th>
<th ng-click="vm.sortType='type'; vm.sortReverse=!vm.sortReverse" ng-if="vm.columnVisiblity.type">TYPE
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in vm.TableData | orderBy:vm.sortType:vm.sortReverse">
<td ng-if="vm.columnVisiblity.name">{{item.name}}</td>
<td ng-if="vm.columnVisiblity.specification">{{item.specification}}</td>
<td ng-if="vm.columnVisiblity.type">{{item.type}}</td>
</tr>
</tbody>
</table>
TOGGLE NAME
TOGGLE SPECIFICATION
TOGGLE TYPE
</div>
Related
Let us assume we have following data structure:
var data = [
{
name: "item name",
nestedData: [{
name: "nested name",
quantity: 1
},
{
name: "nested name 2",
quantity: 2
}
]
},
{
name: "item name 2",
nestedData: [{
name: "nested name 3",
quantity: 3
}
]
}
];
Standard behavior of ng-repeat directive will iterate over high level elements. If we run ng-repeat="item in data" it will produce two items.
Is it possible - without using custom directive - to iterate over first item ("item name") twice (multiply it by a length of nestedData array)?
The output I'd like to achieve is:
<table>
<thead>
<th>Name</th>
<th>Nested name</th>
<th>Nested quantity</th>
</thead>
<tbody>
<tr>
<td rowspan="2">item name</td>
<td>nested name</td>
<td>1</td>
</tr>
<tr>
<td ng-hide="true">item name</td>
<td>nested name 2</td>
<td>2</td>
</tr>
<tr>
<td>item name 2</td>
<td>nested name 3</td>
<td>3</td>
</tr>
</tbody>
</table>
Nested ng-repeat is not suitable in this situation because there's a need to iterate over <tr>'s.
You can use a nested ng-repeat to get your desired result as it's valid HTML to have multiple tbody elements.
Here is a JSFiddle for a working example
<table>
<thead>
<th>Name</th>
<th>Nested name</th>
<th>Nested quantity</th>
</thead>
<tbody ng-repeat="item in data">
<tr ng-repeat="nestedItem in item.nestedData">
<td rowspan="{{item.nestedData.length}}" ng-hide="$index == 1">{{item.name}}</td>
<td>{{nestedItem.name}}</td>
<td>{{nestedItem.quantity}}</td>
</tr>
</tbody>
</table>
It's a different approach to achieve expected output.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var data = [
{
name: "item name",
nestedData: [
{
name: "nested name",
quantity: 1
},
{
name: "nested name 2",
quantity: 2
},
{
name: "nested name 3",
quantity: 3
}
]
},
{
name: "item name 2",
nestedData: [{
name: "nested name 3",
quantity: 3
}
]
}
];
var nestedData = [];
angular.forEach(data, function(item){
if(item.nestedData.length > 1){
angular.forEach(item.nestedData, function(nestedItem){
nestedData.push({
name : item.name,
nestedName: nestedItem.name,
nestedQty: nestedItem.quantity,
colspan: item.nestedData.length
});
});
} else {
nestedData.push({
name : item.name,
nestedName: item.nestedData[0].name,
nestedQty: item.nestedData[0].quantity
});
}
});
$scope.data = nestedData;
});
tr.multiple > td:first-child {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<div class="container" ng-app="myApp" ng-controller="myCtrl">
<table class="table table-stripped">
<thead>
<th>Name</th>
<th>Nested name</th>
<th>Nested quantity</th>
</thead>
<tbody>
<tr ng-repeat="item in data" ng-class="{'multiple': item.colspan > '1' && !$first}">
<td rowspan="{{item.colspan ? item.colspan : '1'}}">{{item.name}}</td>
<td>{{item.nestedName}}</td>
<td>{{item.nestedQty}}</td>
</tr>
</tbody>
</table>
</div>
I just began learning AngularJS, and I am trying to create a pretty simple web application. Right now, I have some users. Each user is displayed in an individual table and each user has its own details which is displayed in a table under it.
$scope.userList = [{username: "Bob_t", detailsId: 1}, {username: "Mike_V", detailsId: 2}];
$scope.userDetails = [{Name: "Bob", Age: 20, id: "1"}, {Name: "Michael", Age: 18, id: "2"}];
You can see that each user has a reference to it's corresponding details (detailsId in userList corresponds to id in userDetails).
Basically, what I'm trying to do is initially have the details table hidden for each user. And when someone clicks the expand button for a specific user, open that user's corresponding details table and populate it with that user's details. What I'm having trouble with is getting the detailsId from the clicked expand button and then using that to query my DB to get the correct user's details to display in the table under it.
<div ng-repeat="user in userList | filter:searchBox">
<div class="uk-panel-box-secondary uk-overflow-container tableDiv uk-margin-large-bottom">
<table class="uk-table uk-table-hover uk-margin-top">
<thead>
<tr>
<th>Username</th>
</tr>
</thead>
</table>
<a class="uk-margin-bottom uk-margin-left" id="expandIcon" ng-click="isOpened=!isOpened; showOrHideDetails(isOpened, param)" ng-class="{'uk-icon-plus-square-o': !isOpened, 'uk-icon-minus-square-o': isOpened}"></a>
</div>
<div class="uk-panel-box-secondary uk-overflow-container uk-margin-top uk-margin-large-left uk-margin-bottom tableDiv">
<table class="uk-table uk-table-hover uk-margin-top">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th></th>
</tr>
</thead>
<tr ng-repeat="details in userDetails" id={{user.id}}>
<td>{{details.Name}}</td>
<td>{{details.Age}}</td>
<td>
</td>
</tr>
</table>
</div>
</div>
my controller:
$http({
method : "GET",
url : "http://database:8081/userAccounts/"
}).then(function mySucces(response) {
$scope.userList = response.data;
}, function myError(response) {
// $scope.userList = response.statusText;
});
$scope.showOrHideDetails = function(isOpened, param)
if(isOpened){
console.log($scope.id)
$scope[id] = true;
console.log($scope.id);
$http({
method : "GET",
url : "http://database:8081/details?id=" + index
}).then(function mySucces(response) {
$scope.userDetails = response.data;
}, function myError(response) {
$scope.userDetails = response.statusText;
});
}
else{
$scope.showDetails = false;
}
}
What is really confusing to me is once I get the correct userDetails object after querying the DB, how do I populate the corresponding table with that info?
I know I probably need a model, but this confuses me because the number of users is unknown.
First, your code is a bit confuse..
After each query you're attributing the response (which one is the details of a single user) to the whole array userDetails:
$scope.userDetails = response.data;
While it should be:
$scope.userDetails.push(response.data);
In addition, you have a single variable called isOpened, for sure it won't work, because you have multiple buttons for only 1 variable.
So my suggestion is to change it to:
<a class="uk-margin-bottom uk-margin-left" id="expandIcon" ng-click="showOrHideDetails(user)" ng-class="{'uk-icon-plus-square-o': !user.isOpened, 'uk-icon-minus-square-o': user.isOpened}"></a>
Also you have to check if the userDetail is already in your userDetails array.
Finally, since you want to show the details based on the user, you can use the native filter, because you already have the id property of users in both arrays, as below:
<tr ng-if="user.isOpened" ng-repeat="details in userDetails | filter: { id: user.detailsId }" id={{user.id}}>
A simple demo:
(function() {
angular
.module('app', [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope', '$http'];
function MainCtrl($scope, $http) {
$scope.userList = [{
username: "Bob_t",
detailsId: 1
}, {
username: "Mike_V",
detailsId: 2
}];
$scope.userDetails = [{
Name: "Bob",
Age: 20,
id: "1"
}, {
Name: "Michael",
Age: 18,
id: "2"
}];
$scope.showOrHideDetails = function(user) {
user.isOpened = !user.isOpened;
function mySuccess(response) {
$scope.userDetails.push(response.data);
}
function myError(response) {
console.log(response.statusText);
}
if (user.isOpened) {
$http.get('http://database:8081/details?id=' + user.id)
.then(mySuccess)
.catch(myError);
} else {
$scope.showDetails = false;
}
}
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.26.4/js/uikit.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.26.4/css/uikit.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="user in userList | filter:searchBox">
<div class="uk-panel-box-secondary uk-overflow-container tableDiv uk-margin-large-bottom">
<table class="uk-table uk-table-hover uk-margin-top">
<thead>
<tr>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-bind="user.username"></td>
</tr>
</tbody>
</table>
<a class="uk-margin-bottom uk-margin-left" id="expandIcon" ng-click="showOrHideDetails(user)" ng-class="{'uk-icon-plus-square-o': !user.isOpened, 'uk-icon-minus-square-o': user.isOpened}"></a>
</div>
<div class="uk-panel-box-secondary uk-overflow-container uk-margin-top uk-margin-large-left uk-margin-bottom tableDiv">
<table class="uk-table uk-table-hover uk-margin-top">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th></th>
</tr>
</thead>
<tr ng-if="user.isOpened" ng-repeat="details in userDetails | filter: { id: user.detailsId }" id={{user.id}}>
<td ng-bind="details.Name"></td>
<td ng-bind="details.Age"></td>
<td>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>
I hope it helps!!
have you tried passing user from
<div ng-repeat="user in userList | filter:searchBox">
to function showOrHideDetails(user)
I'm trying to populate an input two ways. The first method is to simply type an amount into the input, which works perfectly. The second method (which I'm struggling with) is to check the checkbox generated within the ngRepeat directive.
The desired behavior is that the checkbox will take the value of item.amount from the JSON data and populate the input with that value. Here is the markup:
<table class="table table-striped header-fixed" id="invoiceTable">
<thead>
<tr>
<th class="first-cell">Select</th>
<th class="inv-res2">Invoice #</th>
<th class="inv-res3">Bill Date</th>
<th class="inv-res4">Amount</th>
<th class="inv-res5">Amount to Pay</th>
<th class="inv-res6"></th>
</tr>
</thead>
<tbody>
<tr ng-if="invoices.length" ng-repeat="item in invoices | filter: {status:'Unpaid'}">
<td class="first-cell"><input type="checkbox" /></td>
<td class="inv-res2">{{item.invoiceNum}}</td>
<td class="inv-res3">{{item.creationDate}}</td>
<td class="inv-res4" ng-init="invoices.total.amount = invoices.total.amount + item.amount">{{item.amount | currency}}</td>
<td class="inv-res5">$
<input ng-validate="number" type="number" class="input-mini" ng-model="item.payment" ng-change="getTotal()" step="0.01" /></td>
</tr>
</tbody>
</table>
<table class="table">
<tbody>
<tr class="totals-row" >
<td colspan="3" class="totals-cell"><h4>Account Balance: <span class="status-error">{{invoices.total.amount | currency }}</span></h4></td>
<td class="inv-res4"><h5>Total to pay:</h5></td>
<td class="inv-res5">{{total | currency}}</td>
<td class="inv-res6"></td>
</tr>
</tbody>
</table>
And here is the JavaScript:
myApp.controller('invoiceList', ['$scope', '$http', function($scope, $http) {
$http.get('assets/js/lib/angular/invoices.json').success(function(data) {
$scope.invoices = data;
});
$scope.sum = function(list) {
var total=0;
angular.forEach(list , function(item){
total+= parseInt(item.amount);
});
return total;
};
$scope.total = 0;
$scope.getTotal = function() {
$scope.total = 0;
$scope.invoices.forEach(function(item){
$scope.total += parseFloat(item.payment);
});
};
$scope.pushPayment = function(item){
if($scope.checked == 'checked'){
return item.payment;
}
};
}]);
If I understand correctly you want a toggle-able check box, If it is checked then you want to copy that invoices amount into the input box below. You could do something similar to below with a combination of ng-model and ng-change
<tr ng-if="invoices.length" ng-repeat="item in invoices | filter: {status:'Unpaid'}">
<td class="first-cell">
<input type="checkbox" ng-model="item.checked" ng-change="select(item)"/>
</td>
<td class="inv-res5">$
<input ng-validate="number" type="number" class="input-mini" ng-model="item.payment" step="0.01"/>
</td>
</tr>
and add the following to your controller
$scope.select = function(item) {
if(item.checked){
item.payment = item.amount;
}
}
What this should do:
You bind the status of the check box to $scope.checked using ng-model
Every time the checkbox status changes ng-change is called, therefore selectInvoice is called.
Select invoice checks whether the checkbox is checked and adjusts the item.payment value accordingly which is bound to the inputs ng-model
See this Plunker for a working example (Note I thinned out the code so its only the bit we're interested in
As an aside, you don't need to have the input box call getTotal when its value changes. Just change the last few lines to:
<td class="inv-res4"><h5>Total to pay:</h5></td>
<td class="inv-res5">{{getTotal() | currency}}</td>
And modify your JavaScript to:
$scope.getTotal = function() {
var total = 0;
$scope.invoices.forEach(function(item){
total += parseFloat(item.payment);
});
return total;
};
It will still be up to date every time Angular 'digests'
The Plunker
The html:
<table class="table table-striped header-fixed" id="invoiceTable">
<thead>
<tr>
<th class="first-cell">Select</th>
<th class="inv-res2">Invoice #</th>
<th class="inv-res3">Bill Date</th>
<th class="inv-res4">Amount</th>
<th class="inv-res5">Amount to Pay</th>
<th class="inv-res6"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in mainCtrl.invoiceList.invoices">
<td class="first-cell"><input type="checkbox" ng-model="item.selected" /></td>
<td class="inv-res2">{{item.invoiceNum}}</td>
<td class="inv-res3">{{item.creationDate}}</td>
<td class="inv-res4" ng-init="invoices.total.amount = invoices.total.amount + item.amount">{{item.amount | currency}}</td>
<td class="inv-res5">$
<input type="text" ng-model="mainCtrl.getAmount(item)"/></td>
</tr>
</tbody>
</table>
<table class="table">
<tbody>
<tr class="totals-row" >
<td colspan="3" class="totals-cell"><h4>Account Balance: <span class="status-error">{{invoices.total.amount | currency }}</span></h4></td>
<td class="inv-res4"><h5>Total to pay:</h5></td>
<td class="inv-res5">{{mainCtrl.getTotalAmount()}}</td>
<td class="inv-res6"></td>
</tr>
</tbody>
</table>
The JS:
var app = angular.module('plunker', []);
app.controller('MainCtrl', ['tempDataStorageService', function(tempDataStorageService) {
var myCtrl = this;
myCtrl.invoiceList = tempDataStorageService;
myCtrl.getAmount = function(item){
return item.selected? item.amount : "";
};
myCtrl.getTotalAmount = function(){
var total = 0;
for(var i = 0; i < tempDataStorageService.invoices.length; i++){
if(tempDataStorageService.invoices[i].selected){
total = total + tempDataStorageService.invoices[i].amount;
}
}
return total;
}
}]);
app.factory('tempDataStorageService', function() {
// The service object
var storage = this;
storage.invoices = [{invoiceNum: 1, creationDate: "1/1/16", amount: 1.50, selected: false},
{invoiceNum: 2, creationDate: "1/2/16", amount: 2.50, selected: false},
{invoiceNum: 2, creationDate: "1/2/16", amount: 2.50, selected: false},
{invoiceNum: 3, creationDate: "1/3/16", amount: 3.50, selected: false},
{invoiceNum: 4, creationDate: "1/4/16", amount: 4.50, selected: false},
{invoiceNum: 5, creationDate: "1/5/16", amount: 5.50, selected: false},
{invoiceNum: 6, creationDate: "1/6/16", amount: 6.50, selected: false},
{invoiceNum: 7, creationDate: "1/7/16", amount: 7.50, selected: false},
{invoiceNum: 8, creationDate: "1/8/16", amount: 8.50, selected: false}];
// return the service object
return storage;
});
That's a way of doing it
Add an attribute amountToPay to your invoices and send the item to the getTotal function:
<input ng-validate="number" type="number" class="input-mini" value="{{pushPayment()}}"
ng-model="item.amountToPay" ng-change="getTotal(item)" step="0.01" /></td>
In your checkbox change the ng-model to item.checked:
<input type="checkbox" ng-checked="item.checked" /></td>
Add this to your getTotal() function:
$scope.getTotal = function(item) {
item.checked = true;
$scope.total = 0;
$scope.invoices.forEach(function(item){
$scope.total += parseFloat(item.payment);
});
};
If you need to populate your input, just modify the amountToPay attribute
Thanks for the assistance, but I think I was overthinking it. I got to work with simply adding:
ng-click="item.payment=item.amount" ng-change="getTotal()"
to the checkbox. I still have to incorporate this into the sum function, but I solved the issue.
I'm using a table in which I'm displaying some objects. I'm using jquery (bad, I know. But only thing I could get working) to add/remove class ng-hide from all elements with a specific ID. This results in a column being hidden and it works fine. But when any updates from the server comes and I use $scope.rows.push(object) and $scope.apply() the order of the columns gets messed up and the hidden column gets right back..
<!doctype html>
<html ng-app="plunker">
<head>
<script data-require="angular.js#*" data-semver="1.2.0" src="http://code.angularjs.org/1.2.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng:controller="MainCtrl">
<table>
<thead style="font-weight: bold;">
<tr>
<td class="text-right" data-col-id="Value1">Value1</td>
<td class="text-right" data-col-id="Value2">Value2</td>
<td class="text-right" data-col-id="Value3">Value3</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td class="text-right" data-col-id="Value1">{{row.Value1}}</td>
<td class="text-right" data-col-id="Value2">{{row.Value2}}</td>
<td class="text-right" data-col-id="Value3">{{row.Value3}}</td>
</tr>
</tbody>
</table>
<p>Visible Columns:</p>
<br />
<div class="cbxList" ng-repeat="column in columnsTest">
<input type="checkbox" ng-model="column.checked" ng-change="columnToggled(column)"> {{column.id}}
</div>
</div>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.columnsTest = [{
id: 'Value1',
checked: true
}, {
id: 'Value2',
checked: true
}, {
id: 'Value3',
checked: true
}];
$scope.rows = [{
id: 1,
"Value1": 911,
"Value2": 20,
"Value3": 20
}, {
id: 2,
"Value1": 200,
"Value2": 20,
"Value3": 20
}];
$scope.columnToggled = function(column) {
$('[data-col-id="' + column.id + '"]').each(function() {
var element = this;
if ($(element).hasClass('ng-hide')) {
$(element).removeClass('ng-hide');
} else {
$(element).addClass('ng-hide');
}
});
};
//trigger update
window.setInterval(function() {
$scope.simulateUpdates($scope.rows[0]);
}, 5000);
$scope.simulateUpdates = function (row) {
var newRow =
{
id: 1,
"Value1": Math.floor(Math.random() * 100) + 1,
"Value2": Math.floor(Math.random() * 100) + 1,
"Value3": Math.floor(Math.random() * 100) + 1
}
updateRow(newRow);
$scope.$apply();
}
function updateRow(row) {
for (var i = 0; i < $scope.rows.length; i++) {
if ($scope.rows[i].id === row.id) {
$scope.rows[i] = row;
}
}
}
});
Here is a demo of my problem in a minor scale: http://plnkr.co/edit/1tGci7qX9ZFIk69uNfIf?p=preview (uncheck one of the columns)
You overcomplicate things a bit: your model seems to be pretty simple actually. The key is using templates to express it properly. That's how it might look like, for example:
<table>
<thead>
<tr>
<th class="text-right" ng-repeat="column in columnsTest"
ng-if="column.checked" ng-bind="column.id"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="column in columnsTest"
ng-if="column.checked" ng-bind="row[column.id]"></td>
</tr>
</tbody>
</table>
<p>Visible Columns:</p>
<br />
<div class="cbxList" ng-repeat="column in columnsTest">
<input type="checkbox" ng-model="column.checked">{{column.id}}
</div>
See? No need for that extra function: when you change the specific column checked attribute, it's automatically updated in all the corresponding views.
Demo.
I have fixed your code without using jQuery.
<table>
<thead style="font-weight: bold;">
<tr>
<th ng-repeat="column in columnsTest" class="text-right" data-col-id="column.id" ng-show="column.checked">
{{column.id}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td class="text-right" data-col-id="Value1" ng-show="columnsTest[0].checked">{{row.Value1}}</td>
<td class="text-right" data-col-id="Value2" ng-show="columnsTest[1].checked">{{row.Value2}}</td>
<td class="text-right" data-col-id="Value3" ng-show="columnsTest[2].checked">{{row.Value3}}</td>
</tr>
</tbody>
</table>
<div class="cbxList" ng-repeat="column in columnsTest">
<input type="checkbox" ng-model="column.checked">{{column.id}}
</div>
You don't need to bind the ng-change function to the input checkbox since you already assigned it the ng-model using two-way data-binding.
The following is the working :Plunker
Friends,
I'm using jQuery DataTables plugin. I'm doing the Server Side Processing with JSON datasource to fill the DataTable as showing in the example
Here's my code
HTML
<Table class="projectGrid DataTable display" id="tblList" width="100%">
<thead>
<tr>
<th align="center">
Created
</th>
<th align="center">
Assigned
</th>
<th align="center">
Stage
</th>
<th align="center">
Priority
</th>
<th align="center">
Status
</th>
</tr>
</thead>
<tfoot>
<tr>
<th align="center">
Created
</th>
<th align="center">
Assigned
</th>
<th align="center">
Stage
</th>
<th align="center">
Priority
</th>
<th align="center">
Status
</th>
</tr>
</tfoot>
<tbody>
<asp:Repeater ID="reptList" runat="server">
<ItemTemplate>
<tr>
<td align="center">
<%#Eval("CreatedBy")%>
</td>
<td align="center">
<%#Eval("AssignedTo")%>
</td>
<td align="center">
<%#Eval("Stage")%>
</td>
<td align="center">
<%#Eval("Priority")%>
</td>
<td align="center">
<%#Eval("Status")%>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</tbody>
</table>
JavaScript
<script type="text/javascript">
var data =
{
datatableConfig: {
"aaSorting": [],
"processing": true,
"serverSide": true,
"ajax": {
url: "~/IssueData.asmx/GetIssueList",
type: "POST"
},
"columns": [
{ "data": "0" },
{ "data": "1" },
{ "data": "2" },
{ "data": "3" },
{ "data": "4" }
]
}
}
$(data.datatable + ' tfoot th').each(function () {
var title = $(this).text();
if (!$(this).hasClass('hidden')) {
$(this).html('<input type="text" class="footerInput" style="width:' + ($(this).width() - 10) + 'px" placeholder="Filter ' + $.trim(title) + '" />');
}
});
// Apply Datatable
if ($(options.datatable).length) {
table = $(options.datatable).DataTable(options.datatableConfig);
}
// Apply the search
table.columns().every(function () {
var that = this;
$('input.footerInput', this.footer()).on('change', function () {
if (that.search() !== this.value) {
that.search(this.value).draw();
}
});
});
</script>
Everything is working fine, except Search. When I enter single letter in a Search, It raises 3-4 Ajax POST Requests. Any Idea why it processes more POST requets on single keypress event?
You can use below code to apply search so when user press 'enter' key ajax request is made to search :
// Apply the search
table.columns().every(function () {
var that = this;
$('input.footerInput', this.footer()).on('keyup', function (e) {
if (e.keyCode == 13 && $.trim(this.value) !== '') {
that.search(this.value).draw();
}
});
});