Append data in same page in button click with react Js - reactjs

How can we list data from the array list on the same page in button click using react?
When user enter quantity setting value text box change event
class ProductList extends Component {
constructor(props) {
super(props);
this.state={
CartArray:[],
ProductList:[],
}
}
handleInputChange = event =>
{
const cart_values = event.target.name.split('-');
let newCart = {};
newCart["Key"]=cart_values[0]
newCart["ProductName"]=cart_values[1]
newCart["ProductBrand"]=cart_values[2]
this.setState(prevState => ({CartArray: [...prevState.CartArray, newCart]}))
}
viewCart = () => {
//What need to write here show data from CartArray:[] to my basket
}
}
Below is my render method. Numerical text box change i am setting in state value
render() {
return (
<div className="card" style={{ marginBottom: "10px"}}>
<div> <button className="btn btn-sm btn-warning float-right" onClick={this.viewCart}>View cart</button></div>
{this.state.ProductList.map((product, key) =>(
<div className="card-body">
<div className="card-title" key={key} value={key}>{product.ProductName}
<img src= {`data:image/jpeg;base64,${product.Image2}`} width="200" height="80" />{product.Brand}
<div>
<button className="btn btn-sm btn-warning float-right"
onClick={this.addToCart}>Add to cart</button>
<div>
<input type="number" min="0" pattern="[0-9]*" onInput={this.handleInputChange.bind(this)} name={`Name${key}-${product.ProductName}-${product.Brand}`} />
</div>
</div>
</div>
</div>
))}
</div>
)
}

If by show you mean to show on screen, not inside viewCart but in separate method render()
render(){
return(
<div>
{
this.state.CartArray.map((product) => {
<p>Key: {product.Key} </p>
<p>ProductName: {product.ProductName} </p>
<p>ProductBrand: {product.ProductBrand} </p>
})
}
</div>
);
}

Related

Modal not displaying on click (React)

I am trying to get a modal to function the modal I am trying to mirror is available here.
https://codesandbox.io/s/n9zn3n43o0
The button for the modal is displaying however the modal itself is not.
Here is my exact code for this function.
class App extends React.Component {
constructor(props) {
console.log("Props - ", props);
super(props);
this.state = {
modalVisible: false
};
this.openModal = this.openModal.bind(this);
}
openModal() {
console.log("Open modal called ", this.state.modalVisible);
const modalVisible = !this.state.modalVisible;
this.setState({
modalVisible
});
}
render() {
let styles = this.state.modalVisible
? { display: "block" }
: { display: "none" };
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button
type="button"
onClick={this.openModal}
className="btn btn-info btn-lg"
>
Open Modal
</button>
<div
id="myModal"
className="modal fade in"
role="dialog"
style={styles}
>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button
type="button"
onClick={this.openModal}
className="close"
>
×
</button>
<h4 className="modal-title">Modal Header</h4>
</div>
<div className="modal-body">
<p>Some text in the modal.</p>
</div>
<div className="modal-footer">
<button
onClick={this.openModal}
type="button"
className="btn btn-default"
>
Close
</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
And here is the code of the whole page
import React from "react";
import { Link } from "react-router-dom";
import Popup from "reactjs-popup";
import { Button, ButtonToolbar, Modal } from "react-bootstrap";
import ReactDOM from "react-dom";
import AddWorkstation from "./UpdateUserWorkStationDetailsForm";
class DisplayUserAcountDetails extends React.Component {
constructor() {
super();
this.state = { AccountDetails: [] };
}
// sets the questions form sql into state for questions
getItems() {
var user = window.localStorage.getItem("User");
if (user) {
fetch(`/profile-work-station-detailss/${user}`)
.then(recordset => recordset.json())
.then(results => {
this.setState({ AccountDetails: results.recordset });
});
} else {
alert("user not set");
}
}
//when the component mounts make the sql questions the
componentDidMount() {
this.setState({
AccountDetails: this.getItems()
});
}
render() {
try {
return (
<>
<h3 style={{ textAlign: "center" }}> Workstations</h3>
<button></button>
{this.state.AccountDetails ? (
<ul>
<App /> // calling it here
<Popup
style={{ width: "300px" }}
trigger={<button> Help?</button>}
closeOnDocumentClick
className={"tooltipBoundary"}
>
<AddWorkstation />
</Popup>
<Link to="/update-work-station-details">
<button style={{ float: "right" }}>+</button>
</Link>
<br />
<br />
{this.state.AccountDetails &&
this.state.AccountDetails.map(function(AccountDetails, index) {
return (
<div className="jumbotron">
<h3>Work Station</h3>
<li> Location: {AccountDetails.DeskLocation}</li>
<li>
ExtraInformation: {AccountDetails.ExtraInformation}
</li>
<li>
Primary Work Station:
{AccountDetails.PrimaryWorkStation}
</li>
<li> Date Added: {AccountDetails.PrimaryWorkStation}</li>
<li>
<Link to="/update-work-station-details">
<button>Update Account Details</button>
</Link>
</li>
</div>
);
})}
</ul>
) : (
<ul>
<div className="jumbotron">
<h3>Work Station</h3>
<li> Email: Null </li>
<li> Name: Null </li>
<li> Contact Number: Null </li>
<li>
<Link to="/update-work-station-details">
<button>Update Accoudnt Details</button>
</Link>
</li>
</div>
</ul>
)}
</>
);
} catch (e) {
console.log(e);
}
}
}
export default DisplayUserAcountDetails;
class App extends React.Component {
constructor(props) {
console.log("Props - ", props);
super(props);
this.state = {
modalVisible: false
};
this.openModal = this.openModal.bind(this);
}
openModal() {
console.log("Open modal called ", this.state.modalVisible);
const modalVisible = !this.state.modalVisible;
this.setState({
modalVisible
});
}
render() {
let styles = this.state.modalVisible
? { display: "block" }
: { display: "none" };
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button
type="button"
onClick={this.openModal}
className="btn btn-info btn-lg"
>
Open Modal
</button>
<div
id="myModal"
className="modal fade in"
role="dialog"
style={styles}
>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button
type="button"
onClick={this.openModal}
className="close"
>
×
</button>
<h4 className="modal-title">Modal Header</h4>
</div>
<div className="modal-body">
<p>Some text in the modal.</p>
</div>
<div className="modal-footer">
<button
onClick={this.openModal}
type="button"
className="btn btn-default"
>
Close
</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
I have tried multiple examples but this issue still persists.
Is there something I am missing ?
Any help greatly appreciated.
Hope this helps someone this is the code I have used instead and it worked fine.
class Header extends React.Component {
constructor(props) {
super(props);
this.handleClose = this.handleClose.bind(this);
this.handleShow = this.handleShow.bind(this);
this.state = {
show: false
};
}
handleClose() {
this.setState({
show: false
});
}
handleShow() {
this.setState({
show: true
});
}
render() {
// console.log(this.state);
return (
<div className="header-container">
<Button onClick={this.handleShow}>LOGIN</Button>
<Modal show={this.state.show} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal Header</Modal.Title>
</Modal.Header>
<Modal.Body>Modal Body</Modal.Body>
</Modal>
</div>
);
}
}

setState is not updating the state even callback

On input field change, the handler function gets called and updates the state, but the state is not getting updated. I know setState() is async so I put the console.log in the callback.
Here are the functions:
class WorkspaceEditModal extends React.PureComponent {
constructor(props) {
super(props);
console.log(props.selectedWorkspace); // prints correct value
this.state = {
editWorkspaceName: props.selectedWorkspace,
exists: false,
};
}
handleEditChange = event => { // this handler is called
console.log(event.target.value); // prints new value
this.setState({ editWorkspaceName: event.target.value },
() => {console.log(this.state.editWorkspaceName)}); // still prints old value
};
handleFocus = e => e.target.select();
handleKeyPress = e => {
if (e.key === 'Enter') {
e.preventDefault();
this.editWorkspace();
}
};
render() {
const { editWorkspaceName, exists } = this.state;
let content;
content = (
<div className="save-workspace">
<div className="modal-header">
<div className="modal-title">
<p>Rename Workspace</p>
</div>
<div className="modal-select">
<span className="input-label">Workspace Name</span>
<div>
<input
className="name-input"
placeholder="Workspace Name"
type="text"
defaultValue={editWorkspaceName}
onChange={this.handleEditChange} // calls the handler on change
onFocus={this.handleFocus}
onKeyPress={this.handleKeyPress}
autoFocus
/>
{notValid && (
<p className="invalid">
Only alphanumeric characters, hyphens, spaces, and
underscores are allowed.
</p>
)}
</div>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-default"
onClick={this.onCloseModal}
>
Cancel
</button>
<button
type="button"
className="btn btn-primary"
onClick={this.editWorkspace}
disabled={notValid}
>
Update
</button>
</div>
</div>
);
const contentStyle = {
width: '500px',
};
return (
<Modal
isOpen={true}
onClose={this.onCloseModal}
contentStyle={contentStyle}
shouldCloseOnOverlayClick={true}
>
{content}
</Modal>
);
}
}
I don't know why this is happening. This is crazy.
Thank you for your help.
You are passing down the default value of the input via props. That should be your input default value. It should not update the state of the child component.
State should be updated on the parent component, not the child in this case. The handleEditChange (handleChange in example) function should be placed in the parent component, then passed down via props to the input. You want the props value changed in the parent via that parent function so that setState works properly.
You could use getDerivedStateFromProps, but it seems unnecessary here. https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
class ParentWorkSpaceEditModal extends React.Component {
constructor(props) {
super(props);
this.state = {
editWorkspaceName: 'whatever your original value is',
exists: false,
};
}
handleChange = event => {
this.setState({ editWorkspaceName: event.target.value });
};
render() {
const { editWorkspaceName, exists } = this.state;
return (
<ChildWorkspaceEditModal editWorkspaceName={editWorkspaceName} exists={exists} handleChange={this.handleChange} />
)
}
}
const ChildWorkspaceEditModal = ({ editWorkspaceName, exists, handleChange )} => {
content = (
<div className="save-workspace">
<div className="modal-header">
<div className="modal-title">
<p>Rename Workspace</p>
</div>
<div className="modal-select">
<span className="input-label">Workspace Name</span>
<div>
<input
className="name-input"
placeholder="Workspace Name"
type="text"
value={editWorkspaceName}
onChange={handleChange}
/>
{notValid && (
<p className="invalid">
Only alphanumeric characters, hyphens, spaces, and underscores are allowed.
</p>
)}
</div>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-default"
onClick={this.onCloseModal}
>
Cancel
</button>
<button
type="button"
className="btn btn-primary"
onClick={this.editWorkspace}
disabled={notValid}
>
Update
</button>
</div>
</div>
);
const contentStyle = {
width: '500px',
};
return (
<Modal
isOpen={true}
onClose={this.onCloseModal}
contentStyle={contentStyle}
shouldCloseOnOverlayClick={true}
>
{content}
</Modal>
)
}

Reactjs not able to render a component which has a form

In my App.js, I have a class component Addition which will display 2 numbers and have a text box to get the result from the user. In the same file I have another class component App from which when I try to call <Addition/>, it renders the form perfectly as expected. However, I want the <Addition/> component to be triggered on a button click, which is not working.
class Addition extends Component{
render(){
return (
<form onSubmit={this.validateResult}>
<div >
<Box1 val={this.state.value1}/>
<Box1 val="+"/>
<Box1 val={this.state.value2}/>
<Box1 val="=" />
<input className="resbox"
value={this.state.result}
onChange={event => this.setState({result: event.target.value})}
required
/>
<br/>
<Box2 val={this.state.message} />
<br/><br/>
<input className="btn btn-info" type="submit" value="Submit" />
</div>
</form>
)
}
}
export default class App extends Component {
handleClick= (event) => {
event.preventDefault()
console.log("inside handleclick")
return (
<Addition />
);
}
render(){
return (
<div className="App">
<header className="row App-header">
<p >
KIDS MATHS
</p>
<div className="row col-2">
<button className="btn btn-lg offset-1" onClick={this.handleClick}> + </button>
</div>
</header>
</div>
)
}
}
When I tried to include the <Addition/> within the on-click event, the page simply remains same.
Please advice.
Everything you want to render has to called directly from within the render function. You can use conditional rendering to achieve to selective rendering of Addition. For this add a state member and set the value accordingly at the trigger point. This will call render again and the content will be shown as expected.
export default class App extends Component {
state = {
showAddition: false
}
handleClick= (event) => {
event.preventDefault()
console.log("inside handleclick")
this.setState({showAddition: true})
}
render(){
const { showAddition } = this.state
return (
<div className="App">
<header className="row App-header">
<p >
KIDS MATHS
</p>
<div className="row col-2">
<button className="btn btn-lg offset-1" onClick={this.handleClick}> + </button>
</div>
</header>
{showAddition && <Addition/>}
</div>
)
}
}
You can also consider to convert the components to function components and use useState instead of the state object. This will shorten the code a little bit.

Reactjs - Submitting multiple lines from one textarea

I'm trying to allow a textarea to take a list of names and display the submission of names on the page. However, I want the user to only be able to submit one name per line.
How would one go about this? More specifically, how would one grab the line breaks and split them into, say... an array to be mapped through and displayed in a dom element.
In my code the state of names is an empty string, but I think it would be easier/more manageable if it were an array.
Thanks!
class Content extends Component {
constructor(props) {
super(props);
this.state = {
names: ""
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleSubmit = (e) => {
e.preventDefault();
}
handleChange = (e) => {
this.setState({
names: e.target.value
});
}
render() {
return (
<section className="flex">
<div className="content flex">
<div className="sandbox flex">
<div className="directions">
<h1>Please enter a list of names.</h1>
<h3>Select a langauge at the top of the page.</h3>
</div>
<form id="nameForm" className="names flex">
<div className="form-group">
<textarea
id="names"
name="hard"
value={this.state.names}
cols={20}
rows={20}
onChange={this.handleChange}
wrap="hard">
</textarea>
</div>
</form>
<button id="formButton" form="nameForm" type="submit">Submit</button>
<div className="nametags flex">
<div className="nametags-group flex">
<button type="button" className="nametag">{this.state.names}</button>
<p className="greeting">Hello there, happy to see you back!</p>
</div>
<div className="nametags-group flex">
<button type="button" className="nametag">John Doe</button>
<p className="greeting">Hello there, happy to see you back!</p>
</div>
</div>
</div>
</div>
</section>
)
}
}
export default Content;
This code should work perfectly for you:
import React, { Component } from 'react'
class Content extends Component {
constructor(props) {
super(props)
this.state = {
names: ''
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleSubmit = name => {
alert(`Submitted name: ${name}`)
}
handleChange = e => {
this.setState({
names: e.target.value
})
}
render() {
return (
<section className="flex">
<div className="content flex">
<div className="sandbox flex">
<div className="directions">
<h1>Please enter a list of names.</h1>
<h3>Select a langauge at the top of the page.</h3>
</div>
<form id="nameForm" className="names flex">
<div className="form-group">
<textarea
id="names"
name="hard"
value={this.state.names}
cols={20}
rows={20}
onChange={this.handleChange}
wrap="hard"
/>
</div>
</form>
<button id="formButton" form="nameForm" type="submit">
Submit
</button>
<div className="nametags flex">
<div className="nametags-group flex">
{this.state.names
.split('\n')
.filter(n => n) // to filter out empty names
.map((name, index) => (
<button
key={index}
type="button"
className="nametag"
onClick={() => this.handleSubmit(name)}
>
{name}
</button>
))}
<p className="greeting">Hello there, happy to see you back!</p>
</div>
</div>
</div>
</div>
</section>
)
}
}
export default Content
I think it's easier to keep the name state as string.
When rendering the names, split the string at \n, filter out the empty names (basically those extra newlines without names), and render the rest.
When clicking on those name buttons, call handleSubmit and pass name as argument.
So the rest to do is what you want to do with those names in handleSubmit.
Something like this:
handleChange = e => {
this.setState({
names: e.target.value,
submitNames: e.target.value.split(/\r?\n/)
});
};
And change how you display buttons:
{ this.state.submitNames.map(
(name) =>
<button
onClick={() => this.handleSubmit(name)}
type="button"
className="nametag"
>
{name}
</button>
)}

How to change the state of an item affected by onClick in array?

I'm making a page where I need to make multiple selections of buttons (like a filter, which I'll use for the next page).
the information from these buttons is coming from an array and I'm using .map () to mount the button list.
My problem is how do I change the state of only the button that was clicked. The way it is now, when I click, all the buttons are active.
How can I solve this?
Thank you.
import React from 'react';
import { Link } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import messages from './messages';
import { getLevel, getDiscipline } from '../../functions';
import template from './index.pug';
export default class ConfigAssessment extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
constructor(props){
super(props);
this.state = {
level: getLevel(),
discipline: getDiscipline(),
active: '',
first_click: true,
}
}
changeActive = () => {
if (this.state.first_click === true) {
this.setState({
active: 'active',
first_click: false
});
} else {
this.setState({
active: '',
first_click: true,
});
}
}
render() {
return(
<div className="configuration">
<div className="config-title">
<i className="ti-settings" />
<h2>
<FormattedMessage {...messages.configAssessment} />
</h2>
</div>
<div className="config-items">
<div className="form-group">
<label>
<FormattedMessage {...messages.level} />
</label>
<div className="row">
{this.state.level.map((level, i) => (
<div className="col-xs-1 col-md-4 col-lg-3" key={level.id}>
<button
className={`btn btn-light-gray btn-block ${this.state.active}`}
id={level.id}
onClick={this.changeActive}
>
{level.level}
</button>
</div>
))}
</div>
</div>
<div className="form-group">
<label>
<FormattedMessage {...messages.discipline} />
</label>
<div className="row">
{ this.state.discipline.map((discipline, i) => (
<div className="col-xs-1 col-md-4 col-lg-3" key={i}>
<button
className={`btn btn-light-gray btn-block ${this.state.active}`}
onClick={this.changeActive}
>
{discipline.discipline}
</button>
</div>
))}
</div>
</div>
<div className="form-group">
<label>
<FormattedMessage {...messages.selectQuestion} />
</label>
<div className="row">
<div className="col-xs-1 col-md-4 col-lg-3">
<button
className={`btn btn-light-gray btn-block ${this.state.active}`}
onClick={this.changeActive}
>
<FormattedMessage {...messages.typeAutomatic} />
</button>
</div>
<div className="col-xs-1 col-md-4 col-lg-3">
<button
className={`btn btn-light-gray btn-block ${this.state.active}`}
onClick={this.changeActive}
>
<FormattedMessage {...messages.typeManual} />
</button>
</div>
</div>
</div>
<div className="form-group fg-right">
<Link className="btn btn-warning" to="#">
<FormattedMessage {...messages.createAssessment} />
</Link>
</div>
</div>
</div>
);
}
}
Create a separate component for button
class MyButton extends Component {
constructor(props){
super(props);
this.state = {
person: this.props.person
}
}
buttonActiveHandler = () => {
let oldStatus = this.props.person.status;
this.props.person.status = (!oldStatus ? 'active': '');
this.setState({
person:this.props.person
});
}
render() {
return (
<button className={this.state.person.status} onClick={this.buttonActiveHandler}>{this.state.person.name}</button>
);
}
}
export default MyButton;
Then import button component. use map function to for your code block
<div className={classes.Box}>
<h4>Lorem, ipsum.</h4>
{
this.props.survey.map((person, i) => {
return (
<MyButton key={i} person={person}/>
)
})
}
</div>
The easiest solution to this problem is making the component of the content inside the map and then handling the state of that component there. Hence it will maintain individual states.
It depends what you need.
You can create separate component for button with state.
You can also keep state of each button in react state as an array, and then you can get the state of each button by index.
I'd recommend the first solution, it'd easier to manage such state, but it will be harder to get the state of a specific button from the parent component.

Resources