How to specify class on a JSX node? - javascript

I have defined a class name for the table below (as part of JSX).
<table class="table">
However once its displayed the class is not set on the table:
var SearchResult = React.createClass({
render: function(){
return (
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
</tr>
</thead>
<tbody>...</tbody>
</table>
);
}
});
Instead the table shows as <table data-reactid=".0.1.0.0">...</table> in Chrome -> inspect element.

ReactJS uses the attribute className to avoid the use of a JavaScript reserved word.
<table className="table">

Related

Webcomponents based on <table>. Slot out of flow

I'm try create data-grid with "web component" based on TABLE. I'm use slot in TBODY to append new items. But TR rows rendered out of TBODY. I don't understand this behavior.
shadowDom disallow use TABLE and TR elements, possibly the reason is this, but using HTMLElement.appendChild() also doesn't work
<html>
<head>
<script type="module">
class DataGrid extends HTMLElement {
TEMPLATE_ID = '#data-grid';
constructor() {
super();
this._records = [];
}
connectedCallback() {
let shadow = this.attachShadow({mode: 'open'});
this._render(shadow);
}
_render(shadow){
let tmpl = document.querySelector(this.TEMPLATE_ID);
shadow.appendChild(tmpl.content.cloneNode(true));
//this.appendChild(tmpl.content.cloneNode(true)); //
}
}
customElements.define('data-grid', DataGrid);
</script>
</head>
<body>
<template id="data-grid">
<table border="1">
<thead>
<tr>
<th>id</th>
<th>time</th>
<th>voltage</th>
<tr>
</thead>
<tbody>
<slot></slot>
<tbody>
</table>
</template>
<data-grid>
<!-- need replaced to component
<grid-row time="" voltage="">
-->
<tr>
<td>1</td>
<td>123123123120</td>
<td>12.0</td>
</tr>
<tr>
<td>2</td>
<td>123123133324</td>
<td>12.1</td>
</tr>
<tr>
<td>1</td>
<td>123123122330</td>
<td>12.2</td>
</tr>
</data-grid>
</body>
From the <TR> documentation on MDN:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr
Permitted parents
<table> (only if the table has no child <tbody> element, and even
then only after any <caption>, <colgroup>, and <thead>
elements); otherwise, the parent must be <thead>, <tbody> or
<tfoot>
So
<data-grid>
<tr>
is not valid HTML
move (invalid) lightDOM to a <table> inside <data-grid> shadowDOM
note: attachShadow() both sets and returns this.shadowRoot for free
No need to create your own shadow variable.
psuedo code:
const table = this.shadowRoot.querySelector("TABLE");
this.querySelectorAll("TR").forEach(table.appendChild);

Trying to get data of the row clicked of the table react js

I am new to react,and making app where I want to get data of the row being clicked on a table,I don't whether this approach is good or not need suggestions
So far i have used onClick listener but when I click on a table , it gives me [object,object] in console.log(contract),I have also tried to to use loop to view data in it but it gives me [object,object],here's my below code:
<table id="mytable" cellSpacing="0" width="100%">
<thead>
<tr>
<th>CarName</th>
<th>DriverName</th>
<th>Date</th>
<th>Pickup</th>
</tr>
</thead>
<tbody>
{
this.state.contracts.map((contract,index)=>{
return(
<tr key={index} data-item={contract} onClick={this.contractdetails}>
<td>{contract.car} </td>
<td>{contract.driver}</td>
<td>{contract.date}</td>
<td>{contract.pickup}</td>
</tr>
)})
}
</tbody>
</table>
onClickfunction
contractdetails=(e)=>{
const contract=e.currentTarget.getAttribute('data-item');
console.log(contract)
};
Use JSON.stringify while setting the data-item
<tr key={index} data-item={JSON.stringify(contract)} onClick={this.contractdetails}>
And use JSON.parse() while accessing it.
contractdetails=(e)=>{
const contract= JSON.parse(e.currentTarget.getAttribute('data-item'));
console.log(contract)
};
A better way is to just set index as data-index and you can access it from the state
this.state.contracts.map((contract,index)=>{
return(
<tr key={index} data-index={index} onClick={this.contractdetails}>
...
...
}
You can access it like below
contractdetails=(e)=>{
let index = +e.currentTarget.getAttribute('data-index')
console.log(this.state.contracts[index]);
};

How to create table with multiline cells in React-bootstrap?

I want to create table where some cells contain several lines.
It's work if I do it:
<Table bordered>
<thead>
<tr>
<th>Date</th>
<th>Analysed ID</th>
<th>Analysed Name</th>
<th>Solve To change</th>
</tr>
</thead>
<tbody>
<tr>
<td rowSpan="3">Date</td>
</tr>
<tr>
<td>ID</td>
<td>Name</td>
<td>Decision</td>
</tr>
<tr>
<td>ID</td>
<td>Name</td>
<td>Decision</td>
</tr>
</tbody>
</Table>
I got it:
Table with multiline cell
And now I want to add my 3 "TR" tags in one component, because after I want use for-cycle to create many such components. But components must return content in one closed tag. I tried to contain my 3 "tr" in one parent "tr", but I got error. What can I do here?
It is not possible to create a React Component that returns three elements without wrapping them in another element, such as a div. Otherwise, you'll get the following error:
A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.
Your case here is a bit special, because you cannot have div's as the immediate child of table or tbody, so that's a problem...
What you can do however, is to create a class function that returns an array. Like this:
class MyApp extends React.Component {
getTr = () => {
return [
<tr key={0}>
<td rowSpan="3">Date</td>
</tr>,
<tr key={1}>
<td>ID</td>
<td>Name</td>
<td>Decision</td>
</tr>,
<tr key={2}>
<td>ID</td>
<td>Name</td>
<td>Decision</td>
</tr>
];
}
render() {
return (
<table className="table">
<thead>
<tr>
<th>Date</th>
<th>Analysed ID</th>
<th>Analysed Name</th>
<th>Solve To change</th>
</tr>
</thead>
<tbody>
{this.getTr()}
{this.getTr()}
{this.getTr()}
</tbody>
</table>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
You need to include tr tags in one div tag.
The right way to rowSpan is this:
var MyRow = React.createClass({
render: function () {
return (
<div>
<tr>
<td rowSpan="2">{this.props.item.date}</td>
<td>{this.props.item.data[0].id}</td>
<td>{this.props.item.data[0].name}</td>
<td>{this.props.item.data[0].solve}</td>
</tr>
<tr>
<td>{this.props.item.data[1].id}</td>
<td>{this.props.item.data[1].name}</td>
<td>{this.props.item.data[1].solve}</td>
</tr>
</div>
);
}
});
This is my working example: http://jsfiddle.net/andrea689/e33pd14L/

jquery how to get the class of parent element using chlid id?

I'm trying to alert the table(parent) class on click using the child id <th id="first">.
alert($(this).parent('tr').attr('class')); using this i have got the class of the <tr>.
But i want to get the class of the table when i use alert($(this).parent('table').attr('class')); it showing alert says undefined can someone help me how can the parent class using the child id
<table class="table table-bordered">
<thead>
<tr class="sample">
<th id="first">Firstname</th>
<th id="last">Lastname</th>
<th id="user">Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>arun </td>
<td>kumaresh</td>
<td>arun kumaresh</td>
</tr>
</tbody>
</table>
</div>
<script>
$(document).ready(function(){
$("#first").click(function(){
alert($(this).parent('tr').attr('class'));
});
});
</script>
Use .closest(TARGET_SELECTOR), For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
As .parent(SELECTOR), Get the parent of each element in the current set of matched elements, optionally filtered by a selector. (the parent() method traverses to the immediate parent)
$(document).ready(function() {
$("#first").click(function() {
alert($(this).closest('table').attr('class'));
});
$("#last").click(function() {
alert($(this).closest('thead').attr('class'));
});
$(".user").click(function() {
alert($(this).closest('table').attr('class'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table class="table table-bordered">
<thead class='ANY_CLASS'>
<tr class="sample">
<th id="first">Firstname</th>
<th id="last">Lastname</th>
<th class="user">Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>arun</td>
<td>kumaresh</td>
<td>arun kumaresh</td>
</tr>
</tbody>
</table>
simply use
alert($(this).closest('table').attr('class'));
refer closest here
https://api.jquery.com/closest/

React - table created incorrectly

I have a table in React where the user can add a variable number of rows.
<div>
<table class="table table-condensed table-bordered">
<tr>
<th>List Names</th>
<th>List Full Names</th>
<th>List Descriptions</th>
</tr>
{this.displayTableBody()}
</table>
<button style={{display:'inline-block'}} type="button"
className="btn btn-primary btn-small" onClick={this.addList}>
<span className="glyphicon glyphicon-plus"></span>
</button>
</div>
The rows are added by the displayTableBody method:
displayTableBody: function() {
var rows = Array.apply(null, Array(this.state.rowNr)).map(
function(e1, index) {
return <ListInput key={index} ref={index}/>
}
);
return(<div>{ rows }</div>);
}
One row is made of a ListInput component, which has the following render method:
render: function() {
return (
<tr>
<td>{this.displaySimpleInputField(
"List Name(<15 characters - A-Z, 0-9 and _ only)", this.setListName, "input")}</td>
<td>{this.displaySimpleInputField(
"List Full Name(<75 characters)", this.setListFullName, "input")}</td>
<td>{this.displaySimpleInputField(
"List Description(<225 characters)", this.setListDescription, "input")}</td>
</tr>
)
}
However, when I add a row, it is placed above the table header:
When working with tables, it is doubly important to write valid HTML, otherwise you get weird results like this. Specifically, the correct structure of a table is kinda like this:
<table>
<thead>
<tr><th></th></tr>
</thead>
<tbody>
<tr><td></td></tr>
</tbody>
</table>
Specifically, I'm pretty sure you can't place a div directly in table, like you do with your displayTableBody method. Try to rewrite your component to follow the HTML standard, I believe that's what causes your problem.
You are inserting div element directly inside a table, which is not correct html and it does break the layout, placing that element at the top of the table.
I would suggest restructuring your code as follows, and consider using times function from lodash:
displayTableBody: function() {
var rows = times(this.state.rowNr).map(
function(index) {
return <ListInput key={index} ref={index}/>
}
);
return(<tbody>{ rows }</tbody>);
}
And the table
<table class="table table-condensed table-bordered">
<thead>
<tr>
<th>List Names</th>
<th>List Full Names</th>
<th>List Descriptions</th>
</tr>
</thead>
{this.displayTableBody()}
</table>

Categories