I'm using ng-repeat to populate a table with data. This is how I have it setup:
<tbody>
<tr ng-repeat="client in clients | filter:x | filter:y |orderBy:predicate:!reverse | itemsPerPage: pageSize">
<td><input id="option-{{client.id}}" type="checkbox" value=""></td>
<td>{{client.lastname}}</td>
<td>{{client.firstname}}</td>
<td>{{client.status}}</td>
<td>{{client.phone}}</td>
<td>{{client.email}}</td>
</tr>
</tbody>
But I'm needing it to add a table row underneath the row it creates in the ng-repeat. Is that possible?
You can create a directive:
app.directive('addRow', function ($parse, $compile) {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
var template = attrs.addRow ? $parse(attrs.addRow)(scope) : '<tr><td>-</td></tr>';
elem.after(template);
$compile(elem.contents());
}
}
});
It adds passed row template after each element. If template is not passed it uses default template. It also compiles your template, so you can use all angular's stuff inside (eg. <td>{{variable}}</td>).
Example use:
<table>
<tbody>
<tr ng-repeat="item in [1,2,3,4]" add-row="'<tr><td>my template</td></tr>'">
<td>{{item}}</td>
</tr>
</tbody>
</table>
Here is jsfiddle: http://jsfiddle.net/aartek/52b6e/
You can allways add a row manually to the table like:
<tbody>
<tr ng-repeat="client in clients | filter:x | filter:y |orderBy:predicate:!reverse | itemsPerPage: pageSize">
<td><input id="option-{{client.id}}" type="checkbox" value=""></td>
<td>{{client.lastname}}</td>
<td>{{client.firstname}}</td>
<td>{{client.status}}</td>
<td>{{client.phone}}</td>
<td>{{client.email}}</td>
</tr>
<tr>
<td>Footer 1</>
<td>Footer 2</>
<td>Footer 3</>
<td>Footer 4</>
<td>Footer 5</>
<td>Footer 6</>
</tr>
</tbody>
Even better include it in a tfoot tag.
Or if you need two rows, you can do this:
<tbody ng-repeat="item in items">
<tr>
<td>{{item.row_one_stuff}}</td>
<td>{{item.more_row_one_stuff}}</td>
</tr>
<tr>
<td>{{item.row_two_stuff}}</td>
<td>{{item.more_row_two_stuff}}</td>
</tr>
</tbody>
Related
I've got a table with large number of columns, I need to be able to show and hide some columns by clickin checkbox. I've tried a lot of variations of ng-click--ng-show, $scope$watch and now I've trying to do this by addEventListener, but It doesn't work, nothing happend.
$scope.showTheItem = false;
function newFunction() {
document.getElementById("showTheItemEvent").addEventListener('checked', function () {
$scope.showTheItem = true;
$scope.digest();
});
}
and this is html:
<form ng-show="showTheForm"> // this is the form with checkboxes
<table onload="newFunction();">
<tr><td style="vertical-align:top" ng-repeat="item in superKeys" ng-if="$even"><input type="checkbox" id="showTheItemEvent" ng-true-value="checked" style="margin-left:3px; margin-right:15px"><label>{{localization.setLicTabs[locale][item]}}</label></td></tr>
<tr style="height:10px"></tr>
<tr><td style="vertical-align:top" ng-repeat="item in superKeys" ng-if="$odd"><input type="checkbox" id="showTheItemEvent" ng-true-value="checked" style="margin-left:3px; margin-right:15px"><label>{{localization.setLicTabs[locale][item]}}</label></td></tr>
</table>
</form>
<table>
<thead>
<tr>
<th ng-show="showTheItem">{{localization.setLicTabs[locale].VirtualType}}</th>
<th ng-show="showTheItem">{{localization.setLicTabs[locale].FarmName}}</th>
</tr>
</thead>
<tbody dir-paginate="item in dataObjHosts | filter:searchFilter | orderBy:orderListType:true | itemsPerPage: pageSize" pagination-id="POPaginatorServersSoft" current-page="currentPage" ng-click="setActiveState($event)">
<tr >
<td ng-show="showTheItem"><span ng-bind="dataObj[item][0].VirtualType"></span></td>
<td ng-show="showTheItem"><span ng-bind="dataObj[item][0].FarmName"></span></td>
</tr>
I have an object that looks like this:
[{'name':'Mike', 'age':21},
{'name':'Joe', 'age':24}]
My angular/html code looks like this:
<table class="Names">
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tbody>
<tr ng-repeat-start="value in msg.object">
<td rowspan="2">{{value.name}}</td>
</tr>
<tr ng-repeat-end ng-repeat="value in msg.object">
<td>{{value.age}}</td>
</tr>
</tbody>
</table>
The names show up fine and vertically how i'd want them to be in the table (first column),
but for each value of name i get both of the ages displaying instead of just the age for that person.
Can anyone guide me in the right direction here? I feel like I'm close but just picked up angular today so I'm new to it and ng-repeat.
You only need a simple row repeat with 2 cells in each row
<tr ng-repeat="value in msg.object">
<td>{{value.name}}</td>
<td>{{value.age}}</td>
</tr>
Your table format is wrong. Place the headers inside and do a ng-repeat to generate tr
DEMO
var app =angular.module('testApp', []);
app.controller('testCtrl', function($scope) {
$scope.users = [{'name':'Mike', 'age':21},
{'name':'Joe', 'age':24}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="testApp" ng-controller="testCtrl">
<table border="2">
<tr>
<td>name</td>
<td>age</td>
</tr>
<tr ng-repeat="user in users">
<td >{{user.name}}</td>
<td >{{user.age}}</td>
</tr>
</table>
</body>
Have a click event ng-click="$ctrl.toggleSub(state)" in the first row that is triggering the ng-if="showSubCat" event in the second row. This makes the second row appear when I click.
The problem is that it's causing all of the ng-repeat options to appear vs just the one I clicked.
For instance I'm getting:
Parent
- Child
- Child
Parent
- Child
- Child
I would like it to behave like this:
Parent
- Child
- Child
Parent
I only want the clicked ng-repeat options to expand accordingly. I've tried passing in the state object but am not having any luck. Any help would be greatly appreciated
toggleSub(state) {
this.$log.log(state)
this.$scope.showSubCat = !this.$scope.showSubCat
}
<tr md-row ng-repeat-start="state in country.states | orderBy: query.order">
<td md-cell><a ng-click="$ctrl.toggleSub(state)">{{state.name}}</a></td>
<td md-cell>-</td>
<td md-cell>{{state.totalCount}}</td>
</tr>
<tr md-row ng-repeat-end
ng-repeat="subcat in state.data | orderBy: 'subcategory'"
ng-if="showSubCat">
<td md-cell></td>
<td md-cell>{{subcat.subcategory}}</td>
<td md-cell>{{subcat.count}}</td>
<td md-cell>{{subcat.percentage}}</td>
</tr>
Make the showSubCat boolean a property of the state iteration object:
toggleSub(state) {
this.$log.log(state)
//this.$scope.showSubCat = !this.$scope.showSubCat
state.showSubCat = ! state.showSubCat;
}
<tr md-row ng-repeat-start="state in country.states | orderBy: query.order">
<td md-cell><a ng-click="$ctrl.toggleSub(state)">{{state.name}}</a></td>
<td md-cell>-</td>
<td md-cell>{{state.totalCount}}</td>
</tr>
<!-- BEFORE
<tr md-row ng-repeat-end
ng-repeat="subcat in state.data | orderBy: 'subcategory'"
ng-if="showSubCat">
-->
<!-- AFTER -->
<tr md-row ng-repeat-end
ng-repeat="subcat in state.data | orderBy: 'subcategory'"
ng-if="state.showSubCat">
<!-- -->
<td md-cell></td>
<td md-cell>{{subcat.subcategory}}</td>
<td md-cell>{{subcat.count}}</td>
<td md-cell>{{subcat.percentage}}</td>
</tr>
By making the showSubCat boolean part of the state iteration object, it will be different for each item in the parent ng-repeat.
here is demo: http://codepen.io/mafeifan/pen/PzrGRE?editors=1010
table1 is working,
in table2 I wrote a directive to render the td , but not work. I don't know why.
Html:
<table>
<tbody>
<tr ng-repeat="tr in vm.getTrs() track by $index">
<form-cell ng-repeat="cell in vm.getCellsByRow($index+1)">data</form-cell>
</tr>
</tbody>
</table>
JS:
App.directive('formCell', function(){
return {
replace: true,
template: '<td>td</td>'
}
});
if I change to
<table>
<tbody>
<tr ng-repeat="tr in vm.getTrs() track by $index">
<td ng-repeat="cell in vm.getCellsByRow($index+1)"><form-cell></form-cell></td>
</tr>
</tbody>
</table>
JS:
change the template to '<span>td</td>' in directive
it's working, I don't know why
You do need <th> or <td> in <tr> tags:
<html>
<body>
<table border="1">
<tr>
<td>renders</td>
<td>renders</td>
</tr>
<tr>
<div>renders outside the table</div>
<td>renders</td>
</tr>
</table>
</body>
</html>
It seems form-cell tag is not allowed inside tr tag and browser may do something wrong. Use the directive inside an attribute:
App.directive('formCell', function(){
return {
restrict: 'A', // <-- add the restriction
replace: true,
template: '<td>td</td>'
}
});
Like:
<td form-cell ng-repeat="cell in vm.getCellsByRow($index+1)">data</td>
Does angular have a onfilter method or onquery as you type to query through results:
for example:
<input type='text' ng-model='query'>
<table>
<tr>
<td>Name</td>
<td># of Enrollments</td>
</tr>
<tr ng-repeat='c in courses | filter:query' onfilter='someStuff()'>
<td>{{c.name}}</td>
<td>{{c.enrollmentLength}}</td>
</tr>
</table>
when I type in the input text the letter "a", I want it to call the someStuff() function.
The way you do this is with a watch inside your controller:
$scope.$watch('query', function(newval) {
// this will fire when query is changed
});
Filter can call a function instead of using an expression. Here's an example:
$scope.processQuery = function(course) {
// do some processing
};
<input type='text' ng-model='query'>
<table>
<tr>
<td>Name</td>
<td># of Enrollments</td>
</tr>
<tr ng-repeat='c in courses | filter:processQuery'>
<td>{{c.name}}</td>
<td>{{c.enrollmentLength}}</td>
</tr>
</table>