onChange method not getting called from input - javascript

I am having a button from which I open the file explorer. I am doing it like this
{
this.props.fileUploadIsOpen
&& <div className='assign-dialog'>
<div className='assign-dialog-inner'>
<div className='dia-title'> File Upload</div>
<div className='dia-body'>
<div className='control-container'>
<div className='control-label'> Video File</div>
<div className='control'>
<input type="text" className="form-control" id="usr"/>
<button type="button" className="btn btn-primary" onClick={(e) => this.upload.click()}>Browse</button>
<input id="myInput" type="file" ref={(ref) => this.upload = ref} style={{visibility: 'hidden', width:0}} onChange={this.handleFileSelect}/>
</div>
</div>
But onChange method is not getting called. When I select a file, nothing happens. onChange method is supposed to called handleFileSelect function, which prints the file name in console. But nothing happens in console. Is onChange not getting triggered? How can I solve it?

I do not know why you are passing a function to the ref attr, but
I have recreated your case and it nails what you want
class Uploader extends React.Component {
constructor () {
super();
}
onClick (e) {
const {fileUpload} = this.refs;
fileUpload.click();
}
// prints the file name
handleFileSelect (e) {
const {fileUpload} = this.refs;
console.log(fileUpload.files[0].name)
}
render () {
return (
<div>
<div className='control-label'> Video File</div>
<div className='control'>
<input type="text" className="form-control" id="usr"/>
<button
type="button"
className="btn btn-primary"
onClick={this.onClick.bind(this)}>Browse</button>
<input id="myInput" type="file" ref="fileUpload" style={{visibility: 'hidden', width:0}} onChange={this.handleFileSelect.bind(this)}/>
</div>
</div>
);
}
}

Because you didn't call handleFileSelect function here and it call by your eventListener, you need to bind it, like this code:
this.handleFileSelect.bind(this)

Related

Delete/reset a displayed picture from vue js

i want to remove image src,
here is my template
<div class="file-upload-section">
<label id="preview" for="file-upload">
<img v-if="url" :src="url" />
</label>
<div class="file-upload">
<label class="file-upload-button" for="file-upload">Upload Image</label>
<input type="file" id="file-upload" #change="onFileChange"/>
</div>
<div v-if="url">
<button #click="removeImage()">Remove image</button>
</div>
</div>
this is my script
data: function () {
return {
url: null,
file: null
}
},
methods: {
onFileChange (e) {
this.file = e.target.files[0]
this.url = URL.createObjectURL(this.file)
},
removeImage: function () {
this.url = null
}
}
}
this is all i did, am i doing anything wrong or there is another way to delete a picture from a img
Your code is working; I tried it in my environment. It works perfectly. The issue could be re-rendering. I removed the "file" variable, as this seems no use based on your code, and I created scoped variable inside onFileChange function.
For a re-rendering issue to fix, add the key in your "img" tag and give it a unique value which will change on the "add" and "remove" image. In the below case, I use "URL" as a key.
<img :key="url" v-if="url" :src="url" />
Here is the code, give it a try:
<template>
<div class="file-upload-section">
<label id="preview" for="file-upload">
<img :key="url" v-if="url" :src="url" />
</label>
<div class="file-upload">
<label class="file-upload-button" for="file-upload">Upload Image</label>
<input type="file" id="file-upload" #change="onFileChange"/>
</div>
<div v-if="url">
<button #click="removeImage()">Remove image</button>
</div>
</div>
</template>
<script>
export default {
data: function () {
return {
url: null
}
},
methods: {
onFileChange (e) {
let file = e.target.files[0]
this.url = URL.createObjectURL(file)
},
removeImage: function () {
this.url = null
}
}
}
</script>
Edit:
On testing your code, I noticed the file preview does reset (the url variable), however the value of the input, did not. I assume that's what you mean, thus:
You can use a ref on the file input, and reset it as well.
Add a ref to your input:
<input type="file" id="file-upload" ref="file" #change="onFileChange"/>
Also, update your removeImage method accordingly:
removeImage: function () {
this.url = ""
this.$refs.file.value = ""
}
Pen here
In Vuejs in order to bind an event you should use v-on:click or in short way :click:
<button :click="removeImage">Remove image</button>
https://v2.vuejs.org/v2/guide/events.html

React: Get value of input[type=text] and output the value

I'm pretty new to React & JavaScript in general, and could use some help with a fairly simple thing:
I want to output the input value from my text <input> into my <h4> by hitting the update button. (Or something similar if that doesn't work)
return (
<div>
<div className="top-menu">
<div>
<h1>Progress</h1>
</div>
</div>
<div className="progress-container">
<h4>Progress: 43 %</h4>
<div className="progress-bar"></div>
</div>
<div className="inputs">
<label>Progress (in %)</label>
<div className="input">
<form>
<input id="progress" type="text" placeholder="e.g. 75" />
<button className="button">Update</button>
</form>
</div>
</div>
</div>
);
Thanks so much for your help!
Create some progress state and use the form's onSubmit callback to update state and clear the input value. Render the progress state into the h4 tag.
function App() {
const [progress, setProgress] = useState(43); // <-- progress state
return (
<div>
<div className="top-menu">
<div>
<h1>Progress</h1>
</div>
</div>
<div className="progress-container">
<h4>Progress: {progress} %</h4> // <-- render progress state
<div className="progress-bar"></div>
</div>
<div className="inputs">
<label>Progress (in %)</label>
<div className="input">
<form onSubmit={e => { // <-- form submit callback
e.preventDefault(); // prevent default form action so page doesn't reload
const { value } = e.target.progress;
setProgress(value); // update state
e.target.progress.value = ''; // reset input value
}}>
<input id="progress" type="text" placeholder="e.g. 75"></input>
<button type="submit" className="button">Update</button> // <-- type = submit
</form>
</div>
</div>
</div>
);
}

Prevent Page Reload When File Input Clicked

I appreciate anyone's response and suggestions. I have a react component that loads a form to edit a product. When the component is mounted, it will receive props from another function and I use these values within the prop as default value of the input fields in the form. I also have an input element that accepts uploading a file. When the file is selected, the component seems to be refreshing and setting other input fields to their default values. Here is my component:
<form onSubmit={handleSubmit}>
<div className="form-row">
<div className="col-md-4 mt-md-2">
<input
type="text"
className="form-control"
name="name"
placeholder="Name"
defaultValue={product!.name}
ref={register({
required: true,
pattern: /^[a-zA-Z ]*$/,
})}
/>
</div>
<div className="col-md-4 mt-2 mt-md-2">
<input
type="text"
className="form-control"
name="qty"
placeholder="Quantity"
defaultValue={product!.qty}
ref={register({ required: true, pattern: /^[0-9]+$/ })}
/>
</div>
</div>
<div className="form-row">
<div className="col-md-4 mt-2 mt-md-2">
<div className="input-group">
<div className="custom-file">
<input
type="file"
className="custom-file-input"
name="posImg"
id="img"
title="Add image to product if it is a menu item"
onChange={handleImg}
/>
<label
className="custom-file-label"
htmlFor="img"
aria-describedby="inputGroupFileAddon02"
>
{fileLabelState}
</label>
</div>
</div>
</div>
</div>
<div className="d-flex justify-content-end mt-2">
<button
type="submit"
className="btn zaad justify-content-end"
title="Submit product edit"
>
Update
</button>
</div>
</form>
The issue is when I choose the file and click on select, all the other input fields are reset to their default values. Here is my handleImg function:
const handleImg = (e: any) => {
e.preventDefault();
const file = e.target.files[0];
setFileLabelState(e.target.files[0].name);
setFile(file);
};
I have tried to work with the e.preventDefault(), but I have had no chance so far. Any suggestions on how I can go about this?
Thank you again.
EDIT:
I fixed the form handler and now here is my handleSubmit function:
const handleSubmit = (event: any) => {
event.preventDefault();
event.stopPropagation();
let editedProd = new FormData();
let isMenu: string = event.menuItemOption === "yes" ? "true" : "false";
editedProd.append("name", event.name);
editedProd.append("qty", event.qty);
editedProd.append("img", file);};
const handleSubmit = event => {
event.preventDefault();
let editedProd = new FormData();
let isMenu: string = event.menuItemOption === "yes" ? "true" : "false";
editedProd.append("name", event.name);
editedProd.append("qty", event.qty);
editedProd.append("img", file);};
}
try this answer note here i change (event: any) to event. this is working code from my project

How can i connect a submit button to 2 inputs in react?

I've tried using onSubmit on both the inputs and the submit button but I know that's wrong. and I've tried connecting the functions to the inputs. I've seen examples of people using https links to get it posted but I just want to be able to change the color and text when you click submit.
this.state = {
deftextcolor: "green",
text: "Color Me"
}
}
colorchanger(newcolor) {
this.setState({deftextcolor: newcolor})
}
textchanger(newtext) {
this.setState({text: newtext})
}
render() {
return (
<div className='colorer-wrapper'>
<h1 style={{color: this.state.deftextcolor}}>{this.state.text}</h1>
<input type="text"/>
<input type="text"/>
<button type="submit">Submit</button>
</div>
);
}
}
here some example:
const App =()=>{
const [state,setState] = React.useState({bgColor:"",textColor:"",color:"white",backgroundColor:"red"});
const handleChange = (e)=>{
const {target} = e
setState(current =>({...current,[target.name]:target.value}))
}
const onSubmit = (e)=>{
e.preventDefault();
if(state.bgColor.length>0 && state.textColor.length>0)
setState((current)=>({bgColor:"",textColor:"",color:current.textColor,backgroundColor:current.bgColor}))
}
return (<div><form style={{backgroundColor:state.backgroundColor,color:state.color}} onSubmit={onSubmit}>
<div>test style color</div>
<input type="text" name="bgColor" placeholder="background color" value={state.bgColor} onChange={handleChange}/>
<input type="text" name="textColor" value={state.textColor} onChange={handleChange} placeholder="text color"/>
<button type="submit">Apply style </button>
</form></div>)
}
ReactDOM.render(<App/>,document.getElementById("root"))
form{
width:100vw;
height:100vh
}
<script src="https://unpkg.com/react#16/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.production.min.js" crossorigin></script>
<div id="root"></div>
remenber you need to store event in variable because react update state asynchronously so the event will be gone.
Two places you can wire with onSubmit,
wire it with a button directly
<button onClick={onSubmit} />
wire it with form
<form onSubmit={onSubmit}>
<button type="submit" />
</form>
Your function needs to look like
const onSubmit = (e) => {
// do something. here
}
In your case, you also want to pass something into this function, so either calling handleSubmit directly or <button onClick={ e=> { colorchanger(color) } />
Like this:
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
deftextcolor: "green",
text: "Color Me",
defInput: '',
textInput: ''
}
}
handleChange = (e) => {
this.setState({[e.target.id]: e.target.value})
}
handleSubmit = () => {
this.setState((state) => ({
deftextcolor: state.defInput,
text: state.textInput,
defInput: '',
textInput: ''
}))
}
render() {
return (
<div className='colorer-wrapper'>
<h1 style={{color: this.state.deftextcolor}}>{this.state.text}</h1>
<input type="text" value={this.state.defInput} onChange={this.handleChange} id="defInput"/>
<input type="text" value={this.state.textInput} onChange={this.handleChange} id="textInput"/>
<button type="submit" onClick={this.handleSubmit}>Submit</button>
</div>
);
}
}
export default App
You can attach the same method to both inputs to update state input values, and then another method to the button that uses state input values to update your other state properties.

Close form without reloading page when sending post request to backend API

This is probably a simple one, but I have a React front end and Express back end, and I'm sending data to my API through a form on the front end. I have two buttons, one Submit and one Close. The Close button has a click event handler that closes the overlay without leaving the page. I would like my Submit button to work the same using the onSubmit handler. However, even though my post requests goes through successfully, it never closes the overlay despite using the same function.
I can make the app work by using a res.redirect on my back end to the home page, but I'd ideally like to not have the page reload. Additionally, when I have my back end send any kind of data back using res.send() or res.json(), it loads the JSON data in my browser instead of processing it in my front end (e.g. showing all posts in my Posts.js component).
Relevant code:
Post route
router.post('/', (req, res) => {
Post.create(req.body)
.then(newPost => {
console.log("Success!")
res.status(201).json(newPost);
//res.redirect('http://localhost:3000');
})
.catch(err => {
console.log(err);
res.send(err);
})
})
Form and Close overlay function
handleClose(e) {
this.props.closeForm();
e.preventDefault();
}
render() {
const postForm =
<div className="form-popup" id="newPost">
<form action="http://localhost:5000/api/posts" method="post" className="form-container">
<h1>New Blog Post</h1>
<div className="formArea formtitle">
<label htmlFor="title"><b>Title</b></label>
<input type="text" placeholder="Blog Post Title" name="title" required />
</div>
<div className="formArea formlocation">
<label htmlFor="location"><b>Location</b></label>
<input type="text" placeholder="Location" name="location" required />
</div>
<div className="formArea postcontent">
<textarea placeholder="Your post here" name="bodyText" required />
</div>
<div className="formArea formsubmit">
<button type="submit" className="btn" onSubmit={this.handleClose} >Post</button>
<button type="submit" className="btn cancel" onClick={this.handleClose}>Close</button>
</div>
</form>
</div>
Two options
Recommended: Send the request by JavaScript using an Ajax call
Hacky solution: Insert an iframe tag in your page and have the form have it as a target
XHR
var xhr = new XMLHttpRequest();
xhr.open("POST", '/server', true);
//Send the proper header information along with the request
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() { // Call a function when the state changes.
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
// Request finished. Do processing here.
}
}
xhr.send("foo=bar&lorem=ipsum");
iframe
<iframe name="formTarget" style="display:none;"></iframe>
<form action="http://localhost:5000/api/posts" method="post" target="formTarget">
<!--Your inputs and other form contents-->
</form>
Your issue has nothing to do with Node.js. Read about controlled components and axios.
To do it the react way, change your code to the following:
import React from 'react';
import axios from 'axios';
class YourComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
title: '',
location: '',
bodyText: ''
};
handleOnInputChange = (event)=> {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmitForm = ()=> {
const { title, location, bodyText } = this.state;
axios.post('http://localhost:5000/api/posts', {
userName: name,
userLocation: location,
text: bodyText
})
.then(response=> {
//Do something with the response
console.log(response)
})
.catch(error=>{
//Do something with the error
console.log(error)
})
}
}
render(){
<div className="form-popup" id="newPost">
<form className="form-container">
<h1>New Blog Post</h1>
<div className="formArea formtitle">
<label htmlFor="title"><b>Title</b></label>
<input type="text" placeholder="Blog Post Title" name="title" required value={this.state.title} onChange={event => this.handleOnInputChange(event)} />
</div>
<div className="formArea formlocation">
<label htmlFor="location"><b>Location</b></label>
<input type="text" placeholder="Location" name="location" required value={this.state.location} onChange={event => this.handleOnInputChange(event} />
</div>
<div className="formArea postcontent">
<textarea placeholder="Your post here" name="bodyText" required onChange={event => this.handleOnInputChange(event}>{this.state.bodyText}</textarea>
</div>
<div className="formArea formsubmit">
<button type="button" className="btn" onSubmit={this.handleSubmitForm} >Post</button>
<button type="button" className="btn cancel" onClick={this.handleClose}>Close</button>
</div>
</form>
</div>
}
}
export default YourComponent

Categories