Button/dropdown button disabled by default without specifying disabled - reactjs

I am trying to add a dropdown button in my react project and its rendering as disabled by default. why is this happening ?
The first dropdown is working fine, i called the same dropdown in the navbar after this one and it renders as disabled. I tried other things as well, like adding a button also would not work for me.
The navbar is diplayed when i get a response from the backend and a different component is rendered (ResultTable)
import React from "react";
import ResultTable from "./ResultTable";
...
import DropdownButton from "react-bootstrap/DropdownButton";
import Dropdown from "react-bootstrap/Dropdown";
class MainContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
//more state values
threshold: 0.75
};
this.thresholdChange = this.thresholdChange.bind(this);
}
thresholdChange(input) {
this.setState({
threshold: input
});
}
toProperCase = function (txt) {
return txt.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
};
render() {
const { responseData } = this.state;
return (
<div className="container-flex container-without-scroll wrapper"
style={{
backgroundImage: `url(${bg})`,
width: "100%",
height: "100vh",
backgroundSize: "cover",
backgroundRepeat: "no-repeat",
overFlow:'hidden'
}}
>
<div
className={`container-fluid `}>
{this.state.displayTable ? (
<Navbar
style={{
position: "fixed",
left: "50%",
top: "95%",
transform: "translate(-50%, -90%)",
backgroundColor: 'black'
}}
sticky="bottom"
>
<br />
<Navbar.Collapse className="justify-content-end">
<Button
variant="primary"
disabled={
this.props.initialTransaction &&
this.props.initialTransaction.version == 0 &&
this.props.initialTransaction
? true
: false
}
size="sm"
style={{ color: "#FFF" }}
onClick={this.undoAction}
>
<span className=" fa fa-undo "></span>
Undo
</Button>
<Button
variant="primary"
size="sm"
style={{ color: "#FFF" }}
disabled={
(this.props.initialTransaction &&
this.props.initialTransaction.version) <
(this.props.currentVersion &&
this.props.currentVersion.version)
? false
: true
}
onClick={this.redoAction}
>
<span className=" fa fa-repeat "></span>
Redo
</Button>
<Button
variant="success"
size="sm"
style={{ color: "#FFF" }}
disabled={
this.props.initialTransaction &&
this.props.initialTransaction.version == 0
? true
: false
}
onClick={() =>
this.exportExcel(this.props.initialTransaction)
}
>
<span className=" fa fa-download "></span>
Export
</Button>
<DropdownButton
size="md"
title={this.state.threshold}
>
{this.state.thresholdValues.map(eachValue => {
return (
<Dropdown.Item
key = {Math.random()}
onClick={() => this.thresholdChange(eachValue)}
as="button"
>
{eachValue}
</Dropdown.Item>
);
})}
</DropdownButton>
</Navbar.Collapse>
<br/>
</Navbar>
) : null}
{this.state.displayTable ? null : (
<div
className="col-md-4 col-md-offset-4"
style={{
position: "absolute",
left: "50%",
top: "50%",
transform: "translate(-50%, -50%)",
backgroundColor: 'rgba(14, 13, 13, 0.74)'
}}
>
<br />
<div className="row">
<div className="input-group col-md-9">
<div className="input-group-prepend">
<span
style={{ cursor: 'pointer' }}
onClick={this.onFormSubmit}
className="input-group-text"
id="inputGroupFileAddon01"
>
{" "}
Upload{" "}
</span>
</div>
<div className="custom-file">
<input
type="file"
className="custom-file-input"
id="inputGroupFile01"
onChange={this.onChange}
aria-describedby="inputGroupFileAddon01"
/>
<label
className="custom-file-label"
htmlFor="inputGroupFile01"
>
{this.props.active && this.props.active.filename}
</label>
</div>
</div>
<div className="col-md-3">
<DropdownButton
size="md"
id="dropdown-item-button"
title={this.state.threshold}
>
{this.state.thresholdValues.map(eachValue => {
return (
<Dropdown.Item
onClick={() => this.thresholdChange(eachValue)}
as="button"
>
{eachValue}
</Dropdown.Item>
);
})}
</DropdownButton>
</div>
</div>
<br />
</div>
)}
<div >
{this.state.displayTable ? (
<div className = "container-flex" style =
{{overflowY:'scroll', maxHeight:'80vh'}}>
<ResultTable
data={responseData}
afterMerge={params => {
this.afterMerge(params);
}}
/>
</div>
) : null}
</div>
</div>
</div>
);
}
}
// Maps state from store to props
const mapStateToProps = (state, ownProps) => {
return {
};
};
// Maps actions to props
const mapDispatchToProps = dispatch => {
return {
};
};
// Use connect to put them together
export default connect(
mapStateToProps,
mapDispatchToProps
)(MainContainer);

Related

MUI Icon button show border when clicked

I have used an Iconbutton for my website but when it is clicked it shows a border & the animation is also gone. Also, I would like to know how to assign functions to my + / - buttons to increase & decrease the value in the text input. following is my full code. I get the NaN in
Code:
export class BookingSummary extends Component {
constructor(props) {
super(props);
this.state = {
seatPrice: [],
dataLoaded: false,
priceList :[],
};
}
state = { value: 0 };
onPlusClick = () => {
this.setState({ ...this.state, value: this.state.value + 1 });
};
onMinusClick = () => {
this.setState({ ...this.state, value: this.state.value - 1 });
};
render () {
return (
<IconButton
onClick={this.onMinusClick}
aria-label="minus"
style={{ marginTop: 15 }}
>
<RemoveCircleIcon fontSize="inherit" />
</IconButton>
<TextField
value={this.state.value}
id="outlined-adornment-small"
// defaultValue="50"
variant="outlined"
size="small"
style={{ width: 48, height: 35 }}
labelWidth={0}
/>
<IconButton
onClick={this.onPlusClick}
aria-label="plus"
style={{ marginTop: 15 }}
>
<AddCircleIcon fontSize="inherit" />
</IconButton>
You can achieve your aim with predifined setState in classify component. Also you need to use onClick for IconButtons. When user clicks on the buttons, you should change the value of the counter. Here's the classify component which you would like to implement:
import React from "react";
import IconButton from "#material-ui/core/IconButton";
import TextField from "#material-ui/core/TextField";
import RemoveCircleIcon from "#material-ui/icons/RemoveCircle";
import AddCircleIcon from "#material-ui/icons/AddCircle";
import "./styles.css";
export class MyComponent extends React.Component {
state = {
value: 0
};
onPlusClick = () => {
this.setState({ ...this.state, value: this.state.value + 1 });
};
onMinusClick = () => {
this.setState({ ...this.state, value: this.state.value - 1 });
};
render() {
return (
<div className="App">
<div className="col-xl-4 col-lg-4 col-md-12 col-sm-12 col-12">
<div className="row">
<div className="col-md-12">
<div className="st_dtts_bs_wrapper float_left">
<div className="st_dtts_bs_heading float_left">
<p>Booking summary</p>
</div>
<div className="st_dtts_sb_ul float_left">
<ul>
<li>
movieData.seats
<br />( 5 Tickets ) ODC <span>Rs .50</span>
</li>
<li>
Child Tickets
<br />( 2 Tickets ) ODC <span>Rs .5 </span>
<br />
<br />
<IconButton
onClick={this.onMinusClick}
aria-label="minus"
style={{ marginTop: 15 }}
>
<RemoveCircleIcon fontSize="inherit" />
</IconButton>
<TextField
value={this.state.value}
id="outlined-adornment-small"
defaultValue="50"
variant="outlined"
size="small"
style={{ width: 48, height: 35 }}
labelWidth={0}
/>
<IconButton
onClick={this.onPlusClick}
aria-label="plus"
style={{ marginTop: 15 }}
>
<AddCircleIcon fontSize="inherit" />
</IconButton>
</li>
<li>
Handling fees <span>Rs. 25</span>
</li>
</ul>
</div>
<div className="st_dtts_sb_h2 float_left">
<h3>
Sub total <span>Rs. 55</span>
</h3>
<h4>
Current State is <span>Colombo</span>
</h4>
<h5>
Payable Amount{" "}
<span style={{ color: "#ff4444" }}>Rs. 555</span>
</h5>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default function App() {
return <MyComponent />;
}

I am new to react and when i click on submit button nothing happens?

Here is the code!!
Actually very new to react and i am working on a project which is about to-do list but while doing this i am stuck on rendering the output of the input field in the list item. if there is another solution like without the list group it would be very helpful!
Where i am doing the actual mistake please someone look upon this
Thanks in advance!
import React, { Component, Fragment } from "react";
class MainPage extends Component {
state = { data: "" };
handleChange = (e) => {
e.preventDefault();};
handleSubmit = (e) => {
e.preventDefault();
this.setState({ data: e.target.value });
};
render() {
const mystyle = {
padding: "16px 16px 16px 60px",
textAlign: "start",
fontSize: "24px",
fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif',
width: "500px",
};
return (
<Fragment>
<h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
todos
</h1>
<form className="todo-form" onSubmit={this.handleSubmit}>
<input
type="text"
onChange={this.handleChange.bind(this)}
className="new-todo shadow-lg p-3 mb-5 bg-white rounded"
style={mystyle}
placeholder="What needs to be done?"
/>
<button className="btn btn-primary btn-sm ml-3">Submit</button>
<ul className="list-group">
<li
className="list-group-item disabled p-3 mb-5 w-50 p-3 mx-auto "
style={{ width: "200px", fontSize: "24px" }}
>
{this.state.data}
</li>
</ul>
</form>
</Fragment>
);}}
export default MainPage;
There are some issues in your code:
You want to submit on button. For that you need to add type="submit"
<button className="btn btn-primary btn-sm ml-3" type="submit">
Submit
</button>
You need to maintain two states first for input and second for todo's. In that way you can always append in existing todo when user submits form:
state = { data: [], input: "" };
Last you are saving value onSubmit but it has not e.target.value instead you need to save in onHandleChage
Here is full code:
import React, { Component, Fragment } from "react";
class MainPage extends Component {
state = { data: [], input: "" };
handleChange = (e) => {
e.preventDefault();
this.setState({ input: e.target.value });
};
handleSubmit = (e) => {
e.preventDefault();
this.setState({ data: [...this.state.data, this.state.input], input: "" });
};
render() {
const mystyle = {
padding: "16px 16px 16px 60px",
textAlign: "start",
fontSize: "24px",
fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif',
width: "500px"
};
return (
<Fragment>
<h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
todos
</h1>
<form className="todo-form" onSubmit={this.handleSubmit}>
<input
type="text"
onChange={this.handleChange.bind(this)}
value={this.state.input}
className="new-todo shadow-lg p-3 mb-5 bg-white rounded"
style={mystyle}
placeholder="What needs to be done?"
/>
<button className="btn btn-primary btn-sm ml-3" type="submit">
Submit
</button>
<ul className="list-group">
{this.state.data.map((data, i) => {
return (
<li
className="list-group-item disabled p-3 mb-5 w-50 p-3 mx-auto "
style={{ width: "200px", fontSize: "24px" }}
key={"todo-" + i}
>
{data}
</li>
);
})}
</ul>
</form>
</Fragment>
);
}
}
export default function App() {
return (
<div className="App">
<MainPage />
</div>
);
}
Here is the demo: https://codesandbox.io/s/xenodochial-banzai-qwxfu?file=/src/App.js:0-1762
import React, { Component, Fragment } from "react";
class MainPage extends Component {
state = { data: "" };
handleSubmit = (e) => {
e.preventDefault();
alert(data)
};
render() {
const mystyle = {
padding: "16px 16px 16px 60px",
textAlign: "start",
fontSize: "24px",
fontFamily: 'Helvetica Neue", Helvetica, Arial, sans-serif',
width: "500px",
};
return (
<Fragment>
<h1 className="display-1 text-center" style={{ color: "#f7c6c6" }}>
todos
</h1>
<form className="todo-form" onSubmit={this.handleSubmit}>
<input
type="text"
onChange={(e) => this.setState({data: e.target.value})}
className="new-todo shadow-lg p-3 mb-5 bg-white rounded"
style={mystyle}
placeholder="What needs to be done?"
/>
<button className="btn btn-primary btn-sm ml-3">Submit</button>
<ul className="list-group">
<li
className="list-group-item disabled p-3 mb-5 w-50 p-3 mx-auto "
style={{ width: "200px", fontSize: "24px" }}
>
{this.state.data}
</li>
</ul>
</form>
</Fragment>
);}}
Try it like:
state = { data: "", FinalDataValue:"" };
handleChange = (e) => {
e.preventDefault();
this.setState({ data: e.target.value });};
handleSubmit = (e) => {
e.preventDefault();
this.setState({ FinalDataValue:this.state.data });};
and in render in list write it like :
<li
className="list-group-item disabled p-3 mb-5 w-50 p-3 mx-auto "
style={{ width: "200px", fontSize: "24px" }}
>
{this.state.FinalDataValue}
</li>

Pass props to child component from parent component dynamically

I have a child component StepperNotification which gets an input from user and returns it as prop to its child component in following way.
const styles = {
transparentBar: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
const useStyles = makeStyles((theme: Theme) =>
createStyles({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}),
);
function getSteps() {
return ['Create', 'Audience', 'Timing'];
}
function getStepContent(step, $this) {
switch (step) {
case 0:
return (
<div className="row">
<CardBox styleName="col-lg-12"
heading="">
<form className="row" noValidate autoComplete="off" style={{"flex-wrap":"no-wrap", "flex-direction": "column" }}>
<div className="col-md-12 col-12">
<TextField
id="campaign_name"
label="Campaign Name"
value={$this.state.name}
onChange={$this.handleChange('name')}
margin="normal"
fullWidth
/>
</div>
</form>
</CardBox>
</div>
);
default:
return 'Unknown step';
}
}
class NotificationStepper extends React.Component {
state = {
activeStep: 0,
name: '',
};
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
this.props.titlechange(event.target.value);
};
handleNext = () => {
this.setState({
activeStep: this.state.activeStep + 1,
});
};
handleBack = () => {
this.setState({
activeStep: this.state.activeStep - 1,
});
};
handleReset = () => {
this.setState({
activeStep: 0,
});
};
render() {
const steps = getSteps();
const {activeStep} = this.state;
return (
<div className="col-xl-12 col-lg-12 col-md-7 col-12">
<Stepper className="MuiPaper-root-custom" activeStep={activeStep} orientation="vertical">
{steps.map((label, index) => {
return (
<Step key={label}>
<StepLabel>{label}</StepLabel>
<StepContent className="pb-3">
<Typography>{getStepContent(index, this)}</Typography>
<div className="mt-2">
<div>
<Button
disabled={activeStep === 0}
onClick={this.handleBack}
className="jr-btn"
>
Back
</Button>
<Button
variant="contained"
color="primary"
onClick={this.handleNext}
className="jr-btn"
>
{activeStep === steps.length - 1 ? 'Finish' : 'Next'}
</Button>
</div>
</div>
</StepContent>
</Step>
);
})}
</Stepper>
{activeStep === steps.length && (
<Paper square elevation={0} className="p-2">
<Typography>All steps completed - you"re finished</Typography>
<Button onClick={this.handleReset} className="jr-btn">
Reset
</Button>
</Paper>
)}
</div>
);
}
}
export default NotificationStepper;
In my parent component i am getting this prop value and passing it to another child component Tabcomponent in following way
ParentCompoennt.js
const SendNotification = ({match}) => {
let titlename = '';
let message = '';
function handleTitle(title_) {
console.log('in here');
console.log(title_);
titlename = title_;
}
return (
<div className="dashboard animated slideInUpTiny animation-duration-3">
<ContainerHeader match={match} title={<IntlMessages id="sidebar.notification"/>}/>
<div className="row" style={{'flex-wrap': 'no wrap', "flex-direction": 'row'}}>
<div className="col-xl-7 col-lg-7 col-md-7 col-7">
<NotificationStepper titlechange={handleTitle} />
<div className='flex-class' style={{'width': '100%'}}>
<Button color="primary" style={{"align-self": "flex-end", "border" : "1px solid", "margin-left": "10px", "margin-bottom": "40px"}} size="small" className="col-md-2 col-2">Fetch</Button>
<Button color="primary" style={{"align-self": "flex-end", "border" : "1px solid", "margin-left": "10px", "margin-bottom": "40px"}} size="small" className="col-md-2 col-2" color="primary">Discard</Button>
</div>
</div>
<div className="col-xl-5 col-lg-5 col-md-5 col-5" style={{"padding-top": "20px"}}>
<span style={{"margin-left" : "20px", "font-weight": "bold"}}>Preview</span>
<TabComponent {...{[title]:titlename}} message={message} />
</div>
</div>
</div>
);
};
export default SendNotification;
and in TabComponent i am getting this prop value and using it component in following way
TabContainer.propTypes = {
children: PropTypes.node.isRequired,
dir: PropTypes.string.isRequired,
};
class TabComponent extends Component {
state = {
value: 0,
};
render() {
const {theme} = this.props;
const title = this.props.title;
return (
<div className="col-xl-12 col-lg-12 col-md-12 col-12" style={{"margin-top": "15px"}}>
<NotifCard key={0} data={{'name': title, 'company': 'sayge.ai', 'image': require("assets/images/bell.png"), 'description': this.props.message}} styleName="card shadow "/>
</div>
);
}
}
TabComponent.propTypes = {
theme: PropTypes.object.isRequired,
};
export default withStyles(null, {withTheme: true})(TabComponent);
StepperNotification is working fine and props are being updated in parent. i have checked this by printing the updated values in console, but the props in TabComponent are not being updated. What am i doing wrong here? any help is appreciated.
Probaly this is your issue
<TabComponent {...{[title]:titlename}} message={message} />` this could be just
title is undefined and you are sending props[undefined]=titlename
Just do this
<TabComponent title={titlename} message={message} />`
And if SendNotification is react fuction component useState for keeping track of current titlename. If it still doesn't work after first fix this second will be another source of your problems.

Is there a way to force a React component to rerender a child?

I have a React component <ProductPrices>:
render() {
if (this.props.currentProduct.id !== 'new' && !this.props.currentProductPrices) {
this.props.fetchProductPrices(this.props.currentProduct.id);
}
return (
<div>
<div style={{backgroundColor: 'gray', paddingLeft: '10px', paddingTop: '10px', paddingBottom: '5px'}}>
<h1>Precios</h1>
</div>
<div>
{this.props.currentProductPrices && this.props.currentProductPrices.map((price, index) => {
console.log({detail: price});
return (
<ProductPricesEntry key={price.id} price={price} index={index} />
)
})}
</div>
</div>
)
}
As you can see, <ProductPrices> contains a number of subcomponents <ProductPricesEntry>, which amount is dynamic depending on Redux state variable currentProductPrices:
render() {
console.log({entry: this.props.price});
return (
<div style={{display: 'flex', background: 'white', backgroundColor: 'lightgray', marginTop: '2px', paddingLeft: '10px', paddingTop: '10px', paddingBottom: '5px'}}>
<div className='col-10'>
<div fullWidth>
<h3>{this.props.price.prices_table.name}</h3>
</div>
<div fullWidth style={{display: 'flex'}}>
{this.props.price.current_price?
<div style={{textAlign: 'right'}} className='col-4'><strong>{currencyFormatter.format(this.props.price.current_price)}</strong></div>:
<div style={{textAlign: 'right', color: 'orange'}} className='col-4'>Ninguno</div>
}
{this.props.price.due_date?
<div style={{textAlign: 'center'}} className='col-4'><strong>{this.props.price.due_date}</strong></div>:
<div style={{textAlign: 'center', color: 'orange'}} className='col-4'>Ninguno</div>
}
{this.props.price.next_price?
<div style={{textAlign: 'right'}} className='col-4'><strong>{currencyFormatter.format(this.props.price.next_price)}</strong></div>:
<div style={{textAlign: 'right', color: 'orange'}} className='col-4'>Ninguno</div>
}
</div>
<div fullWidth style={{display: 'flex'}}>
<div style={{textAlign: 'right'}} className='col-4'>Actual</div>
<div style={{textAlign: 'center'}} className='col-4'>Vigencia</div>
<div style={{textAlign: 'right'}} className='col-4'>Próximo</div>
</div>
</div>
<div className='col-1'>
<IconButton color="primary" aria-label={''.concat('update-price-', this.props.price.id)}>
<i className="zmdi zmdi-edit zmdi-hc-fw" onClick={this.handleUpdateClick} />
</IconButton>
<Dialog fullWidth open={this.state.updateDialogOpen} arialabelledby={''.concat('update-price-', this.props.price.id)}>
<DialogTitle id={"".concat("update-price-", this.props.price.id)}>Actualizar Precio</DialogTitle>
<DialogContentText>
<div style={{paddingLeft: '25px'}}><h2>{this.props.currentProductData.name}</h2></div>
<div style={{paddingLeft: '25px'}}><h2>{this.props.price.prices_table.name}</h2></div>
</DialogContentText>
<DialogContent>
<FormControl fullWidth>
<InputLabel htmlFor="newPrice">Precio</InputLabel>
<Input
type="number"
id="newPrice"
name="newPrice"
value={this.state.newPrice}
onChange={this.handleChange}
startAdornment={<InputAdornment position="start">$</InputAdornment>}
/>
</FormControl>
<div fullWidth><TextField fullWidth label="Fecha" type="date" name="newDate" value={this.state.newDate} onChange={this.handleChange} /></div>
</DialogContent>
<DialogActions>
<Button onClick={this.handleDialogAcceptClick} name="accept" color="primary">
Aceptar
</Button>
<Button onClick={this.handleDialogCancelClick} name="cancel" color="secondary">
Cancelar
</Button>
</DialogActions>
</Dialog>
</div>
</div>
)
}
}
I have put console.log() statements right before calling <ProductPricesEntry> from <ProductPrices>, and inside <ProductPricesEntry> when rendering, and I can see that both console.log() statements are reached the first time, but the one inside <ProductPricesEntry> is not reached if this.props.currentProductPrices changes:
This is the value of this.props.currentPrices that is different, and I can see the change on Redux Tools:
The problem is that console.log() statement inside <ProductPricesEntry> is never reached, which means that it does not rerenders, in despite that the Redux state value that changed is sent to the component as a props, and displayed inside.
I guess I am doing something wrong, but I can't find it.
EDIT
This is the reducer that changes the state that must cause the rerendering:
case UPDATE_PRODUCT_PRICE_SUCCESS: {
if (state.currentPricesTable) {
let currentPricesTableProducts = [...state.currentPricesTableProducts];
let updatedProductIndex = currentPricesTableProducts.findIndex(product => product.id === action.payload.productPrice.id)
currentPricesTableProducts[updatedProductIndex]['next_price'] = action.payload.productPrice.next_price;
currentPricesTableProducts[updatedProductIndex]['due_date'] = action.payload.productPrice.start_date;
return {
...state,
currentPricesTableProducts: [...currentPricesTableProducts],
alert: {type: ALERT_SUCCESS, message: "El precio se actualizó existosamente."},
showMessage: true,
}
} else if (state.currentProduct) {
let currentProductPrices = [...state.currentProductPrices];
let updatedProductPriceIndex = currentProductPrices.findIndex(productPrice => productPrice.prices_table_product === action.payload.productPrice.prices_table_product)
currentProductPrices[updatedProductPriceIndex].next_price = action.payload.productPrice.next_price;
currentProductPrices[updatedProductPriceIndex].due_date = action.payload.productPrice.start_date;
return {
...state,
currentProductPrices: [...currentProductPrices],
alert: {type: ALERT_SUCCESS, message: "El precio se actualizó existosamente."},
showMessage: true,
}
} else {
return {
...state
}
}
}
As you can see, I replace the state variable currentProductPrices whit a brand new array.
I added a console.log() just before returning from the reducer, and I can see that the data is right. I can see the change:
I could never make it work as it was, but I found a wait around the problem, and I am sharing it in case it was useful for anyone.
I basically connected <ProductPricesEntry> to Redux store instead of sending the data as props from the parent.
class ProductPricesEntry extends React.Component {
constructor(props) {
super(props);
this.state = {
updateDialogOpen: false,
newPrice: null,
newDate: null,
price: null,
}
this.price = null;
this.handleUpdateClick = this.handleUpdateClick.bind(this);
this.handleDialogAcceptClick = this.handleDialogAcceptClick.bind(this);
this.handleDialogCancelClick = this.handleDialogCancelClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleUpdateClick = () => {
this.setState({updateDialogOpen: true});
}
handleDialogAcceptClick = () => {
this.props.updateProductPrice(
this.price.prices_table_product,
this.price.prices_table.id,
this.props.currentProductData.id,
this.state.newPrice, this.state.newDate
);
let price = {...this.state.price};
price.due_date = this.state.newDate;
price.next_price = this.state.newPrice;
this.setState({newPrice: null, newDate: null, updateDialogOpen: false, price: price});
}
handleDialogCancelClick () {
this.setState({newPrice: null, newDate: null, updateDialogOpen: null});
}
handleChange (event) {
this.setState({[event.target.name]: event.target.value})
}
render() {
this.price = this.props.currentProductPrices[this.props.index]
return (
<div key={this.props.index} style={{display: 'flex', background: 'white', backgroundColor: 'lightgray', marginTop: '2px', paddingLeft: '10px', paddingTop: '10px', paddingBottom: '5px'}}>
<div className='col-10'>
<div fullWidth>
<h3>{this.price.prices_table.name}</h3>
</div>
<div fullWidth style={{display: 'flex'}}>
{this.price.current_price?
<div style={{textAlign: 'right'}} className='col-4'><strong>{currencyFormatter.format(this.price.current_price)}</strong></div>:
<div style={{textAlign: 'right', color: 'orange'}} className='col-4'>Ninguno</div>
}
{this.price.due_date?
<div style={{textAlign: 'center'}} className='col-4'><strong>{this.price.due_date}</strong></div>:
<div style={{textAlign: 'center', color: 'orange'}} className='col-4'>Ninguno</div>
}
{this.price.next_price?
<div style={{textAlign: 'right'}} className='col-4'><strong>{currencyFormatter.format(this.price.next_price)}</strong></div>:
<div style={{textAlign: 'right', color: 'orange'}} className='col-4'>Ninguno</div>
}
</div>
<div fullWidth style={{display: 'flex'}}>
<div style={{textAlign: 'right'}} className='col-4'>Actual</div>
<div style={{textAlign: 'center'}} className='col-4'>Vigencia</div>
<div style={{textAlign: 'right'}} className='col-4'>Próximo</div>
</div>
</div>
<div className='col-1'>
<IconButton color="primary" aria-label={''.concat('update-price-', this.price.id)}>
<i className="zmdi zmdi-edit zmdi-hc-fw" onClick={this.handleUpdateClick} />
</IconButton>
<Dialog fullWidth open={this.state.updateDialogOpen} arialabelledby={''.concat('update-price-', this.price.id)}>
<DialogTitle id={"".concat("update-price-", this.price.id)}>Actualizar Precio</DialogTitle>
<DialogContentText>
<div style={{paddingLeft: '25px'}}><h2>{this.props.currentProductData.name}</h2></div>
<div style={{paddingLeft: '25px'}}><h2>{this.price.prices_table.name}</h2></div>
</DialogContentText>
<DialogContent>
<FormControl fullWidth>
<InputLabel htmlFor="newPrice">Precio</InputLabel>
<Input
type="number"
id="newPrice"
name="newPrice"
value={this.state.newPrice}
onChange={this.handleChange}
startAdornment={<InputAdornment position="start">$</InputAdornment>}
/>
</FormControl>
<div fullWidth><TextField fullWidth label="Fecha" type="date" name="newDate" value={this.state.newDate} onChange={this.handleChange} /></div>
</DialogContent>
<DialogActions>
<Button onClick={this.handleDialogAcceptClick} name="accept" color="primary">
Aceptar
</Button>
<Button onClick={this.handleDialogCancelClick} name="cancel" color="secondary">
Cancelar
</Button>
</DialogActions>
</Dialog>
</div>
</div>
)
}
}
const mapStateToProps = ({inventory}) => {
const {
currentProduct,
currentProductData,
currentProductPrices,
} = inventory
return {
currentProduct,
currentProductData,
currentProductPrices,
}
}
export default connect(mapStateToProps, {updateProductPrice}) (ProductPricesEntry);
Now it works as intended.

how to create a file tree explorer/view using react js?

I have an react js application whose landing page(index page) allows the user to create a new folder or new view.
As seen in the screenshot the folders and views are displayed in the tile view format.I would like to change the view to a tree structure similar to the file explorer seen on ide such as visual studio code or eclipse.
My render function for the landing page-
render() {
const formList = localStorage.getItem("FormList") !== null ? JSON.parse(localStorage.getItem("FormList")) : [];
const { openmodal, newfolder, foldername, folderList, formView, alertMessage, alert } = this.state;
const folderid = this.props.history.location.pathname;
let fid = folderid.replace('/folder/', '');
return (
<div className="bacgrounImage">
<AlertFunction type={alert} msg={alertMessage} />
<Container fluid>
<Row>
<Col lg="12"
className="spilt folderheader"
>
<div style={{ paddingTop: '7px', paddingLeft: '3%' }}>
<NavLink to={fid === '/' ? "/formcreate" : '/formcreate/' + fid} >
<button className='butt' onClick={() => {
localStorage.setItem('viewId', null);
}} style={{ float: 'right', width: '14%', height: '43px', marginLeft: '10px' }} onClick={e => this.layoutset(e, null, null)}>
<h6 style={{ fontWeight: '500' }}>Create New View</h6>
</button>
</NavLink>
{newfolder === null &&
<button className='butt' type='button' onClick={this.folderName} style={{ width: '15%%', float: 'right' }} >
<img src={require('./image/newFolder.svg')} />
<span style={{ fontWeight: '500' }}>Create New Folder</span></button>
}
</div>
<div>
<h4>File List</h4>
</div>
</Col>
<Col lg='12' className='newfolder folderList'>
<div style={{ display: newfolder === 2 ? 'block' : 'none', padding: '8px 8px 16px 1px' }}>
<span style={{ padding: '6px 18px', cursor: 'pointer' }} onClick={e => this.backToForm(e)}><i className="fa fa-arrow-left" aria-hidden="true" ></i></span>
</div>
{(folderList !== undefined && folderList.length > 0) &&
folderList.map((val, i) => {
return <div key={i + "create"} className='list' id={val.id} onDoubleClick={() => this.folderClick(val.id, 1)}>
<img src={require('./image/folder.svg')} style={{ width: '48px' }} />
<span>{val.name}</span>
</div>
}
)
}
{(formView !== undefined && formView.length > 0) &&
formView.map((val, i) =>
<div key={i + "create"} className='list' id={val.id} onDoubleClick={() => this.folderClick(val.id, 2)}>
<img src={require('./image/file.svg')} style={{ width: '48px' }} />
<span>{val.name}</span>
</div>)
}
{
(folderList !== undefined && folderList.length === 0 && formView !== undefined && formView.length === 0) &&
<div className='noDataFound'>No data found </div>
}
{newfolder === 1 &&
<div className='list' style={{ backgroundColor: '#d3daff' }}>
<img src={require('./image/folder.svg')} style={{ width: '48px' }} />
<input value={foldername} onChange={e => this.setState({ foldername: e.target.value })} onKeyPress={this.createnewFolder} type='text' style={{ width: '72%', marginLeft: '2px', height: '27px' }} onFocus={this.handleFocus} />
</div>
}
</Col>
<div lg="12">
<Formlisting formList={formList} openmodal={openmodal} toggle={this.toggle} />
</div>
</Row>
</Container>
</div>
);
}
How do i modify the render function to change the view from the tile view to tree structure view as seen in the screenshot.Plz help?

Resources