I have a modal react component that renders a table that iterates through an array of users/emails (waitList) and displays them in a tag. My goal is to only remove the first border-top attribute in the row (see image).
Here's a snippet of my component in case my description wasn't clear-
renderTableRows() {
const iter = [];
if (this.props.waitList !== null) {
this.props.waitList.map(applicant => {
iter.push(
<tr>
<td>{applicant.user.name}</td>
<td>{applicant.user.email}</td>
</tr>
);
});
}
return iter;
}
render() {
return (
<div>
<Modal show={this.state.waitListModalIsOpen}>
<Modal.Header>
WAIT LIST ({this.props.waitListCount})
</ Modal.Header>
<Modal.Body>
<table className={'table wait-list-table'}>
<tbody>
{this.renderTableRows()}
</tbody>
</table>
</ Modal.Body>
<Modal.Footer>
<Button onClick={() => { this.closeWaitListModal(); }}>Cancel</Button>
</ Modal.Footer>
</Modal>
</div>
);
}
}
I understand that because I am iterating each td here that nth-child will remove all borders for the supplied child parameter, rather than just the first in the list. Is there a way I can hide this border using CSS? If not, recommendations for how to improve my iteration logic in my React component is welcomed.
table tr td {border-top: solid gray 1px; }
table tr:first-child td {border-top: none;}
<table>
<tbody>
<tr>
<td>a</td>
<td>b</td>
</tr>
<tr>
<td>aa</td>
<td>bb</td>
</tr>
<tr>
<td>aaa</td>
<td>bbb</td>
</tr>
</tbody>
</table>
You could do something along the lines of this:
JS:
renderTableRows() {
const iter = [];
if (this.props.waitList !== null) {
this.props.waitList.map((applicant, index) => {
iter.push(
<tr>
<td className={index === 0 ? "no-border-top" : ""}>
{applicant.user.name}
</td>
<td>{applicant.user.email}</td>
</tr>
);
});
}
return iter;
}
CSS:
.no-border-top {
border-top: none;
}
You can also use inline styling like so:
renderTableRows() {
const iter = [];
const noBorderTopStyle = {
borderTop: "none"
}
if (this.props.waitList !== null) {
this.props.waitList.map((applicant, index) => {
iter.push(
<tr>
<td style={index === 0 ? noBorderTopStyle : null}>
{applicant.user.name}
</td>
<td>{applicant.user.email}</td>
</tr>
);
});
}
return iter;
}
Use first-child selector on your tr as follows:
tbody tr:first-child td{
border-top:0;
}
Related
How to set table row background-color with css pseudo class :has() only when button clicked and class "group-process" added to each row in tbody?
When I click button with id "group_processing_button" displays block with class "group-processing". Also when I click this button only rows which have class i[class$="fa-check-square"] must have background-color: #9e9; I mean this css style must work:
.table tbody tr[class$="group-process"]:has(td.no):has(i[class$="fa-check-square"]) {
background-color: #9e9;
}
Only when block with class "group-processing" displayed by button.
When I click and display off the block with class "group-processing", rows which have class i[class$="fa-check-square"] must have background-color: transparent, this style must not work:
.table tbody tr[class$="group-process"]:has(td.no):has(i[class$="fa-check-square"]) {
background-color: #9e9;
}
Thank You for help!
var $groupProcessingContainer = jQuery('.group-processing');
var $groupProcessingTable = jQuery('.table-order');
jQuery('#group_processing_button').click(function() {
var $rows = $groupProcessingTable.find('tbody tr');
$rows.each(function() {
var $row = jQuery(this);
if ($row.hasClass('group-process')) {
$row.removeClass('group-process');
} else {
$row.addClass('group-process');
}
});
$groupProcessingContainer.slideToggle();
});
tr td.no .group-check {
display: none;
}
tr.group-process td.no .group-check {
display: inline;
}
.table tbody tr[class$="group-process"]:has(td.no):has(i[class$="fa-check-square"]) {
background-color: #9e9;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<button type="button" class="btn btn-sm btn-info" id="group_processing_button">Group processing</button>
<div class="group-processing" style="display: none;">Block for filtering</div>
<table class="iblock table table-striped table-bordered table-hover table-order">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Supplier</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="no">1.<i class="fa group-check fa-check-square"></i></td>
<td>
item_name
</td>
<td>Supplier_name</td>
</tr>
<tr class="even">
<td class="no">1.<i class="fa fa-square-o group-check"></i></td>
<td>
item_name
</td>
<td>Supplier_name</td>
</tr>
</tbody>
</table>
I have the below sample html table definition.
<table id="myDynamicTable" class="table-striped" >
<thead class="ui-widget-header_custom dataTables_wrapper no-footer">
<tr id="uploadrow_0" class="">
<th style="white-space: nowrap;display: table-cell;width: 2px; text-align: center " class="text-left" >
Row#
</th>
<th style="white-space: nowrap;display: table-cell;text-align: center " class="text-left msr_d_col_widths_nationality">
Nationality
</th>
<th style="white-space: nowrap;display: table-cell; text-align: center " class="text-left">
No of Visitors
</th>
<th style="white-space: nowrap;display: table-cell;text-align: center " class="text-left msr_d_col_widths_remark">
Remarks
</th>
</tr>
</thead>
<tbody>
#if (Model.VisitDetails.Any())
{
foreach (var item in Model.VisitDetails)
{
#Html.Partial("VisitDetailsPartial", item);
}
}
else
{
item.RowId = 1;
item.NationalityList = ViewBag.NationalityList;
#Html.Partial("VisitDetailsPartial", item);
}
</tbody>
</table>
On the click of a button, the rows which are defined in asp.net MVC partial view are added to the table.
Button click
$(document).ready(function () {
var tableBody = $('#myDynamicTableDiseases tbody');
var url = '#Url.Action("Add", "Report")';
$('.btnAddRow').click(function () {
$.get(url, function (response) {
tableBody.append(response);
$('#myDynamicTableDiseases tbody tr').each(function (idx) {
$(this).children("td:eq(0)").html(idx + 1);
});
});
});
});
The "Add" action in "Report" control returns the "VisitDetailsPartial" as a new row added to the table.
Below is the VisitDetailsPartial definition.
#model SolutionName.ViewModel.VisitDetailsViewModel
<tr class="">
#using (Html.BeginCollectionItem("item"))
{
<td class="autoGenNumber" style="width: 5px" >
#if (Model == null)
{
var item = new VisitDetailsViewModel
{
NationalityList = ViewBag.NationalityList,
};
#Html.LabelFor(x => item.RowId, item.RowId.ToString(), new { style = "", #class = "autoGenNumber" })
}
else
{
#Html.LabelFor(x => Model.RowId, Model.RowId.ToString(), new { style = "", #class = "autoGenNumber" })
}
</td>
<td class="">
#Html.DropDownListFor(model => model.NationalityId, new SelectList(Model.NationalityList, "Value", "Text", Model.NationalityId), "Select", new { #id = "ddlNationalityList" })
</td>
<td class="">
#Html.TextBox("txtNumberOfVisits", Model.NumberOfVisits, new { id = "txtNumberOfVisits"})
</td>
<td class="">
#Html.TextBoxFor(x => Model.Remarks, new { id = "txtRemarks", Multiline = true})
</td>
}
</tr>
I'm trying to use the CSS below to change the background color in the first column of the dynamically added even table row but the CSS is not being applied.
.table-striped > tbody > tr:nth-of-type(even) td:first-child {
background-color: #e0f0ff;
}
If i apply the same to a table in whose rows are NOT coming from a partial view, the CSS works fine.
Not sure what i'm missing above.
Ok, i got it working by modifying the CSS as below though in my markup above, i cant seem to see why i consider to be column 1 is actually being treated as column 2.
This version works.
.table-striped > tbody > tr:nth-of-type(even) > td:nth-child(2) {
background-color: #e0f0ff;
}
Hi i m using in my project a simple functionality.
i have a table and some data is fetch data in json file .
Data is coming and if i click to name than edit mode is on if i blur than hide the edit mode and show the view mode is fine i have do this .
now i have a update button if i click to this button than only updated data in insert next row how to do this please check to this and help me .
My code is this
var myApp = angular.module('myApp', []);
myApp.controller('myCntrl', function($scope, $http){
$http.get('js/list.json').success(function(data){
$scope.emplyeList = data;
});
$scope.updateSec= function(employe){
alert("Rohit");
}
});
.click{
cursor: pointer;
text-decoration: underline;
}
.normal-table{
width: 50%;
border-collapse: collapse;
}
.normal-table th{
border: solid 2px rgba(0,0,0,0.1);
}
.normal-table td{
border: solid 2px rgba(0,0,0,0.1);
text-align: center;
padding: 10px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCntrl">
<body>
<table class="normal-table">
<thead>
<tr>
<th>Name</th>
<th>ID</th>
<th>Address</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="employe in emplyeList">
<td>
<div ng-show="!data" ng-click="data=true" class="click">{{employe.name}}</div>
<div ng-show="data"><input ng-blur="data=false" type="text" ng-model="employe.name" /></div>
</td>
<td>
<div ng-show="!data">{{employe.ID}}</div>
<div ng-show="data"><input type="text" ng-model="employe.ID" /></div>
</td>
<td>
<div ng-show="!data">{{employe.add}}</div>
<div ng-show="data"><input type="text" ng-model="employe.add" /></div>
</td>
</tr>
<tr>
<td colspan="3">
<button ng-click="updateSec(employe)">Update</button>
</td>
</tr>
</tbody>
<tbody>
<tr ng-repeat="updatEm in employe">
<td>{{updatEm.name}}</td>
<td>{{updatEm.ID}}</td>
<td>{{updatEm.add}}</td>
</tr>
</tbody>
</table>
</div>
My Json file is
[
{"name":"Rohit", "ID":"5Rt", "add":"Delhi"},
{"name":"Kiran", "ID":"4Kn", "add":"UP"},
{"name":"Abhay", "ID":"3Ay", "add":"HR"},
{"name":"Rahul", "ID":"2Rl", "add":"UK"}
]
HTML
<tr ng-repeat="employe in emplyeList" ng-click="updateSec(employe)">
</tr>
<tr>
<td colspan="3">
<button ng-click="showData()">Update</button>
</td>
</tr>
<tr ng-if="showEmployee" ng-repeat="employe in modifiedEmplyee">
<td>{{employe.name}}</td>
<td>{{employe.ID}}</td>
<td>{{employe.add}}</td>
</tr>
Script
//Display list
$scope.showEmployee = false;
//Create an array to hold updated employee
$scope.modifiedEmplyee = [];
//Set updated field to identify updated employee
$scope.updateSec = function (employe) {
employe.updated = true;
$scope.showEmployee = false;
}
//Show data and copy modilfied list
$scope.showData = function () {
$scope.showEmployee = true;
$scope.modifiedEmplyee = [];
for(var i = 0; i< $scope.emplyeList.length; i++)
{
var emp = $scope.emplyeList[i];
if(emp.updated && emp.updated == true){
$scope.modifiedEmplyee.push(emp);
}
}
}
DEMO
I want to highlight a table cell (td) instead of the entire row when a particular row is clicked.
This code below highlights a row in yellow. I would like to highlight the Name column when the row is selected instead.
$(function() {
Thing = function(id, name, selected) {
var self = this;
self.ID = id,
self.Name = name,
self.isSelected = ko.computed(function() {
return selected() === self;
});
};
function viewModel() {
var self = this;
self.model = {};
self.model.CurrentDisplayThing = ko.observable();
self.model.Things = ko.observableArray(
[
new Thing(1, "Thing 1", self.model.CurrentDisplayThing),
new Thing(2, "Thing 2", self.model.CurrentDisplayThing),
new Thing(3, "Thing 3", self.model.CurrentDisplayThing)
]);
self.selectThing = function(item) {
self.model.CurrentDisplayThing(item);
};
}
ko.applyBindings(new viewModel());
});
JS Fiddle Demo
Just move your css data-binding to the td level instead of the tr level:
Demo JS Fiddle
Your old code:
<tr data-bind="click: $root.selectThing, css: { selected: isSelected } ">
<td data-bind="text: ID"></td>
<td data-bind="text: Name"></td>
</tr>
Becomes:
<tr data-bind="click: $root.selectThing ">
<td data-bind="text: ID"></td>
<td data-bind="text: Name, css: { selected: isSelected }"></td>
</tr>
Also runs in Stack Snippet below with latest version of Knockout, so it doesn't appear to be a versioning issue based on your comment.
$(function() {
Thing = function(id, name, selected) {
var self = this;
self.ID = id,
self.Name = name,
self.isSelected = ko.computed(function() {
return selected() === self;
});
};
function viewModel() {
var self = this;
self.model = {};
self.model.CurrentDisplayThing = ko.observable();
self.model.Things = ko.observableArray(
[
new Thing(1, "Thing 1", self.model.CurrentDisplayThing),
new Thing(2, "Thing 2", self.model.CurrentDisplayThing),
new Thing(3, "Thing 3", self.model.CurrentDisplayThing)
]);
self.selectThing = function(item) {
self.model.CurrentDisplayThing(item);
};
}
ko.applyBindings(new viewModel());
});
.selected { background-color: yellow; }
thead tr {
border:1px solid black;
background:lightgray;
}tbody tr {
border:1px solid black;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="if:model.CurrentDisplayThing">
Display: <span data-bind="text: model.CurrentDisplayThing().ID"></span>
</div>
<table class="defaultGrid">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody data-bind="foreach: model.Things">
<tr data-bind="click: $root.selectThing ">
<td data-bind="text: ID"></td>
<td data-bind="text: Name, css: { selected: isSelected}"></td>
</tr>
</tbody>
</table>
Try this:
CSS
tbody tr.selected > td:last-child{
background-color: yellow;
}
JSFIDDLE
Try the following code, it works.
<table id="tableID" border="1">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody >
<tr >
<td >1</td>
<td >2</td>
</tr>
</tbody>
</table>
javaScript:
var table = document.getElementById("tableID");
if (table != null) {
for (var i = 0; i < table.rows.length; i++) {
for (var j = 0; j < table.rows[i].cells.length; j++)
table.rows[i].cells[j].onclick = function () {
this.style.backgroundColor = "yellow";
};
}
}
Maybe the follwing code can help you:
$("table > thead > tr > th").css({"background":"#D3D3D3"});
$("table > thead > tr :nth-child("+($(this).index() + 1) +")").css({"background":"RED"});
This is my code:
<html>
<style>
.left-info
{
font-size:14px;
font-family:Tahoma, Helvetica, sans-serif;
color:#1A5B71;
font-weight:bold;
text-align:right;
}
.right-info
{
font-size:14px;
font-family:Tahoma, Helvetica, sans-serif;
color:#FFFFFF;
font-weight:bold;
text-align:left;
}
</style>
<body>
<table border="1">
<colgroup>
<col class="left-info" />
<col class="right-info" />
</colgroup>
<tr>
<td>3476896</td>
<td>My first HTML</td>
</tr>
<tr>
<td>5869207</td>
<td>My first CSS</td>
</tr>
</table>
</body>
</html>
But, it is showing simple table. Need help !!
Look here
http://www.w3.org/TR/CSS21/tables.html#columns
You can only set border, background, width and visibility with cols
edit
According to MDN, the only allowed attribute on <col> is span. All others are deprecated.
edit
jQuery solution
With this little jQuery snippet you can copy all the class names from the col tags to the corresponding td tags
It works even with colspan in both coland td tags as well as with nested tables.
Example here as jsfiddle
JavaScript
$(document).ready(function() {
var find_TDs_at_COL = function(table, col) {
var ret = [];
$(table).children('tbody').children('tr').each(function() {
var col2 = 0;
$(this).children('td,th').each(function() {
oldCol2 = col2;
if ($(this).attr('colspan')) {
col2 += parseInt($(this).attr('colspan'));
} else {
col2++;
}
if (oldCol2 <= col && col2 > col) {
ret.push(this);
}
})
})
return $(ret);
}
$('table > colgroup').each(function() {
var $table = $(this).parent();
var col = 0;
$(this).children('col').each(function() {
var oldCol = col
if ($(this).attr('colspan')) {
col += parseInt($(this).attr('colspan'))
} else {
col++;
}
for (var i = oldCol; i < col; i++) {
find_TDs_at_COL($table, i).addClass($(this).attr('class'))
}
})
})
})
console.clear()
$(document).ready(function() {
"use strict";
var find_TDs_at_COL = function(table, col) {
var ret = [];
$(table).children('tbody').children('tr').each(function() {
var col2 = 0;
$(this).children('td,th').each(function() {
var oldCol2 = col2;
if ($(this).attr('colspan')) {
col2 += parseInt($(this).attr('colspan'));
} else {
col2++;
}
if (oldCol2 <= col && col2 > col) {
ret.push(this);
}
})
})
return $(ret);
}
$('table > colgroup').each(function() {
var $table = $(this).parent();
var col = 0;
$(this).children('col').each(function() {
var oldCol = col
var that = this
if ($(this).attr('colspan')) {
col += parseInt($(this).attr('colspan'))
} else {
col++;
}
for (var i = oldCol; i < col; i++) {
find_TDs_at_COL($table, i)
.addClass($(this).attr('class'))
// copy style as well
// .each(function() {
// const [ ...style ] = that.style
// for ( let r of style ) {
// this.style[r] = that.style[r]
// }
//})
}
})
})
})
.left-info
{
font-size:14px;
font-family:Tahoma, Helvetica, sans-serif;
color:#1A5B71;
font-weight:bold;
text-align:right;
}
.right-info
{
font-size:14px;
font-family:Tahoma, Helvetica, sans-serif;
color:#00FFFF;
font-weight:bold;
text-align:left;
}
.extra-info {
font-size:14px;
font-family:Tahoma, Helvetica, sans-serif;
color:#ff0000;
font-style: italic;
text-align:right;
}
.additional-info {
font-size:10px;
font-family:Tahoma, Helvetica, sans-serif;
color:#ffdd00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<colgroup>
<col class="left-info" />
<col class="right-info" />
<col class="extra-info" colspan="3"/>
<col class="additional-info"/>
<col />
</colgroup>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>C</th>
<th>C</th>
<th>D</th>
</tr>
<tr>
<td>3476896</td>
<td>My first HTML</td>
<td></td>
<td>Extra</td>
<td>Yes</td>
<td>Add</td>
</tr>
<tr>
<td>5869207</td>
<td>My first CSS</td>
<td>Ugh</td>
<td colspan="2"></td>
<td>Don't trust</td>
</tr>
<tr>
<td>54379</td>
<td>My first JS</td>
<td colspan="2">Trust</td>
</tr>
</table>
VanillaJS solution
{
"use strict";
document.addEventListener('DOMContentLoaded', e => {
Array.from(document.querySelectorAll('table > colgroup')).forEach(cg => {
const table = cg.parentElement
let col = 0
Array.from(cg.querySelectorAll(':scope > col')).forEach(c => {
const oldCol = col
if (c.getAttribute('colspan')) {
col += +c.getAttribute('colspan')
} else {
col++
}
for (let i = oldCol; i < col; i++) {
find_TDs_at_COL(table, i).forEach(el => {
Array.from(c.classList).forEach(c => el.classList.add(c))
})
}
})
})
})
const find_TDs_at_COL = (table, col) => {
let ret = [];
Array.from(table.querySelectorAll(':scope > tbody > tr')).forEach(tr => {
let col2 = 0
Array.from(tr.querySelectorAll(':scope > td, :scope > th')).forEach(tc => {
const oldCol2 = col2
if (tc.getAttribute('colspan')) {
col2 += +tc.getAttribute('colspan')
} else {
col2++
}
if (oldCol2 <= col && col2 > col) {
ret.push(tc);
}
})
})
return ret
}
}
.left-info
{
font-size:14px;
font-family:Tahoma, Helvetica, sans-serif;
color:#1A5B71;
font-weight:bold;
text-align:right;
}
.right-info
{
font-size:14px;
font-family:Tahoma, Helvetica, sans-serif;
color:#00FFFF;
font-weight:bold;
text-align:left;
}
.extra-info {
font-size:24px;
font-family:Tahoma, Helvetica, sans-serif;
color:#ff0000;
font-style: italic;
text-align:right;
}
.additional-info {
font-size:10px;
font-family:Tahoma, Helvetica, sans-serif;
color:#ffdd00;
}
.shadow {
text-shadow: 2px 2px 0 black
}
.info {
text-decoration: overline;
}
<table border="1">
<colgroup>
<col class="left-info" />
<col class="right-info shadow info" />
<col class="extra-info" colspan="3"/>
<col class="additional-info"/>
<col />
</colgroup>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>C</th>
<th>C</th>
<th>D</th>
</tr>
<tr>
<td>3476896</td>
<td>My first HTML</td>
<td></td>
<td>Extra</td>
<td>Yes</td>
<td>Add</td>
</tr>
<tr>
<td>5869207</td>
<td>My first CSS</td>
<td>Ugh</td>
<td colspan="2"></td>
<td>Don't trust</td>
</tr>
<tr>
<td>54379</td>
<td>My first JS</td>
<td colspan="2">Trust</td>
</tr>
</table>
<br><hr><br>
<table border="1">
<colgroup>
<col class="right-info" />
<col class="left-info" />
<col class="additional-info"/>
<col class="extra-info shadow" colspan="3"/>
<col />
</colgroup>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>C</th>
<th>C</th>
<th>D</th>
</tr>
<tr>
<td>3476896</td>
<td>My first HTML</td>
<td></td>
<td>Extra</td>
<td>Yes</td>
<td>Add</td>
</tr>
<tr>
<td>5869207</td>
<td>My first CSS</td>
<td>Ugh</td>
<td colspan="2"></td>
<td>Don't trust</td>
</tr>
<tr>
<td>54379</td>
<td>My first JS</td>
<td colspan="2">Trust</td>
</tr>
</table>
Although the answer given here is about a year old at this point, I thought I'd just point out that you can easily do this with very simple CSS
Instead of trying to give the class to every td in its column, you can simply target them like this:
td:first-child{
color: #1A5B71;
text-align: right;
}
td:last-child{
color: #FFFFFF;
text-align: left;
}
Using JavaScript to complete this task is complete overkill
I've written a small jQuery script for this that applies the class to every th and td element in the colspans table.
Try it here
JavaScript:
$(function () {
$('colgroup').each(function () {
var $colgroup = $(this)
var classes = $colgroup.children().map(function () { return $(this).attr('class') })
$colgroup.siblings().children('tr').each(function () {
var col = 0
$(this).children().each(function () {
var $child = $(this)
$child.addClass(classes[col])
col += parseInt($child.attr('colspan')) || 1
})
})
$colgroup.remove()
})
})
The script isn't complicated, but here are the steps:
For every colgroup
cache the classnames that the cols have
For every tr in the same table
set a var col to 0
For every child of tr (ths and tds)
add a class, selected with col
increment col by its colspan attribute or 1 if it isn't present, so that at the next iteration, the script will know what class to select
Remove the colgroup altogether, because you could, for example, have a background that doens't have an opacity of 1, which would result in your ths and tds having a background with the wrong opacity.
I cache $(this) a couple of times, because it is faster to cache jQuery objects than calling $() everytime you want to select an element.