redux get input text value - javascript

I have the following reactjs component.
class Login extends Component {
render() {
if (this.props.session.Authenticated) {
return (
<div></div>
);
}
return (
<div>
<input type="text" placeholder="Username" />
<input type="password" placeholder="Password" />
<input
type="button"
value="Login"
onClick={() => this.props.LoginAction("admin", "password")}
/>
</div>
);
}
}
The Login component makes use of a prop that is set via redux, named "session.Authenticated". If an user session is not authenticated, I present a couple of input fields (one for username and another for password) and a Login button. If I press on the Login button I want to emit an action with the username and password values, passed as parameters. Now, how do I get the values of the two input fields for the parameters ?
IOW, I want to remove the hardcoded "admin, password" in the above code with the values of the two input fields. How to achieve this ?
All the examples point to redux-form which is a new dependency that I do not want to add. I want to keep my dependencies minimal and so using only react, redux and react-redux in my project.

Something like this:
class Login extends Component {
constructor(props){
super(props);
this.state = {
model = {
login: "",
password: ""
}
}
}
render() {
if (this.props.session.Authenticated) {
return null;
}
return (
<div>
<input type="text" value={this.state.model.value.login} onChange={e => this.updateModel(e.target.value, 'login')}placeholder="Username" />
<input type="password" value={this.state.model.password }onChange={e => this.updateModel(e.target.value, 'password')} placeholder="Password" />
<input
type="button"
value="Login"
onClick={() => this.props.LoginAction(this.state.model.login, this.state.model.password)}
/>
</div>
);
}
updateModel(value, name){
var model = extend({}, this.state.model);
model[name] = value;
this.setState({model});
}
}

Related

react router redirect to self/same page

How to redirect in react router in self page. e.g I have a component ProfileUpdate it updates name & stores to backend. After successful update I want to redirect to same page but it's not working. Here is a sample code.
class ProfileUpdate extends Component {
constructor() {
super();
this.state = {
name: ''
};
}
onSubmit(e) {
e.preventDefault();
this.props.history.replace('/');
}
onChange(e) {
const name = e.target.value;
this.setState(() => ({
name
}))
}
render() {
return (
<form onSubmit={this.onSubmit}>
<div>
<h4>Display Name:</h4>
<div>
<input name='displayName' placeholder='Display name' type='text' value={this.state.name} onChange={this.onChange} />
</div>
</div>
<div>
<button type='submit'>Update</button>
</div>
</form>
);
}
}
Expected behaviour if I update name then click submit it will replace the route/redirect & name input should be empty.
But when I choose a different path to replace it works. e.g this.props.history.replace('/users') it works. But here this.props.history.replace('/'); it doesn't work.

Passing multiple input fields between React Form state-less component and state-full Root component

I'm a beginner with React and I'm attempting to make an address book application (front-end only, for now). I have my root component called App in the App.js file and I'm trying to move the form element from the root component into its own component (state-less I guess) in the AddContact.js file. I was able to find a way (searching SO) to pass the form input fields when the form is part of the root component to the form submit handler function. But I'm not able to do the same when the form element is part of a different component. Below are the App.js and AddContact.js files. How should I go about doing so? Preferably in the simplest way, while adhering to react/es6 best practices.
App.js
import React, { Component } from 'react';
import './App.css';
//import AddContact from './AddContact/AddContact';
//import './AddContact/AddContact.css';
import ContactList from './ContactList/ContactList.js';
import Cockpit from './Cockpit/Cockpit.js';
class App extends Component {
state = {
contacts:[]
};
addContactHandler = (event) => {
event.preventDefault();
//console.log(event.target[0].value);
//console.log(event.target.name.value);
const name = this.input1.value;
const phone = this.input2.value;
const email = this.input3.value;
let contacts = [...this.state.contacts];
if (name.length>0 && phone.length>0 && email.length>0){
let contact = {
name: name,
phone: phone,
email: email
};
contacts.push(contact);
console.log("contacts: ", contacts);
this.setState({
contacts:contacts
});
}
this.input1.value = '';
this.input2.value = '';
this.input3.value = '';
};
render() {
let contactList = null;
let contacts = [...this.state.contacts];
if (contacts.length > 0) {
contactList = (
<ContactList
contacts = {contacts}
/>
);
}
return (
<div className="App">
<Cockpit/>
<p>Add New Contact:</p>
<form className="AddContact" onSubmit={(event)=>this.addContactHandler(event)}>
<label>Name:
<input type="text" name="name" ref={(name) => {this.input1 = name}}/>
</label>
<label>Phone:
<input type="text" name="phone" ref={(phone) => {this.input2 = phone}}/>
</label>
<label>Email:
<input type="text" name="email" ref={(email) => {this.input3 = email}}/>
</label>
<input type="submit" value="Submit" />
</form>
{/* <AddContact submit={(event)=>this.addContactHandler(event)}/> */}
{contactList}
</div>
);
}
}
export default App;
AddContact.js
// Use at a later stage
import React from 'react';
import './AddContact.css';
const AddContact = (props) => {
return (
<div >
<p>Add New Contact:</p>
<form className="AddContact" onSubmit={props.submit}>
<label>Name:
<input type="text" ref={(name) => {this.input = name}}/>
</label>
<label>Phone:
<input type="text" ref={(phone) => {this.input2 = phone}}/>
</label>
<label>Email:
<input type="text" ref={(email) => {this.input3 = email}}/>
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
};
export default AddContact;
Moving the form element into its own dedicated component is a great approach. But don't try to handle the child component's form submit event from the parent component. The child component owns the form, it should handle its mutations and submission too. With that in mind, this is how I'd structure the components:
Your App renders the AddContact component.
For your AddContact component, don't pass an onSubmit handler to it. Instead, pass an onAdd handler that expects a contact object as its argument.
Make your AddContact component stateful! Is there any particular reason you would want it to be stateless? Make it stateful, let it handle form updates as part of its state (use Controlled Components). And finally, on the form onSubmit event, package up a contact object and call the props.onAdd handler with it.
This will be a cleaner, more rationally separated architecture for your components. The parent component shouldn't have to worry about a child component's form submit behavior, but should rather expect a nicely packaged up contact object.
Check this out: https://mn627xy99.codesandbox.io/
class AddContact extends React.Component {
state = {
name: "",
phone: "",
email: "",
}
submit = e => {
e.preventDefault();
this.props.onAdd(this.state);
// Clear the form
this.setState({name: "", phone: "", email: ""});
}
change = e => {
e.preventDefault();
this.setState({[e.currentTarget.name]: e.currentTarget.value});
}
render() {
return (
<div >
<p>Add New Contact:</p>
<form className="AddContact" onSubmit={this.submit}>
<label>Name:
<input type="text" name="name" onChange={this.change} value={this.state.name} />
</label>
<label>Phone:
<input type="text" name="phone" onChange={this.change} value={this.state.phone} />
</label>
<label>Email:
<input type="text" name="email" onChange={this.change} value={this.state.email} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
}

How to get data from multiple inputs and put it to the localStorage? React

class Register extends Component{
constructor(props) {
super(props);
this.submit = this.submit.bind(this);
}
submit(event) {
let username = document.getElementById('username');
let usernameValue = username.value;
localStorage.setItem('username', usernameValue);
}
render(){
return(
<div className="register-block">
<h4>Register</h4>
<div className="register-block">
<InputGroup>
<Input id="username" placeholder="username" />
<Input id="password" placeholder="password" />
<Input id="tel" placeholder="tel number" />
</InputGroup>
</div>
<Button color="primary" onClick ={this.submit}>Register</Button>
</div>
)
}
}
//At this point, I can put data only from input id="username". How can I get data from others inputs and store it in localStorage? Its educational project
You can do something like this:
let username = document.getElementById('username').value;
let password = document.getElementById('password').value;
let phone = document.getElementById('tel').value;
let data = [];
data['username'] = username;
data['password '] = password;
data['phone '] = phone;
localStorage.setItem('userdata', JSON.stringify(data));
// To retrieve data try this
data = JSON.parse(localStorage.getItem('userdata'));
First of all directly interacting with the DOM node in react is not a good idea. Secondly, You can make all your Inputs to be controlled and push the data in localStorage on submit like
class Register extends Component{
constructor(props) {
super(props);
this.submit = this.submit.bind(this);
this.state={
username: '',
password: '',
tel: ''
}
}
handleChange = (key, val) => {
this.setState({[key]: val})
}
submit(event) {
localStorage.setItem('registerData', JSON.stringify(this.state));
}
render(){
return(
<div className="register-block">
<h4>Register</h4>
<div className="register-block">
<InputGroup>
<Input id="username" placeholder="username" onChange={(val) => this.handleChange('username', val)} />
<Input id="password" placeholder="password" onChange={(val) => this.handleChange('password', val)}/>
<Input id="tel" placeholder="tel number" onChange={(val) => this.handleChange('tel', val)} />
</InputGroup>
</div>
<Button color="primary" onClick ={this.submit}>Register</Button>
</div>
)
}
}
Assuming your Input is a custom component, you must also look into How to pass data from child to parent component. Also check Controlled Vs UnControlled Components in React

Creating a form in React that saves data

I am trying to create a customer details form in react (currently using react-json-form) where I can reuse the values in the inputs to create a saved file that the app can refer to. I have created the form and can output the results but I am unsure how to save the input values for future use or call them back once they are saved.
If anyone has any suggestions or examples of a form that does this then I would be greatly appreciative.
My code is as follows:
import React, { Component } from 'react';
import JSONTree from 'react-json-tree';
import { BasicForm as Form, Nest, createInput } from 'react-json-form';
const Input = createInput()(props => <input type="text" {...props} />);
const UserFields = () => (
<section>
<h3>User</h3>
<div>Name: <Input path="name" /></div>
<div>Email: <Input path="email" /></div>
</section>
);
export default class ExampleForm extends Component {
state = { data: {} };
updateData = data => this.setState({ data });
render() {
return (
<Form onSubmit={this.updateData}>
<Nest path="user">
<UserFields />
</Nest>
<button type="submit">Submit</button>
<JSONTree data={this.state.data} shouldExpandNode={() => true} />
</Form>
);
}
}
A more simple solution would be to use a form, like a semanti-ui-react form, store the information to the state onChange, then convert the info to JSON for storage.
import { Form, Button } from 'semantic-ui-react'
export default class App extends Component {
constructor() {
super()
this.state = {
name: "",
email: ""
}
}
handleChange = (e, {name, value}) => {
console.log(name, value)
this.setState({[name]: value})
}
render() {
return (
<div>
<Form onSubmit={this.sendDataSomewhere}>
<Form.Field>
<Form.Input name="name" value={this.state.name} onChange={this.handleChange}/>
</Form.Field>
<Form.Field>
<Form.Input name="email" value={this.state.email} onChange={this.handleChange}/>
</Form.Field>
<Button type="submit">Submit</Button>
</Form>
</div>
)
}
}
I use a dynamic method of receiving the input from different fields using the name and val attributes. The values captured in state are then accessible by this.state.whatever
Hope this helped

How rerender cloned childs with new props after they are initially rendered

The idea is to make a form that will validate the inputs and put all the logic for validating inside the MyForm component. so the only thing that comes from the onsubmit call is a error object and a object with the form values.
i would also like to validate when the user clicks on submit and when the user touched a field with onBlur.
i would like to keep all the logic in MyForm
The problem is that i'm trying to figure out how to change the InputGroup props from MyForm component and display validation errors for example.
how can i change to props of the childs when the user clicks the submit button or a field is touched and call the handleBlur in InputGroup.
also tell me is this is a wrong approach
i managed to change the props of InputGroup from MyForm at runtime.
this will change the label of every child.
children = React.Children.map(this.props.children, (child) =>
React.cloneElement(child, {
label: 'foo'
})
)
...
return (
<form onSubmit={this.validate}>
{children}
</form>
)
NewCustomerContainer:
class NewCustomerContainer extends Component {
handleSubmit(errors, customer) {
// if errors is empty do something with customer
}
render() {
return (
<div className={shared.flexRow}>
<div className={shared.flexColumn}>
<ColumnHeader
headerTitle="New Customer" />
<MyForm formHandler={this.handleSubmit}>
<InputGroup
type="text"
label="Customer Name"
placeholder="Customer Name"
name="customerName"
isRequired={true} />
<InputGroup
type="text"
label="Customer Number"
placeholder="Customer Number"
name="customerNumber" />
<InputGroup
type="text"
label="Customer Email"
placeholder="Customer Email"
name="customerEmail"
isRequired={true}
validateOption="email" />
</MyForm>
</div>
</div>
)
}
}
export default NewCustomerContainer
MyForm
export class MyForm extends Component {
validate(e) {
e.preventDefault()
children = React.Children.map(this.props.children, (child) =>
React.cloneElement(child, {
label: 'foo'
})
)
// handle validation login here
// then call the parent function with the errors and values
this.props.testForm(errors, values)
}
render() {
const children = React.Children.map(this.props.children, (child) =>
React.cloneElement(child, {
})
)
return (
<form onSubmit={this.validate}>
{children}
</form>
)
}
}
InputGroup:
export class InputGroup extends Component {
handleBlur() {
// handle blur here
}
render() {
return (
<div className={shared.formGroup}>
<label className={shared.formLabel}>{this.props.label}</label>
<input className={shared.formError} type={this.props.type} name={this.props.name} placeholder={this.props.placeholder} onBlur={this.handleBlur} />
<span className={shared.formError}>{this.props.foo}</span>
</div>
)
}
}
i'm very new to React and i know i can use redux-form or a other plugin, but i want to challenge myself and understand the concept how children works. there are plenty of examples out there but they do not answer my questions
thanks in advance.

Categories