How to make bootstrap table columns resizable using react - javascript

I am using bootstrap table
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>Table heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Table cell</td>
</tr>
</tbody>
</table>
</div>
I want to make columns resizable using react

Try this code:
$(document).ready(function() {
//$("td,th")
$("td:first-child,td:nth-child(2),td:nth-child(3)")
.css({
/* required to allow resizer embedding */
position: "relative"
})
/* check .resizer CSS */
.prepend("<div class='resizer'></div>")
.resizable({
resizeHeight: false,
// we use the column as handle and filter
// by the contained .resizer element
handleSelector: "",
onDragStart: function(e, $el, opt) {
// only drag resizer
if (!$(e.target).hasClass("resizer"))
return false;
return true;
}
});
});
html,
body {
height: 100%;
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
padding: 0;
margin: 0;
}
.page-container {
margin: 20px;
}
table {
border-collapse: collapse;
width: 800px;
}
td,
th {
padding: 8px;
border: 1px solid silver;
}
th {
color: white;
background: #535353;
}
pre {
margin: 20px;
padding: 10px;
background: #eee;
border: 1px solid silver;
border-radius: 4px;
}
/*
this is important!
make sure you define this here
or in jQuery codef
*/
.resizer {
position: absolute;
top: 0;
right: -8px;
bottom: 0;
left: auto;
width: 16px;
cursor: col-resize;
}
<div class="page-container">
<h1>
jquery-resizable - Table Column Resizing
</h1>
<hr />
<p>
This example makes the first two columns of the table resizable.
</p>
<hr />
<table>
<thead>
<th>
col 1
</th>
<th>
col 2
</th>
<th>
col 3
</th>
<th>
col 4
</th>
</thead>
<tbody>
<tr>
<td>
Column 1
</td>
<td>
Column 2
</td>
<td>
Column 3
</td>
<td>
Column 4
</td>
</tr>
<tr>
<td>
Column 1
</td>
<td>
Column 2
</td>
<td>
Column 3
</td>
<td>
Column 4
</td>
</tr>
</tbody>
</table>
<hr />
<p>
To create resizable columns requires a bit of extra effort as tables don't have an easy way to create a drag handle that can be moved around.
</p>
<p>
To make columns resizable, we can add an element to the right of the column to provide the handle so we have a visual indicator for dragging. The table cell to resize is made <code>position:relative</code> and the injected element is <code>position: absolute</code> and pushed to the right of the cell to provide the drag handle. Dragging then simply resizes the cell.
</p>
<p>
In practice this means you need some CSS (or jquery styling) to force the injected styling and the logic to inject the element.
</p>
</div>

Resizable Column for react-bootstrap
Please see the code spinnet Code sandbox Resizable columns
uses 'column-resizer' npm package

Related

Expand last table column to fill container

How do you expand the last column of a table to fill the parent container without specifying a width for the container?
In this jsfiddle, I want the last column of the green table to fill the blue container. The width of the container should only be determined by its text.
.container{
background-color: #003388;
color: white;
display: inline-block;
}
table {
background-color: #008833;
color: white;
width:auto;
}
table tr td:last-child {
/* width:100%; */
}
Setting the width of the last td fills the entire page.
One possible approach is given below. It uses...
width: 100% rule (instead of width: auto) to make table fill the container
width: 1px; white-space: nowrap; combo trick to make all the columns define their width based on content width; without that rule it seems there's no simple way to override default behaviour of table-layout: auto sharing the whole width between columns equally.
max-width: 1px for the last column to ensure that inline-block container is not extended when that column grows, and text is wrapped instead
.container{
background-color: #003388;
color: white;
display: inline-block;
}
table {
background-color: #008833;
color: white;
width: 100%;
}
table td:not(:last-child) {
width: 1px;
white-space: nowrap;
}
table td:last-child {
max-width: 1px;
}
<div class="container">
long text long text long text long text long text long text
<table>
<tr>
<th>Product</th>
<th>Cardinality</th>
<th>Price per item</th>
</tr>
<tr>
<td>Apple</td>
<td>5</td>
<td>$2</td>
</tr>
<tr>
<td>Pear</td>
<td>3</td>
<td>$3</td>
</tr>
<tr>
<td>Sausage</td>
<td>10</td>
<td>$0.5</td>
</tr>
<tr>
<td>Pineapple</td>
<td>2</td>
<td>$8</td>
</tr>
<tr>
<td>Tomato</td>
<td>5</td>
<td>$1</td>
</tr>
<tr>
<td>Lightsaber</td>
<td>2</td>
<td>$99 999 999999999 99999999 99999999</td>
</tr>
</table>
</div>
Use fractional units fr to automatically take up the fraction you desire

How to get thead to the top on scrolling

I have problem creating sticky thead, my first 3 columns are fixed, rest of data is scrollable horizontal. I'm using jquery library for the sticky header, but position fixed is destroying my horizontal scroll, displaying all elements on the page.
I need sticky header to stay at the top, and at the same time horizontal scroll to work.
This is how it should look but with sticky header.
enter image description here
.horizontal-scroll-access-point {
display: block;
overflow-x: auto;
white-space: nowrap;
thead,tbody {
tr {
//First three elements are fixed
th,td {
&:nth-child(1), &:nth-child(2), &:nth-child(3){
background-color: white;
position:absolute;
text-align: center;
width: 100px;
padding-bottom: 10px;
z-index: 1;
}
&:nth-child(1) {
left: 0;
}
&:nth-child(2) {
left: 100px;
}
&:nth-child(3) {
left: 180px;
}
&:nth-child(4) {
padding-left: 300px;
}
}
}
}
}
<table class="table monthTable horizontal-scroll-access-point" ng-if="showActions()">
<thead class="sticky-header" sticky-divs sticky-divs-margin-top="50">
<tr>
<th class="heading" translate>SH_Area</th>
<th><span translate>AP_openClose</span></th>
<th translate>AP_maxUnits</th>
<th class="hour hover-cell" ng-repeat="hour in apu.hours" ng-click="changeUnitsAllByHourModal(hour)" on-finish-render>
<span ng-bind="hour | hourminute"></span>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="area in apu.areaHours">
<td ng-class="area.closed ? 'closed-cell' : 'hover-cell'" ng-click="changeUnitsAllByAccessPointModal(area)"><strong ng-bind="area.accessPointName"></strong></td>
<td class="open-close-cell">
<button type="button" class="btn btn-xs" ng-class="area.closed ? 'btn-danger' : 'btn-success'" ng-click="switchAreaStatus(area)" translate>{{ area.closed ? 'AP_closed' : 'AP_opened' }}</button>
</td>
<td class="gradient-cell-green" ng-bind="area.maxUnits">
</td>
<td ng-class="area.closed ? 'closed-cell' : 'hover-cell'" style="background-color: rgba(110, 170, 120, {{ hour.units / area.maUnits }})" ng-repeat="hour in area.hours" ng-click="changeUnitsModal(area, hour)">
<span ng-bind="area.closed ? '0' : hour.units"></span>
</td>
</tr>
</tbody>
</table>
You should only change the position of thead and then give each one of the th elements the same width as the width of the widest tr element in that column.
I assume your table is responsive. If so, write some js code to do so.

Table Row Description

table td {
border: 1px solid black;
}
<table>
<thead>
<th>
col1
</th>
<th>
col2
</th>
</thead>
<tbody>
<tr>
<td>field1</td>
<td>field2</td>
</tr>
<tr>
<td colspan="2">The above row is number 1</td>
</tr>
<tr>
<td>field3</td>
<td>field4</td>
</tr>
<tr>
<td colspan="2">The above row is number 2</td>
</tr>
</tbody>
</table>
What I want?
Well I have this HTML code.
I want to put row description but without the use of a useless TR tag.
Reason:
I am sorting on the basis of column.
The column value is integer , and when I sort, all row description comes at bottom and field rows are sorted on top. But the row description should be attached to parent row.
Question:
How to attach it, so that after sort the table on basis of column, rows descriptions don't get spoiled ?
It's not an amazing solution, but you can try in this way:
<table>
<thead>
<th>
col1
</th>
<th>
col2
</th>
</thead>
<tbody>
<tr>
<td>
field1
</td>
<td>field2</td>
<td>
<div>
description
</div>
</td>
</tr>
<tr>
<td>field3</td>
<td>field4</td>
<td>
<div>
description
</div>
</td>
</tr>
</tbody>
</table>
css:
table,
thead,
tbody,
tr {
display: block;
clear: both;
}
table {
width: 130px;
}
thead {
height: 30px;
}
th,
td {
width: 60px;
float: left;
height: 30px;
border: 1px solid black;
}
td {
margin-top: 30px;
}
tr {
height: 60px;
position: relative;
}
tr td:last-child {
width: 0;
overflow: hidden;
border: none;
}
div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 30px;
line-height: 30px;
text-align: center;
}
https://jsfiddle.net/4xbbzzg5/

CSS/HTML fixed position element resizing when browser resizing

This is my situation: I have a table with table header position: fixed and a couple of table body rows with their width set to 100%.
I am trying to make the header row resize properly when browser resizes, so its cells lines up body row cells.
How am I going to achieve that? (trying to make a position: fixed element react to browser size-change dynamically)
Here is my code. A very simple webpage
<html>
<head>
<style>
body{
width:100%;
}
thead{
position:fixed;
width:100%
overflow:visible;
align:center;
}
th{
border:2px solid black;
width:20%;
text-align:center;
}
td{
border:2px solid black;
width:20%;
text-align:center;
}
table{
width:80%;
margin:auto;
margin-top:50px;
}
.empty{
height:30px;
}
.empty td{
border:none;
}
</style>
</head>
<body>
<table>
<thead>
<th>
heading1;
</th>
<th>
heading2;
</th>
<th>
heading3;
</th>
<th>
heading4;
</th>
<th>
heading5;
</th>
<thead>
<tbody>
<tr class="empty">
<td></td><td></td><td></td><td></td><td></td>
</tr>
<tr>
<td>
cell1;
</td>
<td>
cell2;
</td>
<td>
cell3;
</td>
<td>
cell4;
</td>
<td>
cell5;
</td>
</tr>
<tr>
<td>
cell1;
</td>
<td>
cell2;
</td>
<td>
cell3;
</td>
<td>
cell4;
</td>
<td>
cell5;
</td>
</tr>
<tbody>
</table>
</body>
</html>
I'm developing a website tool using ASP.net currently. Any solution in ASP.net will be much appreciated.
The table element is not quite flexible as other in the html. Aparently the 'position:fixed' property will make the table ignore the width specification.
Therefore I tweaked your html and css a bit, in order to better divide the document's parts into header and content (section).
Basically, the header will contain only the table head.
The section will contain all the table rows and data in it. When scrolling, the header element will remain fixed and the table head cells in it (which has been given the exact same css attributes as the td cells) will remain perfectly aligned with their respective columns.
Hope this helps, good luck.
body {
width: 100%;
margin: 0px;
}
header {
width: 100%;
position: fixed;
margin-top: -30px;
}
section {
width: 100%;
margin-top: 50px;
}
table {
width: 80%;
margin: 0px auto;
}
header table th,
section table td {
width: 20%;
text-align: center;
border: 2px solid black;
}
<header>
<table>
<thead>
<th>heading1;</th>
<th>heading2;</th>
<th>heading3;</th>
<th>heading4;</th>
<th>heading5;</th>
</thead>
</table>
</header>
<section>
<table>
<tbody>
<tr>
<td>cell1;</td>
<td>cell2;</td>
<td>cell3;</td>
<td>cell4;</td>
<td>cell5;</td>
</tr>
<tr>
<td>cell1;</td>
<td>cell2;</td>
<td>cell3;</td>
<td>cell4;</td>
<td>cell5;</td>
</tr>
</tbody>
</table>
</section>

How to expand input field to the right in a header bar

I have a header bar with left-aligned items, center items and right-aligned items. In the center, I have multiple items and a search input field. When the search field gets focus, I'm making it wider by animating the width. Right now, because the items are centered, it's animating both left and right to center the content. How can I change this so it keeps the alignment and expands the width to the right?
I'm not using Bootstrap.
I'm currently using a table for the header bar content. I'm open to changing that, but if there's a way to do it with the current design, that would be preferred.
Here's a JSFiddle...click in the search field to see what's happening: https://jsfiddle.net/L60g0j64/1/
EDIT: I've updated it with the suggested solution below. My only issue is that the red container surrounding the input should expand also.
HTML/CSS/JS Snippet
$('#search').focus(function() {
$(this).val("");
$('#hidden_content').css('display','inline');
$(this).animate({width: '180px'}, 200);
});
$('#search').blur(function() {
$(this).val('Search');
$('#hidden_content').css('display','none');
$(this).animate({width: '120px'}, 200);
});
.header-navbar {
cursor: pointer;
white-space: nowrap;
background-color: #1f2127;
color: #cbcbcb;
min-width: 0;
text-overflow: ellipsis;
z-index: 299;
top: 0px;
left: 0px;
width: 100%;
height: 32px;
float: none;
position: fixed;
border-spacing: 0px;
}
td.cell-center {
text-align: center;
}
.cell-center table {
margin: 0 auto;
}
.header-table {
height: 32px;
border: none;
border-spacing: 0px;
}
td.header_rtd {
padding-right:12px;
}
td.header_ltd {
padding-left:12px;
}
.search-wrapper {
max-width: 124px;
background-color: red;
padding:4px;
}
.hidden_content{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="header-navbar" id="header" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<table class="header-table" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class='header_rtd'>left1</td>
<td class='header_rtd'>left2</td>
</tr>
</table>
</td>
<td width=100% class='cell-center'>
<table class="header-table" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class='header_rtd'>center</td>
<td class='header_rtd'>center</td>
<td><div class="search-wrapper">
<input class="search" id="search" style="width: 120px;" type="text" size="60" value="Search"/>
<div class='hidden_content' id='hidden_content'>
hidden content
</div>
</div></td>
</tr>
</tbody>
</table>
</td>
<td>
<table class="header-table" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class='header_ltd'>right1</td>
<td class='header_ltd'>right2</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
One quick solution would be to give the parent element a max-width equal to the initial width of the element. In doing so, the element will still be centered relative to the initial width because the input element's animated width will not effect the width of the parent element.
Updated Example
.search-wrapper {
max-width: 124px;
}
As a side note, you don't need jQuery/JS to animate the width, you can simply use a CSS transition along with the :focus pseudo-class.
Updated Example
.search-wrapper input.search {
transition: 1s width ease;
width: 120px;
}
.search-wrapper input.search:focus {
width: 180px;
}

Categories