React bootstrap form not rendering spaces in text inputs - reactjs

I'm using react bootstrap components. I have form elements that follow this sort of structure:
class Example extends React.Component {
constructor (props) {
super(props)
this.state = {
name: '',
show: false
}
this.handleChange = this.handleChange.bind(this)
this.handleShow = this.handleShow.bind(this)
this.handleClose = this.handleClose.bind(this)
}
handleShow () {
this.setState({ show: true })
}
handleClose () {
this.setState({ show: false })
}
handleChange (e) {
this.setState({
[e.target.name]: e.target.value
})
}
render () {
return (
<div>
<Button bsStyle='success' onClick={this.handleShow}>Add New</Button>
<Modal show={this.state.show} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add New</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<FormGroup>
<ControlLabel className='form-input'>1. Provide Name</ControlLabel>
<FormControl onChange={this.handleChange} className='form-input' type='text' placeholder='Name' name='name' value={this.state.name} />
</FormGroup>
</form>
</Modal.Body>
</Modal>
</div>
)
}
}
When I type in the text input it removes the spaces e.g. I type 'hello world' but it renders 'helloworld'
I can't seem to find an answer for this.
Edit: I forgot to mention the form is rendering within a bootstrap modal, I don't know if that's what's causing the issue? I've just refactored my code and updated my example snippet to match.
Problem solved: The issue solved itself when we separated the button out so the button was not part of the component and we just return the modal.

import React, { Component } from 'react';
import { render } from 'react-dom';
import { FormGroup, ControlLabel, FormControl } from 'react-bootstrap'
class App extends Component {
constructor (props) {
super(props)
this.state = {
name: ''
}
this.handleChange = this.handleChange.bind(this)
}
handleChange (e) {
this.setState({
[e.target.name]: e.target.value
})
}
render () {
return (
<form>
<FormGroup>
<ControlLabel className='form-input'>1. Provide Name</ControlLabel>
<FormControl onChange={this.handleChange} className='form-input' type='text' placeholder='Name' name='name' value={this.state.name} />
</FormGroup>
</form>
)
}
}
render(<App />, document.getElementById('root'));

Related

How do i display booking details on confirmation page using mern stack

I am a beginner in programming. I am building an appointment booking system using mern stack. I have created the booking form which sends data to the database, now i need to display the booking details ona confirmation page,which i am finding difficult. please this is where i need some help
import React, { Component } from 'react';
import axios from 'axios';
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'
import { Link } from 'react-router-dom';
class Form extends Component {
constructor() {
super();
this.handleChange = this.handleChange.bind(this);
this.handleDateChange = this.handleDateChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this);
}
state = {
name: "",
service: "finance",
date: new Date(),
cost: "3"
};
styles = {
fontSize: 50,
fontWeight: "bold",
color: "blue"
}
//event to handle all inputs except datepicker
handleChange(e) {
const name = e.target.name;
const value = e.target.value;
//to update the input state
this.setState({ [name]: value });
}
//event to handle datepicker input
handleDateChange(date) {
//update the date state
this.setState({
date:date
})
}
handleSubmit(e) {
e.preventDefault()
//console.log(this.state);
if(this.state.value !== ""){
alert('booking success')
}
axios.post('http://localhost:5000/api', this.state)
.then(res => {
console.log(res)
})
.catch((error) => {
console.log(error)
})
this.setState({ name: '', service: '', date: '', cost: '' })
}
render() {
return (
<form className='form' onSubmit={this.handleSubmit}>
<h2 style={this.styles}>Create appointment</h2>
<div className="mb-3">
<label className="form-label">Name</label>
<input name='name' type="text" className="form-control" id="exampleFormControlInput1" value={this.state.name} onChange={this.handleChange} />
<label className="form-label">Service</label>
<input name='service' type="text" className="form-control " id="exampleFormControlInput1" value={this.state.service} onChange={this.handleChange} />
<label className="form-label"> Date</label>
<div>
<DatePicker
selected={this.state.date}
onChange={this.handleDateChange}
name='date'
/>
</div>
{/* <label className="form-label"> Date</label>
<input name='date'type="datetime-local" className="form-control" id="exampleFormControlInput1" value={this.state.date} onChange={this.handleChange} />
*/}
<label className="form-label">Cost</label>
<input name='cost' type="text" className="form-control" id="exampleFormControlInput1" value={this.state.cost} onChange={this.handleChange} />
</div>
<Link to={'/ConfirmBooking'} style={{ textDecoration: 'none' }}>
<input type="submit" value="Submit" className="btn btn-outline-success" />
</Link>
</form>
)
}
}
export default Form;
import React, { Component } from 'react';
import axios from 'axios';
import Form from './Form';
class ConfirmBooking extends Component {
constructor(props){
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
state = {
};
handleSubmit(e){
e.preventDefault();
axios.get('http://localhost:5000/api', this.state)
.then(res => {
console.log(res)
})
.catch((error) => {
console.log(error)
})
this.setState({ name: '', service: '', date: '', cost: '' })
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit} >
<h3>Booking review</h3>
</form >
</div>
);
}
}
export default ConfirmBooking
;
the first code is for the oking form which works fine. The one underneath is for displaying booking details but doesnt work. please kindly help me

Input react wrapper

I want to make a form for user data and I was asked to make a wrapper react components for each type of input. My problem is passing the handler to the input component.
This is my form:
import React from 'react';
import {addUser as addNewUser} from '../../services/index';
import {TextBox} from './TextBox'
interface AddUserProps{
}
interface AddUserState{
UserName:string,
}
export default class AddUser extends React.Component<AddUserProps, AddUserState> {
constructor(props:any) {
super(props);
this.state = {
UserName: '',
};
this.updateUserName = this.updateUserName.bind(this);
}
updateUserName(event: React.ChangeEvent<HTMLInputElement>) {
this.setState({UserName: event.target.value});
}
handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
console.log(this.state)
addNewUser(this.state)
}
render() {
return (
<div>
<form
className = "user-add-form"
onSubmit={(event) => this.handleSubmit(event)}
>
<h3>Adauga utilizatori:</h3>
<label htmlFor="userName">User Name:</label>
<TextBox name="userName" type="text" value={userName} handleChange={this.updateUserName}/>
<input type="submit" value="Add user"/>
</form>
</div>
)
}
}
export {AddUser};
And this is the input component that I made:
import React from 'react'
export function TextBox(props) {
return (
<div>
<input type={props.type}
name={props.name}
value={props.value}
onChange={(event) => props.HandleInput(event)}
/>
</div>
)
}
So what I don't know is how to pass the event handler to the input component, because as it is right now it can't find it.
It should exist in Textbox's props as handleChange as it's passed in the parent component. Does this not work?
<input
type={props.type}
name={props.name}
value={props.value}
onChange={(event) => props.handleChange(event)}
/>

Getting Data From React-Bootstrap Input

I am not finding good docs or videos on how to get data from my inputs with React-Bootstrap. I want to be able to click the button and then bring what I typed into the input box into my onClick function.
import React from "react";
import Button from 'react-bootstrap/Button';
import './Search.css';
import InputGroup from 'react-bootstrap/InputGroup';
import FormControl from 'react-bootstrap/FormControl';
class search extends React.Component {
constructor(props){
super(props);
this.text = React.createRef();
this.searchChar = this.searchChar.bind(this);
}
searchChar = () => {
console.log("Button Clicked")
const value = this.input.current.value;
console.log(value)
}
render() {
return (
<div className="searchBar">
<form>
<InputGroup className="mb-3">
<InputGroup.Prepend>
<InputGroup.Text id="basic-addon1">Character Search</InputGroup.Text>
</InputGroup.Prepend>
<FormControl ref = {this.input}
placeholder="Character Name"
aria-label="Character Name"
aria-describedby="basic-addon1"
/>
</InputGroup>
<Button onClick={this.searchChar(this.input)} variant="outline-danger">Search </Button>
</form>
</div>
);
}
}
export default search;
Just try to write your input values in state
for example;
import React from "react";
import Button from 'react-bootstrap/Button';
import './Search.css';
import InputGroup from 'react-bootstrap/InputGroup';
import FormControl from 'react-bootstrap/FormControl';
class search extends React.Component {
constructor(props){
super(props);
this.state = {
basicAddon1 : null,
};
}
searchChar = () => {
console.log("Button Clicked")
const value = this.state.basicAddon1;
console.log(value)
}
render() {
return (
<div className="searchBar">
<form>
<InputGroup className="mb-3">
<InputGroup.Prepend>
<InputGroup.Text id="basic-addon1">Character Search</InputGroup.Text>
</InputGroup.Prepend>
<FormControl
placeholder="Character Name"
aria-label="Character Name"
aria-describedby="basic-addon1"
onChange={event => {
this.setState({
basicAddon1 : event.target.value
});
}}
value={this.state.basicAddon1 ? this.state.basicAddon1 : ""}
/>
</InputGroup>
<Button onClick={this.searchChar(this.input)} variant="outline-danger">Search </Button>
</form>
</div>
);
}
}
export default search;
you can create inputChangeHandler function or something else for improve your code
it just basic
The same way you deal with getting data from a form in pure React, you do with react-bootstrap. This answer here shows many options to do so.
My favourite approach among those options is this one. Using that approach your code would be something like:
class search extends React.Component {
constructor(props) {
super(props)
this.handleSave = this.handleSave.bind(this)
}
onChange(event) {
// Intended to run on the change of every form element
event.preventDefault()
this.setState({
[event.target.name]: event.target.value,
})
}
handleSave() {
console.log(`Do something with : {this.state.characterName}`)
}
render() {
return (
<div className="searchBar">
<form>
<InputGroup className="mb-3">
<InputGroup.Prepend>
<InputGroup.Text id="basic-addon1">
Character Search
</InputGroup.Text>
</InputGroup.Prepend>
<FormControl
name="characterName"
placeholder="Character Name"
aria-label="Character Name"
aria-describedby="basic-addon1"
onChange={this.onChange.bind(this)}
/>
</InputGroup>
<Button onClick={this.handleSave} variant="outline-danger">
Search{' '}
</Button>
</form>
</div>
)
}
}

React couldn't read the state

I used the same function I got on a react native in a react app and it didn't work, looks like I couldn't access the sate although I defined it in the constructor, the goal is to push data to firebase, I tried with random strings and it definitely works, it's just when using the form that it crashes.
As you can see I'm using text components to take a look a the state on the HTML page :
import React, { Component } from 'react';
import fire from './config/Fire';
class Home extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
isOpen: false,
title: '',
description: '',
loading: true
};
}
handleChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
saveData(e) {
e.preventDefault();
let title = this.state.title;
let description = this.state.description;
const { currentUser } = fire.auth();
fire
.database()
.ref(`/master/setup/`)
.push({ title, description })
.then(() => {
this.setState({ loading: false }).catch(error => {
console.log(error);
});
});
}
render() {
return (
<div>
<Container>
<Row>
<Col sm="2" lg="3" />
<Col sm="8" lg="6">
<h1>General Setup</h1>
<form>
<div class="form-group">
<label for="exampleInputEmail1">Title</label>
<input
value={this.state.title}
onChange={this.handleChange}
name="title"
class="form-control"
id="title"
placeholder="Enter event title"
/>
</div>
<div class="form-group">
<label for="exampleInputEmail1">Description</label>
<input
value={this.state.description}
onChange={this.handleChange}
name="description"
class="form-control"
id="description"
placeholder="Enter event description"
/>
</div>
<button onClick onClick={this.saveData} class="btn btn-primary">
Submit
</button>
</form>
<p>{this.state.title}</p>
<p>{this.state.description}</p>
<p>{this.state.loading.toString()}</p>
</Col>
<Col sm="2" lg="3" />
</Row>
</Container>
</div>
);
}
}
export default Home;
TypeError: Cannot read property 'state' of undefined
Please, someone, let me know what's going on with this code?
You can change saveData to an arrow function hence binding isn't required. This is an ES6 version, do something like below
saveData = e => {
e.preventDefault();
let title = this.state.title;
let description = this.state.description;
const { currentUser } = fire.auth();
fire.database().ref(`/master/setup/`)
.push({ title, description })
.then(() => {
this.setState({ loading: false})
.catch((error) => {
console.log(error);
})
});
}
You need to bind saveData in constructor.
this.saveData = this.saveData.bind(this);
You forgot to bind scope to saveData method.
Do it in constructor same as you bind it to handleChange method.
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.saveData = this.saveData.bind(this);
this.state = {
isOpen: false,
title: '',
description: '',
loading: true,
};
or
change saveData definition to one that uses arrow function syntax from ES6
saveData = (e) => {...function body as you already have it}
and parent scope will be bind for you by default

Use Popup to display Input Error message in React-Semantic-UI

It is possible to use the Popup Component to display the Input Errors in react Semantic UI?
Something like this
<Popup
content="Error Message"
trigger={
<Input placeholder='Name' />
}
/>
I think there is a way to achieve that, but not by using the PopUp component. To achieve that see the semantic-ui-react documentation on Forms with Label (pointing).
You can use the logic illustrated in the code below:
import React, { Component } from 'react'
import { Form, Label, Input, Button } from 'semantic-ui-react'
export default class MyCustomForm extends Component {
constructor(props){
super(props)
}
this.state = {
input1: 'some value',
input2: '',
errors: {
input1: 'Input 1 error message'
}
this.onChange = this.onChange.bind(this)
this.validate = this.validate.bind(this)
this.onSubmit = this.onSubmit.bind(this)
}
onChange(e, {name, value}){
const state = this.state
const { errors } = state
if(errors[name]){
delete errors[name]
}
this.setState(Object.assign({},...state,{[name]: value, errors }))
this.validate(name, value)
}
validate(name, value){
{/*
THIS SHOULD VALIDATE THE INPUT WITH THE APPROPRIATE NAME ATTRIBUTE
AND UPDATE THE ERRORS ATTRIBUTE OF THE STATE
*/}
}
onSubmit(e){
e.preventDefault()
{/* CLEAR THE ERRORS OF THE STATE, SUBMIT FORM TO BACKEND, THENj RESET ERRORS IF ANY */}
}
render() {
<Form size='small' key='mycustomform'>
<Form.Group>
<Form.Field error={errors.input1} required>
<label>Input1</label>
<Input name='input1' onChange={this.onChange}/>
{errors.input1 && <Label pointing color='red'>{errors.input1}</Label>}
</Form.Field>
</Form.Group>
<Form.Group>
<Form.Field error={errors.input2}>
<label>Input2</label>
<Input name='input2' onChange={this.onChange}/>
{errors.input2 && <Label pointing color='red'>{errors.input2}</Label>}
</Form.Field>
</Form.Group>
<Form.Field control={Button} onSubmit={this.onSubmit}/>
</Form>
}

Resources