I am trying to get familiar with React and the fixed-data-table-2 package by following the tutorial of https://github.com/schrodinger/fixed-data-table-2/blob/master/examples/ResizeExample.js.
I am encountering an odd error in that when I resize a column such that a horizontal scroll bar is needed, the scroll bar does not resize proportional to the table width. Rather it allows the user to scroll past all the column-headers.
The series of steps to recreate the error are:
Hit the Page
Resize Company Column and view the scrollbar is visible
Start Scrolling
Continue scrolling past all my columns
I was wondering if I had missed a configuration of the Table Component?
"use strict";
import React from 'react';
import FixedDataTable from 'fixed-data-table-2';
const {Table, Column, Cell} = FixedDataTable;
class BackupTable extends React.Component {
constructor(props) {
super(props);
this.state = {
dataList: [],
columnWidths: {
firstName: 240,
lastName: 150,
sentence: 140,
companyName: 60,
},
};
this._onColumnResizeEndCallback = this._onColumnResizeEndCallback.bind(this);
}
_onColumnResizeEndCallback(newColumnWidth, columnKey) {
console.log("SETTING NEW WIDTH (" + newColumnWidth+") of " + columnKey);
this.setState(({columnWidths}) => ({
columnWidths: {
...columnWidths,
[columnKey]: newColumnWidth,
}
}));
}
render() {
var {dataList, columnWidths} = this.state;
return (
<Table
rowHeight={30}
headerHeight={50}
rowsCount={10}
onColumnResizeEndCallback={this._onColumnResizeEndCallback}
isColumnResizing={false}
touchScrollEnabled={true}
width={1000}
height={500}
{...this.props}>
<Column
columnKey="firstName"
header={<Cell>First Name</Cell>}
cell={<Cell>Basic content</Cell>}
fixed={true}
width={columnWidths.firstName}
isResizable={true}
/>
<Column
columnKey="lastName"
header={<Cell>Last Name (min/max constrained)</Cell>}
cell={<Cell>Basic content 2</Cell>}
width={columnWidths.lastName}
isResizable={true}
minWidth={70}
maxWidth={170}
/>
<Column
columnKey="companyName"
header={<Cell>Company</Cell>}
cell={<Cell>Basic content 4</Cell>}
width={columnWidths.companyName}
isResizable={true}
/>
<Column
columnKey="sentence"
header={<Cell>Sentence</Cell>}
cell={<Cell>Basic content 3</Cell>}
width={columnWidths.sentence}
isResizable={true}
/>
</Table>
);
}
}
module.exports = BackupTable;
Screen Shots:
INTIAL_TABLE
START_SCROLLING
Running the example you provided in this sandbox - it seems like your table is behaving as expected (no errors).
As soon as the sum of the column widths exceeds the width you set for the table (1000px) - the table starts to overflow horizontally and the horizontal scrollbar appears.
In case the sum of the column widths is less than 1000px (like in the initial state) - a 5th "remainder" column appears in order to "fill up" the table to the table width you set.
I think you will see it more clearly if you try playing around with a smaller table width (try changing it to 500 in the sandbox I shared).
In case you are not interested in the horizontal scroll perhaps you should consider setting the overflowX="hidden" prop on your table.
Related
I am trying to create simple app to show data stored in Mongodb. I could get all the data and make it shown in the app. I want to set color in each cell of table when they meet certain condition. For example, I want any cell values over 50% colored yellow and 70% colored greed ... How can I do that? I am using MDB package based on React bootstrap 4.
import { MDBDataTable } from 'mdbreact';
And here is my code:
and my app appears like:
I tried to find some solution from the documentation of MDB but couldn't find it that specifically change color by threshold.
conditional styles in bootstrap datatable: https://mdbootstrap.com/docs/react/data/datatables/
const conditionalRowStyles = [
{
when: row => row.coverage < 50,
style: {
backgroundColor: 'yellow',
},
},
];
const MyTable = () => (
<DataTable
title="Desserts"
columns={columns}
data={data}
conditionalRowStyles={conditionalRowStyles}
/>
);
I have been trying to add Slider component to a react project. functionality wise its working fine but i am having two issues which i am not able to get rid of
changing value of the slider is not smooth. Dragging doesn't work properly, its just drags to the nearest value and then stops.
On a mobile device its even worse, no dragging at all, i have to tap on the exact spot for the slider to move.
I did find the issue, i was using onChange, so when i removed it it worked exactly like the example. But i need to update state of parent component, so added line 18, but then again the same issue appeared. I fi remove line 18 then all this gets fixed but i need line 18 to call a function of parent component, to update its state variable.
Here is the gist link of my code
https://gist.github.com/kapiljhajhria/0e9beda641d561ef4448abf9195dbcca
import React from "react";
import Slider from "#material-ui/core/Slider";
export default function SliderWithLabel(props) {
const {
labelText, range = {
min: 0,
max: 10
}, step = 1,
// defaultValue = Math.ceil((range.min + range.max) / 2),
handleSliderChange,
name,
value: sliderValue
} = props;
function sliderValuetext(value) {
// handleChange({target: {value: value}});
if(value!==sliderValue)handleSliderChange(value,name)
return `${value}`;
}
return (
<div className="sliderField" style={{display: "flex", flexDirection: "column"}}>
<div>
{labelText}
</div>
<Slider
style={{width: "90%", justifyContent: "center", display: "flex", margin: "auto"}}
defaultValue={sliderValue}
getAriaValueText={sliderValuetext}
aria-labelledby="discrete-slider"
valueLabelDisplay="auto"
// onChange={sliderChange}
step={step}
// name={name}
// onChange={handleChange}
marks
min={range.min}
max={range.max}
/>
</div>
)
}
after spending 2 days on the issue, creating a sample project , trying to recreate the issue , it turned out to be a simple fix.
Parent component has a FORM, key which i was using for the form was
Date().getTime()
This was what was causing the issue with the slider. My guess would be that it was rebuilding the whole form with each slider value change. Which made slider UI behave in such a way. using appropraite key fixed the issue. I am now switching between two key value.
I have a React-mui draggable dialog component on which I am using resizable box:
return (
<StyledDialog
open={open}
classes={{root: classes.dialog, paper: classes.paper}}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog"
>
<ResizableBox
height={520}
width={370}
minConstraints={[300, 500]}
maxConstraints={[Infinity, Infinity]}
className={classes.resizable}
>
<DialogContent classes={{root: classes.dialogContent}} id="draggable-dialog">
<IconButton className={classes.clearIcon} aria-label="Clear" onClick={onClose}>
<ClearIcon/>
</IconButton>
<iframe
src={hjelpemiddel.url}
title={hjelpemiddel.navn}
width="100%"
height="100%">
</iframe>
</DialogContent>
</ResizableBox>
</StyledDialog>
);
I would like to resize the iframe inside the dialog along with the ResizableBox. But, it seems I can only resize the width of the ResizableBox, and not the height of the box, at least the maximum height seems to be the one that is set initially. How can I fix that, so that I can resize the height as well?
UPDATE
Codesanbox is available here.
FYI, for some reason sometimes import fail message appears, but everything works fine if you refresh the page of the codesandbox.
In your CodeSandBox, based on my testing, the events for dragging & resizing are simultaneously firing. You could use the cancel prop of react-draggable so that the dragging would not occur when the resize handle is the component being interacted with.
<Draggable
cancel={".react-resizable-handle"}
...
When you do this, the draggable element will not be updating its CSS transform: translate property anymore while resizing - for this, you can opt to control your Draggable component's position. Translate/Set X & Y as necessary to retain its position while resizing. Note that the x & y state & state setters should be residing on a common parent/ancestor among these components that you will be passing down as props.
export default function App() {
// have the source of truth for the positions on a common parent/ancestor
const [x, setX] = React.useState(0);
const [y, setY] = React.useState(0);
return (
<div className="App">
<PDFDialog x={x} y={y} setX={setX} setY={setY} />
</div>
);
}
...
class PDFDialog extends React.Component {
state = {
open: true
};
render() {
const { open } = this.state;
const { classes } = this.props;
return (
<StyledDialog
open={open}
classes={{ root: classes.dialog, paper: classes.paper }}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog"
PaperProps={{
x: this.props.x,
y: this.props.y,
setX: this.props.setX,
setY: this.props.setY
}}
>
<ResizableBox
height={520}
width={370}
minConstraints={[300, 500]}
maxConstraints={[Infinity, Infinity]}
className={classes.resizable}
onResize={(e) => {
if (e.movementX !== 0) {
this.props.setX((prev) => prev + e.movementX);
} else if (e.movementY !== 0) {
this.props.setY((prev) => prev + e.movementY / 2);
}
}}
></ResizableBox>
...
// refactored draggable component:
<Draggable
position={{ x: x, y: y }}
cancel={".react-resizable-handle"} // <-- cancel the dragging if resize is interacted with
onDrag={(e) => {
if (e.movementX !== 0) {
setX((prev) => prev + e.movementX);
}
if (e.movementY !== 0) {
setY((prev) => prev + e.movementY);
}
}}
>
<Paper {...props} />
</Draggable>
(On my CodeSandBox, I've gotten rid of constraints such as minimum height & width to clearly show the example)
You can bind the event of resize of window, calculate the new height and width and pass it to the resizable-box of yours
object.addEventListener("resize", function() {
//Here you can write logic to apply resizing on the resizable-box
});
Obviously, react-resizable uses inline CSS to handle width and height of a box, and for your issue, I simulate this issue, pay attention to the below screenshot from Google chrome devTools:
The react-resizable-box has an important flag and it overwrites the inline height value so in the view, I have the following behavior:
Your information is not enough so I cannot say directly your issue cause or causes but it is very probable CSS overwriting is the root cause of this issue.
So, inspect the resizable-box on your project and seek to find CSS overwriting.
Update after adding re-produce the issue
Actually, based on my last answer something overwrite your height now in the re-production sandbox, I delete the iframe tag, and everything works well, you pass a height="100%" attribute to your iframe tag and it prevents the change of height. Also, you pass a minConstraints={[300, 500]} to your ResizableBox component, so it could not have a smaller height than 500px.
I have an animated component that slides up/down depending on the prop (true or false). I'm using maxHeight: 0 to hide the component (transition is being done with CSS) and that's the default state that's being passed as prop. For the opened style I use a maxHeight much bigger than needed just to make sure the content will fit properly. After it's opened I'm able to get its height by ref and set the maxHeight accordingly.
export default class AnimatedInput extends React.Component {
constructor (props) {
super(props);
this.state = {
height: 600
}
}
componentDidUpdate(prevProps) {
var height = this.refs.inputNode ? this.refs.inputNode.clientHeight : height;
console.log(height);
if (this.props.open === false && prevProps.open === true) {
this.setState({height: height});
}
}
render () {
var {height} = this.state;
let test = this.props.open ? 'boxVisible' : 'boxHidden';
var styles = {
boxHidden: {
...
maxHeight: 0,
},
boxVisible: {
....
maxHeight: height,
}
}
return (
<div style={styles[test]} ref="inputNode">
{this.props.children}
</div>
)
}
}
There are 2 problems with this approach:
The first time it's opened and closed is not smooth due to maxHeight being larger than it should (maybe render the opened one off-screen and get its height first?)
If it's closed before fully opened the height will be lower than it should (I suppose it's an easy fix - just need to stop updating the height value).
Am I on the right track? How would you fix these? Should I stick to CSS or maybe make the transition entirely in JS. Thanks for your suggestions!
You're looking for ReactCSSTransitionGroup. I used this for the exact same thing you are.
I have a table - let's call it table 1. When clicking on a row in table 1 another table is being displayed, let's call this one table 2. Table 2 displays data relevant to the clicked row in table 1. Sometimes a vertical scroll needs to be displayed in table 2 and sometimes not -depends on the number of rows.Need to solve: there is an unwanted transition of the border when the scroll is not being displayed:
. The idea for the solution: "change margin-right" according to conditions which show whether the scroll exits or not.Save the result of this condition into Redux prop:
element.scrollHeight > element.clientHeight || element.scrollWidth >
element.clientWidth
The problem: Trying to update the display/non-display of the scroll into redux prop from different React events such as componentDidMount, componentWillReceiveProps,CopmponentDidUpdate (set state causes infinte loop here) and from the click event.Tried to use forceUpdate() after setting props into Redux as well.
When console.log into the console in chrome (F12), the only result which is correlated correctly to the display/non display of the scrollbar is coming from within the componentDidUpdate and it doesn't reflect in the redux prop (isoverflown function returns true, redux this.props.scrollStatus and this.state.scrollStatus are false). Also don't like the usage of document.getElementById for the div which contains the rows, because it breaks the manipulation of the dom from within the props and state,but didn't find a different solution for now.
The F12 console when display the scroll bar:
The F12 console when no scroll bar is displayed:
.
The rest of the code:
1) action:
export function setScrollStatus(scrollStatus) {
return {
type: 'SET_SCROLL_STATUS',
scrollStatus: scrollStatus
};
}
2) reducer:
export function scrollStatus(state = [], action) {
switch (action.type) {
case 'SET_SCROLL_STATUS':
return action.scrollStatus;
default:
return state;
}
}
3)Page.js (please click on the picture to see the code)
import {setScrollStatus} from '../actions/relevantfilename';
function isOverflown(element) {
return element.scrollHeight > element.clientHeight ||element.scrollWidth > element.clientWidth;
}
class SportPage extends React.Component {
constructor(props) {
super(props);
this.state = initialState(props);
this.state = {
scrolled:false,
scrollStatus:false};
componentDidUpdate() {
console.log( "1 isoverflown bfr redux-this.props.setScrollStatus inside componentDidUpdate",isOverflown(document.getElementById('content')));
//redux props
this.props.setScrollStatus( isOverflown(document.getElementById('content')));
console.log( "2 isoverflown aftr redux-this.props.setScrollStatus inside componentDidUpdate",isOverflown(document.getElementById('content')));
//redux props
this.props.scrollStatus ? console.log (" 3 this.props.scrollStatus true inside componentDidUpdate") : console.log("this.props.scrollStatus false inside componentDidUpdate");
console.log ("4 state scrollstatus inside componentDidUpdate" , this.state.scrollStatus)
}
componentDidMount(){
console.log( "3 isoverflown bfr set",isOverflown(document.getElementById('content')));
this.props.setScrollStatus("set inside didMount", isOverflown(document.getElementById('content')));
console.log( "4 isoverflown aftr set didMount",isOverflown(document.getElementById('content')));
this.props.scrollStatus ? console.log ("scrollStatus true") : console.log("scrollStatus false");
console.log ("state scrollstatus inside didMount" , this.state.scrollStatus)
}
render() {
<div style={{overflowY:'scroll',overflowX:'hidden',height:'50vh',border:'none'}}>
{
this.props.rowData.map((row,index )=>
<div style={{ display: 'flex',flexWrap: 'wrap', border:'1px solid black'}}
onClick={ e => { this.setState({ selected: index, detailsDivVisible: true,scrolled:isOverflown(document.getElementById('content')),
scrollStatus:isOverflown(document.getElementById('content')) },
this.props.setScrollStatus( isOverflown(document.getElementById('content'))),this.forceUpdate(),console.log ("onclick this.state.scrollStatus", this.state.scrollStatus),
console.log ("onclick pure funtion", isOverflown(document.getElementById('content'))));
const mapDispatchToProps = (dispatch) => {
return {
setScrollStatus: function (scrollStaus) {dispatch (setScrollStatus(scrollStaus))},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Page);
Thank you for your reply. However,solved it in different way which does not involve the life cycle/events:
1) Calculate the height of the scroll by- multiple the height of single row by number of items to be displayed (arr.length, the arr comes from JSON)
2) setting the max height of the scroll to a needed value
3) setting the max height of the content to be the calculated height:
The result is a scroll that displays all the time with the correct height. This solved the indentation problem.
<div style={{overflowY:'auto', marginRight: '18px',zIndex:'1000',borderBottom:'1px solid black',borderRight:'1px solid black', height: this.props.rowData[this.state.selected].rowItemsList.length * singleRowHeight + 'px', maxHeight:'100px' }}>
<div style={{ width:'inherit', maxHeight:this.props.this.props.rowData[this.state.selected].rowItemsList.length * singleRowHeight + 'px' }}>
Lets simplify this. All you need is to dispatch reducer each time some one clicks inside a div.Please find the code snippet useful please go through the comments.
//import store from "./store/directory" - update this to ur store
let DOMObject = document.getElementById("id1"); //dom reference i did it based on ID its up to u to refer how u like it
//call back happens each time onclick event is triggered
DOMObject.onclick = ()=> {
/* store.dispatch(
{
type:"reducer to invoke",
data:"the data to update on click"
}
);
*/
//uncomment above and update to your requirement
console.log("clicked - Please update the dispatch event to you requirement");
}
#id1 {
padding :100px 150px 100px 80px;
background-color: lightblue;
}
<div id="id1">
DIV AREA - clcik
</div>