I am working on an accounts page that lists transactions (credits and debits).
I would like the user to be able to click on a table row and it expands showing more information.
I am using Twitter bootstrap and have looked over the documentation and this is the result I have
<table class="table table-striped" id="account-table">
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Description</th>
<th>Credit</th>
<th>Debit</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
<tr data-toggle="collapse" data-target="#demo1" data-parent="#account-table" class="">
<td>1</td>
<td>05 May 2013</td>
<td>Credit Account</td>
<td class="text-success">$150.00</td>
<td class="text-error"></td>
<td class="text-success">$150.00</td>
<div id="demo1" class="demo out collapse">Demo1</div>
</tr>
See:
http://jsfiddle.net/2Dj7Y/
The only issue is that it displays the "dropdown information" in the wrong place, I would like to add in a new row, instead of printing it at the top of the table
I have also tried adding in a new table row (which just displays the row, and no collapse action (only applied to the first row)
<tr data-toggle="collapse" data-target="#demo1" data-parent="#account-table" >
<td>1</td>
<td>05 May 2013</td>
<td>Credit Account</td>
<td class="text-success">$150.00</td>
<td class="text-error"></td>
<td class="text-success">$150.00</td>
<tr id="demo1" class="demo out collapse">
<td>1</td>
<td>05 May 2013</td>
<td>Credit Account</td>
<td class="text-success">$150.00</td>
<td class="text-error"></td>
<td class="text-success">$150.00</td>
</tr>
</tr>
See http://jsfiddle.net/ypuEj/
I'm not sure you have gotten past this yet, but I had to work on something very similar today and I got your fiddle working like you are asking, basically what I did was make another table row under it, and then used the accordion control. I tried using just collapse but could not get it working and saw an example somewhere on SO that used accordion.
Here's your updated fiddle:
http://jsfiddle.net/whytheday/2Dj7Y/11/
Since I need to post code here is what each collapsible "section" should look like ->
<tr data-toggle="collapse" data-target="#demo1" class="accordion-toggle">
<td>1</td>
<td>05 May 2013</td>
<td>Credit Account</td>
<td class="text-success">$150.00</td>
<td class="text-error"></td>
<td class="text-success">$150.00</td>
</tr>
<tr>
<td colspan="6" class="hiddenRow">
<div class="accordion-body collapse" id="demo1">Demo1</div>
</td>
</tr>
Expanding on Tony's answer, and also answering Dhaval Ptl's question, to get the true accordion effect and only allow one row to be expanded at a time, an event handler for show.bs.collapse can be added like so:
$('.collapse').on('show.bs.collapse', function () {
$('.collapse.in').collapse('hide');
});
I modified his example to do this here: http://jsfiddle.net/QLfMU/116/
If you're using Angular's ng-repeat to populate the table hackel's jquery snippet will not work by placing it in the document load event. You'll need to run the snippet after angular has finished rendering the table.
To trigger an event after ng-repeat has rendered try this directive:
var app = angular.module('myapp', [])
.directive('onFinishRender', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
});
}
}
}
});
Complete example in angular:
http://jsfiddle.net/ADukg/6880/
I got the directive from here:
Use AngularJS just for routing purposes
All the other answers address previous versions of Bootstrap. To implement this in the latest version -- Bootstrap 5 -- check out this link.
Related
I am trying to highlight a table row if it has a tick (check mark) in one of the td’s. I am using the jQuery code below, but it will not find a td with a html symbol such as a tick (check mark). It makes no difference if I use .text() or .html(). The code works as expected if I use any other criteria such as text or numbers, but not with html symbols. Is there away round this?
$('#farm td').filter(
function(t) {
if ($(this).text() == "✓") {
$(this).closest('tr').css('background-color', 'Yellow');
return;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="farm" border="1">
<tr>
<th>One</th>
<th>Two</th>
</tr>
<tr>
<td>Cat</td>
<td>Duck</td>
</tr>
<tr>
<td>Pig</td>
<td>✕</td>
</tr>
<tr>
<td>✓</td>
<td>Bull</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
</tr>
</table>
You just need to check for the actual character (✓). jQuery acts on rendered HTML, not markup. I determined this by setting a breakpoint on the line with text() in it and looking at the values that came through.
Also:
.each() makes more sense to me here
no need to return anything in the function
no need to pass in anything (t)
console logs are far nicer than alerts for debugging
$('#farm td').each(function() {
if ($(this).text() == "✓") {
$(this).closest('tr').css('background-color', 'Yellow');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="farm" border="1">
<tr>
<th>One</th>
<th>Two</th>
</tr>
<tr>
<td>Cat</td>
<td>Duck</td>
</tr>
<tr>
<td>Pig</td>
<td>✕</td>
</tr>
<tr>
<td>✓</td>
<td>Bull</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
</tr>
</table>
Mohamed-Yousef suggested a great refinement using an internal selector:
$('#farm td:contains("✓")').closest('tr').css('background-color', 'Yellow');
It's a slightly different selector as it would also match ✓ blah, for example, but maybe it's useful in your case.
https://api.jquery.com/contains-selector/
I'm trying to create a table in Angular with a dynamic number of columns and rows. I've found this easy to accomplish using the HTML table element by doing something like this:
<table class="html-table">
<tr class="headers">
<th>Name</th>
<th>Age</th>
<th>Sex</th>
<th *ngIf="columns == 4">Species</th>
</tr>
<tr>
<td>Ryan</td>
<td>30</td>
<td>M</td>
<td *ngIf="columns == 4">Human</td>
</tr>
</table>
In this example there might be some button that toggles the value of columns between 3 and 4.
Every explanation I have looked at online involves changing CSS variables, which seems like a somewhat hacky way to accomplish something that should be simple. Is there some way I can specify that something should be a new column in CSS grid rather than that having to specify the number of columns in grid-template-columns?
In Angular you can use ng-repeat to have a dynamic table
A typical example could be
<table ng-table="tableParams" class="table table-striped">
<tr ng-repeat="data in datas">
<td title="Title_Of_First_Variable">{{data.variable1}}</td>
<td title="Title_Of_Second_Variable">{{data.variable2}}</td>
<td title="Title_Of_Third_Variable">{{data.variable3}}</td>
...
</tr>
</table>
Of course with your controller you should pass your dynamic data into the correct $scope, in this case should be $scope.datas (usually an object)...maybe something like this, using NodeJS:
$http.post('route_of_your_method')
.success(function (result) {
$scope.datas = result;
})
.error(function (err) {
...
});
I explained fastly but i hope this is enough
What would be the best way to dynamically add an HTML element, such as another column onto a basic HTML table?
I want to have a button below the table, and if the user were to click the button, the event would add the same amount of rows already in the table and add another column. I would want to support about 5 extra columns being added to the table.
Here's my HTML table as of right now:
<table>
<thead>
<tr>
<th id="row-tag"></th>
<th id="option-column">Option 1</th>
</tr>
</thead>
<tbody>
<tr>
<td id="row-tag">P</td>
<td id="option-column">{{ p }}</td>
</tr>
<tr id="row-tag">
<td>
<app-a-p (saveButtonClick)="toggleAP($event)"
[modModalValues]="modModalValues">
</app-a-p>
</td>
<td id="option-column">
<div class="input-group input-group-sm">
$<input
*ngIf="toggleAP==true"
type="text"
name="aP"
size="10"
disabled
value=""
/>
<input
*ngIf="toggleAP==false"
type="text"
name="aP"
size="10"
[ngModel]="con.pA"
(ngModelChange)="con.pA = $event" appFormatP
(blur)="checkAP($event.target.value);
inputTracker.addModifiedValue('Option 1', $event.target.value)"
/>
</div>
</td>
</tr>
<tr>
<td id="row-tag">L</td>
<td id="option-column">${{l}}</td>
</tr>
<tr>
<td id="row-tag">R</td>
<td id="option-column">${{r}}</td>
</tr>
</tbody>
</table>
I think in Angular, you define table based on your data. for example, you have fields array defining columns, and data array defines the what's actually in the table.
<table >
<thead>
<tr>
<th *ngFor='let key of this.fields'>{{key}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let row of this.data ' >
<td scope="row" *ngFor='let key of this.fields'> {{row[key]}} </td>
</tr>
</tbody>
</table>
when you need a new column, just push a new field into fields. like
fields.push('newcolumn');
when you need a new row, just do:
data.push({col1: '', col2:'', newcolumn: ''});
Look into the insertRow() and insertCell() functions in JavaScript. This alongside an onClick function that you write will let you edit the table.
A good way of generating a table on UI when using angular would be to use 2D-array (row*column) use can have a button using which you can dynamically add values to this array and have another row/column to the table.
Im trying to figure out if its possible to get the width of the parent my directive is going to be placed in.
Keeping it simple I have some directive my-directive which Im placing inside of a table:
<table>
<tr>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
<td><my-directive ..../></td>
</tr>
</table>
And inside my-directive Iwant to know the width of my parent <td> so I could display my content properly - with more or less data according to the width
Can it be done?
Update:
My HTML code:
<table class="table">
<thead>
<tr>
<td width="5%"></td>
<td width="5%"></td>
<td width="85%"></td>
</tr>
<tr>
<th>Col 5</th>
<th>Col 5</th>
<th>Col C 85</th>
</tr>
</thead>
<tbody>
<tr>
<td><trim value="Some value a"></trim></td>
<td>Some value b</td>
<td>Some value c</td>
</tr>
</tbody>
</table>
My directive:
angular.module('ui.directives', []).directive('trim', function() {
return {
restrict: 'E',
scope: {
value: '#'
},
template: "{{value | limitTo:6}}"
};
}
);
From within the template I can limit by a constant I define (or pass by, from outside. But I want to change that, to know myself, from within that directive if I should trim the text or not
Yes you can get the parent element using angular's jqlite, a subset of jquery in the link function. The link function is to provide the behavior to your directive, in this function you can get the directive element and modify it at run time according to your need.
angular.directive('myDirective', [function($document) {
return {
restrict:'E',
link: function(scope, element, attribute) {
var parent = element.parent();// will give an array
var parentWidth = parent[0].offsetWidth;
//modify/truncate your attribute.value depending upon the parentWidth.
}
}
}]);
I'm stumped and can't find the bug.
Angular is working, because it's reading my {{expressions}}, however, it's not replacing them with the content I'm expecting. It's simply removing them and blanks sit in their place.
I'm sure this issue is also tied in with, for some reason, my ng-repeat directive isn't working. (It's not repeating.)
Can someone help me out? I'm trying to draw a table. In this example, when it's done, it should have the respective "idea" posted multiple times across the same row, and each row should have a different "idea", as listed in the $scope.
It's creating one single row filled with blanks (rather than {{idea}} ).
index.html
<!doctype html>
<html ng-app="AppName">
<head>
<link rel="stylesheet" type="text/css" href="styles/table.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
</head>
<body>
<div ng-controller="TableController">
<table>
<tr>
<td>
<table cellspacing="0">
<tr class="title_bar">
<td>Title</td>
<td>Rating</td>
<td>Votes</td>
<td>Comments</td>
<td>Post Date</td>
<td>Status</td>
</tr>
</table>
</td>
</tr>
<div ng-repeat="idea in ideas">
<tr style="color: white">
<td>{{idea}}</td>
<td>{{idea}}%</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
</tr>
</div>
</table>
</div>
<script src="scripts/controllers/TableController.js"></script>
</body>
</html>
TableController.js
var app = angular.module('AppName', []);
app.controller('TableController', ['$scope',function($scope){
$scope.ideas = [
'wow',
'cool',
'so nice',
'amazing',
'please work'
];
}]);
I'm probably missing something obvious but I appreciate any help you could give me.
Edit: Whoops, guess I need to brush up on my HTML basics.
Well, your HTML layout looks pretty strange. You shouldn't put <div> between <tr>
Try something like this:
<table>
<tr class="title_bar">
<td>Title</td>
<td>Rating</td>
<td>Votes</td>
<td>Comments</td>
<td>Post Date</td>
<td>Status</td>
</tr>
<tr ng-repeat="idea in ideas">
<td>{{idea}}</td>
<td>{{idea}}%</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
</tr>
</table>
Fiddle demo
What you have is invalid HTML, so it's not rendering how you expect it to. You can't put a <div> inside a <table> and have it contain elements; you can include a <div> inside a <td> element but that doesn't really help you.
If you want to use ng-repeat in a table use it in <tr> or <tbody>
<tr ng-repeat="idea in ideas">
<td>{{idea}}</td>
........
</tr>
Try adding the ng-repeat directive to the td itself.
<tr>
<td ng-repeat="idea in ideas">{{idea}}</td>
</tr>
That should iterate through your $scope.ideas array.