I want to create a simple form using react. So I though I go with the onSubmit function of the form element, but as it turns out I don't get the form data. data of my handleSubmit function is empty. Why is that?
There is a fiddle that works: https://jsfiddle.net/everdimension/5ry2wdaa/ I don't see the difference.
export default function App() {
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const data = new FormData(e.target);
console.log('do the submitting', data)
}
return (
<div className="App">
<form onSubmit={handleSubmit}>
<label>
Media Plan
<input type="text" name="media-plan" placeholder="Media Plan" required />
</label>
<fieldset>
<legend>Time span selection</legend>
<label>
Start date
<input type="date" name="start-date" required />
</label>
<label>
End date
<input type="date" name="end-date" required />
</label>
</fieldset>
<fieldset id="submit">
<legend>Send options</legend>
<button type="submit" name="copy">
Copy plan
</button>
<button type="submit" name="save">
Save plan
</button>
</fieldset>
</form>
</div>
)
}
I had to read them this way, the formData object only appears empty.
const formData = new FormData(e.target)
for (var value of formData.values()) {
console.log(value);
}
Related
I need a redux-form render field where I can upload image with a preview thumbnail and get base-64 value.
Form
<form className="AddProductForm" onSubmit={handleSubmit(this.addProduct.bind(this))}>
<div className="form-group clearfix">
<img className="addProductImg pull-left" src="" height="200" alt="Image preview..." />
<input className="pull-right addProductImgBtn" type="file" onChange={previewFile} />
</div>
<div className="form-group">
<Field name="name" component={this.renderField} type="text" placeholder="Product name" />
</div>
<Button onClick={close}>Cancel</Button>
<button className='btn btn-primary addProductSave' type="submit" value="CONFIRM">Save</button>
</form>
File upload
function previewFile() {
var preview = document.querySelector('.addProductImg');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
let upImage = preview.src;
this.imageUrl = preview.src; // Base-64 value
}
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
I can get the base-64 value here, but I am unable to add this value into the existing field set.
Submit function
addProduct = (values) => {
console.log("Field values", values);
console.log("image base64 value", this.imageUrl);
}
Here inside addProduct function I want to get the image value with base64 encoding.
I have a form like this(simplified):
handleSubmit(e){
e.preventDefault();
}
render(){
return (
<form onSubmit={this.handleSubmit.bind(this)}>
<input type="text" maxLength="1"/>
<input type="text" maxLength="1"/>
<input type="text" maxLength="1"/>
<input type="text" maxLength="1"/>
</form>
)
}
As you can see, there is no button to submit a form since I want to automatically submit a form when a user filled all inputs.
Also, just to be clear, I'm not trying to find out how to submit a form with enter key.
How can I achieve this?
For an input create value attribute state and assign an onchange handler to the input. On every change set the state of the input state variable. If the value of all four of the state variables is set then call the handleSubmit function. Below is the sampple snippet.
class App extends React.Component {
constructor() {
super();
this.state = {
}
}
handleSubmit(){
console.log('Perform submit acction now');
}
handleChange(e) {
this.setState({[e.target.id]: e.target.value}, function() {
var obj = this.state
var count = 0;
if(Object.keys(this.state).length == 4) {
Object.keys(this.state).forEach(function(key){
if(obj[key] !== '') {
count++;
}
});
if(count == 4) {
this.handleSubmit();
}
}
});
}
render(){
return (
<form ref="form1" onSubmit={this.handleSubmit.bind(this)}>
<input type="text" id="inp1" maxLength="1" onChange={this.handleChange.bind(this)} value={this.state.inp1} />
<input type="text" id="inp2" maxLength="1" onChange={this.handleChange.bind(this)} value={this.state.inp2}/>
<input type="text" id="inp3" maxLength="1" onChange={this.handleChange.bind(this)} value={this.state.inp3}/>
<input type="text" id="inp4" maxLength="1" onChange={this.handleChange.bind(this)} value={this.state.inp4}/>
</form>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
Add a ref to each input. Inside the component have a state where you have ready:false and make it true when the last input as been filled and all other is filled to. Make an action who is ON only when the state ready:true.
With the ref you can see if each input has value. Something you can do too it's disabled the other input if the first one has no value. So you can track the filled stuff and see when they came to the last one you know you got your stuff.
With the small amount of detail you give, I just try to help you with an idea hope that can help you.
/* if inputs are automatically filled*/
f1=React.createRef()
componentDidUpdate() {
this.f1.current.submit();
}
render() {
return (<React.Fragment>
<Form action="localhost/bla-bla" method="POST" ref={this.f1}>
<Form.Control type="text" value="hello"/>
</Form>
</React.Fragment>
)}
is there any way to get value of checkbox using ref in React. Normal way return always value "on" to me.
var MyForm = React.createClass({
save: function(){
console.log(this.refs.check_me.value);
},
render: function(){
return <div><h1>MyForm</h1>
<div className="checkbox">
<label>
<input type="checkbox" ref="check_me" /> Check me out
</label>
</div>
<button className="btn btn-default" onClick={this.save}>Submit</button>
</div>
}
});
For checkbox, use "checked" instead of "value":
var MyForm = React.createClass({
save: function () {
console.log(this.refs.check_me.checked);
},
render: function () {
return <div><h1>MyForm</h1>
<div className="checkbox">
<label>
<input type="checkbox" ref="check_me" /> Check me out
</label>
</div>
<button className="btn btn-default" onClick={this.save}>Submit</button>
</div>
}
});
As a result:
There is a classic way to catch the event and corresponding values with the help of:
event.target.checked, event.target.name
You can see an example:
class MyForm extends React.Component {
onChangeFavorite(event){
console.log(event.target.checked, event.target.name);
};
render(){
return (<div><h1>MyForm</h1>
<div className="checkbox">
<label>
<input type="checkbox" name="myCheckBox1"
onChange={this.onChangeFavorite}
defaultChecked={false} />
Check me out
</label>
</div>
<button className="btn btn-default" onClick={this.save}>Submit</button>
</div>)
};
};
You can make the checkbox a controlled element by listening to onChange and giving it a state value. Try the following:
var MyForm = React.createClass({
save: function(){
console.log(this.refs.check_me.value);
},
toggleCheckboxValue: () => {
this.setState({checkBoxValue: !this.state.checkboxValue});
},
render: function(){
return <div><h1>MyForm</h1>
<div className="checkbox">
<label>
<input type="checkbox" ref="check_me" value={this.state.checkboxValue} onChange={this.toggleCheckboxValue} /> Check me out
</label>
</div>
<button className="btn btn-default" onClick={this.save}>Submit</button>
</div>
}
});
whenever the checkbox is clicked it will run the toggleCheckboxValue function, which will toggle the value of this.state.checkboxValue.
Just don't forget to initialize the this.state.checkboxValue function in your code.
Note: As ivarni pointed out, you may want to control the checked value specifically for checkboxes rather than value. Though both solutions will work.
I'm not sure why you want it using ref specifically, but it can be done nativily:
import React from 'react';
function CheckBox() {
const [isSave, setIsSave] = React.useState(false);
const handler = (value) => {
console.log(value);
setIsSave(value);
};
return (
<div>
<input type="checkbox" onChange={(ev) => handler(ev.target.checked)} />
<label> Save me..</label>
</div>
);
}
export default CheckBox;
I have a login form that has required and email validation. If either of these validations fail, the error message is displayed and the error class is applied to the field.
These are applied as expected. When the user logs in, if the credentials fail, I want to manually add a validation error. This invalidates the form, and my message is displayed saying 'Email/password combination is not recognised', but the error class is not applied to the field - even though (loginForm.$submitted && !loginForm.email.$valid) evaluates to true.
What am I missing here?
js:
login() {
if (!this.$scope.loginForm.$valid) {
return;
}
this.authenticationService
.login(this.email, this.password)
.success((response) => {
//success code...
})
.error((response) => {
if (response.error === 'invalid_grant') {
this.$timeout(() => {
this.$scope.$apply(() => {
this.$scope.loginForm.email.$setValidity('invalidGrant', false);
});
});
}
});
}
html:
<form name="loginForm" ng-submit="loginController.login()" novalidate>
<input type="email" class="form-control" id="email" name="email" placeholder="Email" ng-model="loginController.email" required=""
ng-class="{error:loginForm.$submitted && !loginForm.email.$valid}" />
<div ng-show="loginForm.$submitted">
<span ng-show="loginForm.email.$error.required">Email field is required.</span>
<span ng-show="loginForm.email.$error.email">Email field is not valid.</span>
<span ng-show="loginForm.email.$error.invalidGrant">Email/password combination is not recognised.</span>
</div>
<!-- other fields... -->
<button type="submit">Sign In</button>
</form>
I am trying to add a "hidden" field to a basic form in Angular (using Firebase as the backend). I'm having trouble figuring out how to include this field as part of the array when the form is submitted. I want to include {type: 'Basic'} as part of the array. I've looked at the other related posts on this site, but am still unsure how to apply to my particular situation.
Any suggestions on how to do this?
Javascript:
myApp.controller('NewProjectCtrl', function ($location, Projects) {
var editProject = this;
editProject.type = 'Basic'; //this is the hidden field
editProject.save = function () {
Projects.$add(editProject.project).then(function(data) {
$location.path('/');
});
};
});
HTML:
<form>
<div class="control-group form-group">
<label>Name</label>
<input type="text" name="name" ng-model="editProject.project.name">
</div>
<label>Description</label>
<textarea name="description" class="form-control" ng-model="editProject.project.description"></textarea>
<button ng-click="editProject.save()" class="btn btn-primary">Save</button>
</form>
You don't need a hidden form field, just submit your value in your controller like this:
editProject.save = function () {
editProject.project.type = 'Basic';
Projects.$add(editProject.project).then(function(data) {
$location.path('/');
});
};
All attributes of your editProject.project will be submitted, as you may notice in the developer console.
I would structure the controller a bit different.. here is an example (I am considering you are using angular-resource, where Projects returns a Resource?):
myApp.controller('NewProjectCtrl', function ($location, Projects) {
$scope.project = new Projects({type: 'Basic'});
$scope.save = function () {
$scope.project.$save().then(function(data) {
$location.path('/');
});
};
});
<form ng-submit="save()">
<div class="control-group form-group">
<label>Name</label>
<input type="text" name="name" ng-model="project.name">
</div>
<label>Description</label>
<textarea name="description" class="form-control" ng-model="project.description"></textarea>
<input type="submit" value="Save" class="btn btn-primary" />
</form>
The save function will $save the new project resource (this is an default method and will make a POST on the given resource URL).