How to override default style with ReactJSS? - css

I've implemented a table in my component:
<table className={classes.vehicleStatusTable}>
<thead>
<tr>
<th>MILEAGE</th>
<th>TREAD <FontAwesomeIcon icon={faEye}/></th>
<th>PRESSURE <FontAwesomeIcon icon={faEye}/></th>
<th>CLEAN</th>
</tr>
</thead>
<tbody>
<tr>
<td><span className={classes.unknown}>Unknown</span></td>
<td><HealthDot value={0} healthRange={null} size='large' /></td>
<td><HealthDot value={0} healthRange={null} size='large' /></td>
<td><HealthDot value={0} healthRange={null} size='large' /></td>
</tr>
</tbody>
</table>
Here's the applicable style in my styles file:
vehicleStatusTable: {
width: '600px',
'& thead': {
'& tr': {
'& th': {
fontWeight: 'normal',
textAlign: 'center'
}
}
},
'& tbody': {
'& tr': {
'& td': {
textAlign: 'center'
}
}
}
}
The 'center' alignment is appropriate for all of the columns except for the first one.
I've tried several different things to force the first column's alignment to be left but none work. Any ideas how I can fix this?

Why don't you add a class to every first element of first column ?
or try using CSS :nth-child() Selector
Using a formula (an + b). Description: a represents a cycle size, n is a counter (starts at 0), and b is an offset value.
Here, we specify a background color for all p elements whose index is a multiple of 3:
p:nth-child(3n+0) {
background: red;
}
you can see how people are using such selectors in these stackoverflow questions and answers
How to use pseudo selectors in material-ui?
How to get first child to work with JSS-Nested

The solution turns out to be quite simple. Here's an example:
<td style={{textAlign: 'left'}}

Related

React, typescript: Wrapping text inside table <td> doesn't work

I'd like to wrap the text inside a table cell. I tried "flex-wrap", "break-inside" and similar properties, nothing has worked so far.
It has already worked a few days ago, but I had to modify the table and afterwards it didn't wrap the text anymore. You can scroll along x axis to read the whole text which doesn't fit into the given box, even though I have no "overflow-x: scroll" for this Container or table.
Here's my code for the table:
const CommitMsgTable = ({ apiCommitsResponse }: CommitMsgTableProps) => {
let colorToggle = false;
return <div><table>{apiCommitsResponse.map(commit => {
colorToggle = !colorToggle;
return (
<tr>
<td style={{ whiteSpace: "nowrap", backgroundColor: colorToggle ? "lightgrey" : "white" }}>{processDate(commit.date)}</td>
<td style={{ backgroundColor: colorToggle ? "lightgrey" : "white" }}>
{commit.comment}
</td>
</tr>)
})}
</table></div>
}
This is the container, the table sits in:
export const CommitContent = styled.div`
width: 100%;
height: 250px;
padding: 0em;
border: 1px solid;
margin: 0em;
overflow-y: scroll;
`;
It is supposed to look something like this:
7 minutes ago
commit message, which is very long so the text has to wrap instead of adding a scroll bar underneath the table, so I only have to scroll along y axis. I don't want to scroll in x direction
...
...
Don't mind the "7 min ago" wrapping, it is fine in my real table.

table header background color change dynamically - Angular material

I have followed this example to implement the angular material table.
https://stackblitz.com/angular/jejeknenmgr?file=src%2Fapp%2Ftable-basic-example.ts
Here I changed the heading color using the below CSS code.
.mat-header-cell {
background: red;
}
I want to pass the heading color from the component instead of the static CSS way. Is there any way to change the heading color dynamically?
One of approach is to use Css Var and change variable value programatically in component.
Css
.mat-header-cell {
background: var(--background-color)
}
Component
export class AppComponent {
constructor()
changeColor() {
// set new color here
document.documentElement.style.setProperty(`--background-color`, 'red');
}
}
So when you change variable in css, browser will change value in .mat-header-cell class
Another approach is to use inline style background-color attribute on each mat-header-cell item.
In html
<ng-container matColumnDef="position">
<th mat-header-cell *matHeaderCellDef [style.background-color]="color"> No. </th>
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>
In component
export class TableBasicExample {
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = ELEMENT_DATA;
color = 'green'
changeColor() {
this.color = 'red';
}
}
Example

Gutenberg removing table tag on save

I am attempting to create a Gutenberg block to track exercise sets. I'm using a RichText component to allow users to edit default values in a table I pre-populate for them.
The block works well on the editor and, after saving, renders correctly in the post. However, when I reload the editor, I receive this error message: Block validation: Expected tag name 'thead', instead saw 'table'. It's almost like Gutenberg is stripping the table tag but leaving everything else.
Of course, that doesn't make sense, but I'm not sure what else it could be.
Here's my code, heavily edited for readability:
const { registerBlockType } = wp.blocks;
const { AlignmentToolbar, BlockAlignmentToolbar, BlockControls, RichText, useInnerBlockProps } = wp.blockEditor;
const { Component } = wp.element;
registerBlockType('bsd-strong-post/training-session', {
title: __('Strong Post', 'bsd-strong-post'),
description: __('Provides a short summary of a training session', 'bsd-strong-post'),
category: 'common',
icon: blockIcons.weight_lifting,
keywords: [
__('strength workout', 'bsd-strong-post'),
__('strong', 'bsd-strong-post'),
__('training', 'bsd-strong-post')
],
supports: {
html: true
},
attributes: {
/* ... */,
dayTemplateContent: {
type: 'string',
source: 'html',
selector: '.bsd-strong-post-training-template'
},
/* ... */
},
/* ... */
edit: class extends Component {
constructor(props) {
super(...arguments);
this.props = props;
/* ... */
this.dayTemplateHandler = this.dayTemplateHandler.bind(this);
this.onChangeBlockTemplate = this.onChangeBlockTemplate.bind(this);
}
/* ... */
dayTemplateHandler(new_val) {
const dayTemplateList = this.state.dayTemplateList;
let selectedDayTemplate = dayTemplateList.filter(item => {
return item.value == new_val;
})
if (selectedDayTemplate[0]['label']) {
this.props.setAttributes({
dayTemplateId: new_val,
dayTemplateName: selectedDayTemplate[0]['label']
});
}
this.getTemplate(new_val);
}
getTemplate(templateId) {
api.getDayTemplate(templateId)
.then((data) => {
if (!data.status || data.status == 0) {
return false;
};
if (!data.day_template) {
return false;
};
this.props.setAttributes({
dayTemplateContent: data.day_template.template_content
});
return data.day_template;
}).catch((err) => {
console.log('getTemplate caught error')
return false;
});
}
onChangeBlockTemplate(value) {
this.props.setAttributes({
dayTemplateContent: value
});
}
/* ... */
render() {
const { dayTemplateHandler, onChangeBlockTemplate, phaseControlHandler, programControlHandler, updateBlockAlignment, updateTextAlignment } = this;
const { block_alignment, dayTemplateId, dayTemplateName, dayTemplateContent, phaseId, phaseName, programAuthor, programId, programName, programPhases, text_alignment } = this.props.attributes;
/* ... */
return [
<InspectorControls>
<PanelBody title={ __('Basics', 'bsd-strong-post') }>
<SelectControl
label={ __('Day', 'bsd-strong-post') }
help={ __('The training session (e.g., Day One)', 'bsd-strong-post') }
value={ dayTemplateId }
options={ this.state.phaseTemplates }
onChange={ dayTemplateHandler }
/>
}
</PanelBody>
</InspectorControls>,
<div className='bsd-strong-post-block-editor'>
<div className={ this.props.className }>
<RichText
placeholder={ __('Log your lifts here') }
value={ dayTemplateContent }
multiline={ false }
onChange={ onChangeBlockTemplate }
className='bsd-strong-post-training-log'
/>
</div>
</div>
];
}
},
save: (props) => {
return (
<div className={ `align${props.attributes.block_alignment}` }>
<ul className='list-unstyled'style={{ textAlign: props.attributes.text_alignment }}>
<li>
<strong>{ __('Program', 'bsd-strong-post') }: </strong>
<span className='bsd-strong-post-program'>{ props.attributes.programName }</span>
</li>
<li>
<strong>{ __('Phase', 'bsd-strong-post') }: </strong>
<span className='bsd-strong-post-phase-ph'>{ props.attributes.phaseName }</span>
</li>
<li>
<strong>{ __('Day', 'bsd-strong-post') }: </strong>
<span className='bsd-strong-post-day-ph'>{ props.attributes.dayTemplateName }</span>
</li>
<li>
<strong>{ __('Author', 'bsd-strong-post') }: </strong>
<span className='bsd-strong-post-author-ph'>{ props.attributes.programAuthor }</span>
</li>
</ul>
<RichText.Content
value={ props.attributes.dayTemplateContent }
className='bsd-strong-post-training-log'
/>
</div>
)
}
});
Here's the console output on reload:
Content generated by 'save' function:
<div class="wp-block-bsd-strong-post-training-session alignwide"><ul class="list-unstyled"><li><strong>Program: </strong><span class="bsd-strong-post-program">Madcow</span></li><li><strong>Phase: </strong><span class="bsd-strong-post-phase-ph">Intermediate</span></li><li><strong>Day: </strong><span class="bsd-strong-post-day-ph">Day 1</span></li><li><strong>Author: </strong><span class="bsd-strong-post-author-ph">Madcow</span></li></ul>
<thead>
<tr>
<th scope="col">Exercise</th>
<th scope="col">Set 1</th>
<th scope="col">Set 2</th>
</tr>
</thead>
<tbody>
<tr class="bsd-strong-post-exercise-one">
<td class="bsd-strong-post-exercise-name">Squat</td>
<td class="bsd-strong-post-set-1">95 x 5</td>
<td class="bsd-strong-post-set-2">135 x 5</td>
</tr>
</tbody>
</div>
Content retrieved from post body:
<div class="wp-block-bsd-strong-post-training-session alignwide"><ul class="list-unstyled"><li><strong>Program: </strong><span class="bsd-strong-post-program">Madcow</span></li><li><strong>Phase: </strong><span class="bsd-strong-post-phase-ph">Intermediate</span></li><li><strong>Day: </strong><span class="bsd-strong-post-day-ph">Day 1</span></li><li><strong>Author: </strong><span class="bsd-strong-post-author-ph">Madcow</span></li></ul><table class='bsd-strong-post-training-template'>
<thead>
<tr>
<th scope='col'>Exercise</th>
<th scope='col'>Set 1</th>
<th scope='col'>Set 2</th>
</tr>
</thead>
<tbody>
<tr class='bsd-strong-post-exercise-one'>
<td class='bsd-strong-post-exercise-name'>Squat</td>
<td class='bsd-strong-post-set-1'>95 x 5</td>
<td class='bsd-strong-post-set-2'>135 x 5</td>
</tr>
</tbody>
</table></div>
I can see that the content displayed below Content generated by 'save' function: is missing the <table> and </table> tags. I've tried to work around this by adding tagName='table' in the RichText.Content properties inside the save function, but then the console shows duplicate <table> and </table> tags.
EDIT: The table is populated when a user makes a change to the Select control in InspectorControls. This action calls dayTemplateHandler, which among other things, calls getTemplate, a function that gets the content of the table from the database. Here's an example of that output (data.day_template.template_content):
<table class='bsd-strong-post-training-template'>
<thead>
<tr>
<th scope='col'>Exercise</th>
<th scope='col'>Set 1</th>
<th scope='col'>Set 2</th>
</tr>
</thead>
<tbody>
<tr class='bsd-strong-post-exercise-one'>
<td class='bsd-strong-post-exercise-name'>Squat</td>
<td class='bsd-strong-post-set-1'>95 x 5</td>
<td class='bsd-strong-post-set-2'>135 x 5</td>
</tr>
</tbody>
</table>
On reviewing the table template and considering the error, I suspect the issue is the selector of the dayTemplateContent attribute, .bsd-strong-post-training-template
The first time the content is saved, it successfully loads the template data from database and saves the complete table structure. When the content is reloaded, the block validator fails as the selector of dayTemplateContent reads in the child nodes of the table's css selector (which is thead) and doesn't match expected content. Ref: HTML example of blockquote/paragraphs
Try wrapping the <table> template with a <div class="bsd-strong-post-training-template"> or changing the selector.

Styling material ui table cells according to their values

I have a material ui table and I would like to colour the different cells according to what value is displayed in them. The cells are populated with json data using map. For example if a cell has the value 1, I would like the colour to be yellow.
{
Name: "A Person",
Attendence: [
{
date: "2019/12/01",
attendence: 1
},
{
date: "2019/12/02",
attendence: 1
},
{
date: "2019/12/03",
attendence: 0
}
]
}
];
return (
<Fragment>
{attendence.map(person => {
return (
<Table>
<thead>
<tr>
<th>Name</th>
{person.Attendence.map(personAttendendance => {
return <th>{personAttendendance.date}</th>;
})}
</tr>
</thead>
<tbody>
<tr>
<td>{person.Name}</td>
{person.Attendence.map(personAttendendance => {
return <td>{personAttendendance.attendence}</td>;
})}
</tr>
</tbody>
</Table>
);
})}
</Fragment>
);
}
export default Test;
That is what the table looks like. I tried
if(value === 1){
return(
<TableCell style={{ background: "red" }}>{value}</TableCell>
)
} else {
return(
<TableCell style={{ background: "red" }}>{value}</TableCell>
)
}
}
But that did not work . It just read the else and made everything red.
Change your tbody in test.js to:
<tbody>
<tr>
<td>{person.Name}</td>
{person.Attendence.map(personAttendendance => {
if(personAttendendance.attendence === 1){
return <td style={{background: "red" }}>{personAttendendance.attendence}</td>;
} else {
return <td style={{background: "blue" }}>{personAttendendance.attendence}</td>;
}
})}
</tr>
</tbody>
or
<tbody>
<tr>
<td>{person.Name}</td>
{person.Attendence.map(personAttendendance => {
return <td style={{background: personAttendendance.attendence === 1 ? "red" : "blue"}}>{personAttendendance.attendence}</td>;
})}
</tr>
</tbody>
Which ever suits you best.
Link to fork here. (using the second example)

Why if i modify in one css file the table will be changed in all places?

I have 2 different pages and 2 different css (one for each html page) and if i modify .table{} in one of them, the css is applied on all pages. I use react bootstrap
I expect to have one table from page1 at 100% width and the table from page2 at 33.3% width.
page2:
import React from 'react';
import Container from "react-bootstrap/Container";
import {Jumbotron} from "react-bootstrap";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Image from "react-bootstrap/Image"
import ProgressBar from "react-bootstrap/ProgressBar"
import Table from "react-bootstrap/Table"
import './Doctor.css'
export default class Doctor extends React.Component {
constructor(props){
super(props);
this.state = {
items: [],
isLoaded: false,
}
}
componentDidMount() {
fetch('http://localhost:8000/api/doctorsList')
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
items: json,
})
});
}
render() {
var { isLoaded, items} = this.state;
if (!isLoaded){
return <div>Loading...</div>
}else {
return (
<Container>
<Jumbotron>
<h1 align="center">The Clinicum</h1>
</Jumbotron>
<Row>
{items.map(row =>(
<Col className={".column"} key={row.iddoctor}>
<Image src={require('./photos/dr1.jpg')} roundedCircle />
<p>Raiting:</p>
<ProgressBar>
<ProgressBar striped variant="success" now={70} key={1} label={"70%"} />
<ProgressBar striped variant="danger" now={30} key={2} label={"30%"} />
</ProgressBar>
<br/>
<Table striped bordered hover >
<tbody>
<tr>
<td>Name</td>
<td>{row.nume}</td>
</tr>
<tr>
<td>An absolvire</td>
<td>{row.anAbsolvire}</td>
</tr>
<tr>
<td>Specializare</td>
<td>{row.specializare}</td>
</tr>
<tr>
<td>Telefon</td>
<td>{row.photoLink}</td>
</tr>
</tbody>
</Table>
</Col>
))}
</Row>
</Container>
)};
}
}
page1:
import React, {Component} from 'react';
import { Link} from 'react-router-dom';
import {Jumbotron} from 'react-bootstrap';
import './Home.css';
import Container from "react-bootstrap/Container";
import Table from "react-bootstrap/Table";
import {Image} from "react-bootstrap";
class Home extends Component {
constructor(props){
super(props);
this.state = {
items: [],
isLoaded: false,
}
}
componentDidMount() {
fetch('http://localhost:8000/api/clinicList')
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
items: json,
})
});
}
render() {
var { isLoaded, items} = this.state;
if (!isLoaded){
return <div>Loading...</div>
}else {
return (
<Container>
<Jumbotron>
<h1 align="center">The Clinicum</h1>
</Jumbotron>
<Table className="table">
<thead>
<tr>
<th>Name</th>
<th>Locatie</th>
<th>Tip Unitate</th>
</tr>
</thead>
<tbody>
{items.map(row =>(
<tr key={row.idclinic}>
<td>
<Link to="/doctor">
<Image
src= {require(`./photos/${row.photoLink}.jpg`)}//{row.photoLink}
width="30"
height="30"
className="d-inline-block align-top"
alt={"aa"}
/>{row.name}
</Link>
</td>
<td>{row.locatie}</td>
<td>{row.tipUnitate}</td>
</tr>
))}
</tbody>
</Table>
</Container>
);
}
}
}
export default Home;
at Home.css i have
.table{
width: 100%;
}
at Doctor.css i have
.table{
width: 33.3%;
}
but in Home page the table is 33.3%
React doesn't compartmentalize CSS like Angular does. Once it's loaded in the browser it applies everywhere in the current page. Use additional classes on your tables to specify width.
Better yet, use the grid that Bootstrap provides (.col-xs-4 for 33%).
The order of your import statements will decide on which css file will be used last. However, in your case you should just simply add another marker that points to the change. For instance, in this you have a table className. Add another piece to it like so.
.table{
width: 100%;
border: 1px solid black
}
.home{
width: 33.3%
}
Then, in your JSX you can do this.
<Table className='table home' />
Now your table will have the border, and also the home width. This is the easiest way to modify existing css.
That is the normal behaviour. You have two classes with the same name, which means after React is finished building your dev, or prod environment the second class will overwrite the first one, because that is what CSS does.
There is a view different options for you to make sure that doesn't happen:
define inline styles
use CSS-in-js like this or with libraries like styled-components
define separate css class names (for this i would recommend a naming convention, this can be your own, your companies naming convention, or something like BEM)
Personally i would go for the naming convention BEM. This could look like the following:
.home__table {
width: 100%;
}
.doctor__table {
width: 33%;
}
But since you are using Bootstrap, you might want to use the inline-style option and use the bootstrap provided col sizes like #isherwood suggested.

Resources