I am trying to get inputs value but something is wrong. No error, just an empty value on click. Please see the code below. Could someone explain what is wrong?
let tipController = (() => {
let DOMstring = {
inputAmount: "#bill_amount",
inputService: '#service_option',
inputPeople: '#people'
};
return {
getInput: () => {
return {
amount: parseInt(document.querySelector(DOMstring.inputAmount).value),
service: document.querySelector(DOMstring.inputService).value,
people: document.querySelector(DOMstring.inputPeople).value,
}
}
})();
// APP CONTROLLER
let appCtrl = ((tipCtrl) => {
let data = tipCtrl.getInput();
let test = () => {
console.log(data.amount);
console.log(data.service);
console.log(data.people);
};
document.querySelector('.submit').addEventListener('click', test);
})(tipController);
<input id="bill_amount" class="input" type="text" name="bill_amount">
<select class="input" id="service_option">
<option value="">-- Pick an option --</option>
<option value="exellent">Exellent</option>
<option value="good">Good</option>
<option value="ok">Ok</option>
<option value="bad">Bad</option>
</select>
<input class="input" type="text" name='people' id='people' placeholder="Number of people">
<button type='submit' class='submit'>Calculate</button>
Related
This form works correctly as a regular form - submitting retains the dropdown values. When I use RHF's reset() to load data from the URL parameters, The input boxes show the default values but the select fields do not reflect the default values.
The functionality I'm going for here, is to load the values from the URL querystring params, which look like this:
http://localhost:3000/search?search=dev&location=&environment=On-Site&job_type=Internship&industry=&industry_category=&date_posted=&offset=0&count=25
...effectively making it "stateless", so we're able to pass this URL to anyone and it loads the form values, performs the search, etc.
import React, { useContext, useEffect, useState, useRef } from "react";
import { useForm, Controller } from "react-hook-form";
import InputMask from "react-input-mask";
import useLookupService from "../../service/lookup_service";
const Search = props => {
const { onSearch } = props;
const lookupSvc = useLookupService();
const [searchFormDefaults, setSearchFormDefaults] = useState(null);
const [locationOptions, setLocationOptions] = useState([]);
const [jobTypeOptions, setJobTypeOptions] = useState([]);
const [workEnvironmentOptions, setWorkEnvironmentOptions] = useState([]);
const [industryOptions, setIndustryOptions] = useState([]);
const [industryCategoryOptions, setIndustryCategoryOptions] = useState([]);
const {
register,
setValue,
handleSubmit,
control,
reset,
formState: { errors }
} = useForm({
defaultValues: searchFormDefaults,
context: JobSearchForm.type,
resolver: validator.validateResolver
});
useEffect(() => {
loadData();
}, []);
useEffect(() => {
if (!window.location.search) {
return;
}
const queryParams = new URLSearchParams(window.location.search);
let defaults = Object.fromEntries(queryParams);
setSearchFormDefaults(defaults);
reset(defaults);
}, [reset]);
const loadData = async () => {
let [
jobTypesData,
workEnvironmentsData,
industriesData,
industryCategoriesData
] = await Promise.all([
lookupSvc.getJobTypes(),
lookupSvc.getWorkEnvironments(),
lookupSvc.getIndustries(),
lookupSvc.getIndustryCategories()
]);
setJobTypeOptions([
<option key={-1} value="">Please select...</option>,
jobTypesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setWorkEnvironmentOptions([
<option key={-1} value="">Please select...</option>,
workEnvironmentsData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIndustryOptions([
<option key={-1} value="">Please select...</option>,
industriesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIndustryCategoryOptions([
<option key={-1} value="">Please select...</option>,
industryCategoriesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
};
return (
<div>
<div>
<div>
Filters
</div>
<div>
<a onClick={onClearClick}>
Clear Filters
</a>
</div>
</div>
<form onSubmit={handleSubmit(onSearch)} autoComplete="off">
<div>
<div>
<div>
<label>Search</label>
</div>
<input type="text" {...register("search")} />
{errors.search && <span className="validation">{errors.search}</span>}
</div>
<div>
<div>
<label>Location</label>
</div>
<input type="text" {...register("location")} onChange={onLocationChange} />
{errors.location && <span className="validation">{errors.location}</span>}
</div>
<div>
<div>
<label>Work Environment</label>
</div>
<select {...register("environment")}>
{workEnvironmentOptions}
</select>
</div>
<div>
<div>
<label>Date Posted</label>
</div>
<Controller
control={control}
name="date_posted"
render={({ field }) => (
<InputMask {...field} mask="99/99/9999" />
)}
/>
{errors.date_posted && <span className="validation">{errors.date_posted}</span>}
</div>
<div>
<div>
<label>Job Type</label>
</div>
<select {...register("job_type")}>
{jobTypeOptions}
</select>
</div>
<div>
<div>
<label>Job Industry</label>
</div>
<select {...register("industry")}>
{industryOptions}
</select>
</div>
<div>
<div>
<label>Industry Category</label>
</div>
<select {...register("industry_category")}>
{industryCategoryOptions}
</select>
</div>
<button type="submit">
Search
</button>
</div>
</form>
</div>
);
};
export default Search;
Note that the selected values and display values are set to the same - a string such as "On-Site".
While debugging, the first useEffect() is firing and loading the data before the second one, with reset as its param. I thought perhaps the lists were being reloaded and wiping out the selected value, but I don't see evidence of that.
When setting a breakpoint on the return line of the component, searchFormDefaults contains the expected values, yet they're always set to the default value on the screen (the initial "Please select..." when they're created.)
This is what I see for searchFormDefaults on the final render:
{
"search": "dev",
"location": "",
"environment": "On-Site",
"job_type": "Internship",
"industry": "",
"industry_category": "",
"date_posted": "",
"offset": "0",
"count": "25"
}
I'm fairly new to react-hook-form so I'm sure I've done something goofy, but I'm unable to spot it or find an explanation anywhere.
Figured it out. Was just an async issue that a simple flag solved.
const [isDataLoaded, setIsDataLoaded] = useState(false);
...then in my data loading function:
const loadData = async () => {
let [
jobTypesData,
workEnvironmentsData,
industriesData,
industryCategoriesData
] = await Promise.all([
lookupSvc.getJobTypes(),
lookupSvc.getWorkEnvironments(),
lookupSvc.getIndustries(),
lookupSvc.getIndustryCategories()
]);
setJobTypeOptions([
<option key={-1} value="">Please select...</option>,
jobTypesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setWorkEnvironmentOptions([
<option key={-1} value="">Please select...</option>,
workEnvironmentsData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIndustryOptions([
<option key={-1} value="">Please select...</option>,
industriesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIndustryCategoryOptions([
<option key={-1} value="">Please select...</option>,
industryCategoriesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIsDataLoaded(true);
};
...and the hook that needs it:
useEffect(() => {
if (!isDataLoaded) {
return;
}
if (!window.location.search) {
return;
}
const queryParams = new URLSearchParams(window.location.search);
let defaults = Object.fromEntries(queryParams);
setSearchFormDefaults(defaults);
reset(defaults);
}, [reset, isDataLoaded]);
I have a svelte component where i want to connect a selected input with a declared attribute.
My problem is that the binding of the selected value of status to the attribute'status' declared in 'flightschedules' doesnt work.
The options are from the attribute questions: on-time, delayed, cancelled
Can somebody help me please ?
Here is my code (its a component to create form, e.g create a flightschedule):
<script>
import axios from "axios";
import { onMount } from "svelte";
export let params = {};
let flightschedule = {
timeofdeparture: "",
flightnumber: "",
gatenumber: "",
status: "",
privatejetline_id: null,
};
let questions = [
{ text: "on-time" },
{ text: "delayed" },
{ text: "cancelled" },
];
let selected;
let privatejetline_ids = [];
onMount(() => {
getPrivateJetLineIds();
selected = params.status;
});
function getPrivateJetLineIds() {
axios
.get("http://localhost:8080/flights/privatejetline")
.then((response) => {
privatejetline_ids = [];
for (let privatejetline of response.data) {
privatejetline_ids.push(privatejetline.id);
}
flightschedule.privatejetline_id = privatejetline_ids[0];
});
}
function addFlightSchedule() {
axios
.post("http://localhost:8080/flights/flightschedule", flightschedule)
.then((response) => {
alert("Flight Schedule added");
console.log(response.data);
})
.catch((error) => {
console.log(error);
alert(error);
});
}
</script>
<div class="mb-3">
<label for="" class="form-label">Status</label>
<select bind:value={flightschedule.status} class="from-select">
<option value="" disabled>-- Select Status --</option>
{#each questions as question}
<option value={selected} selected={selected===flightschedule.status}>{question.text}</option>
{/each}
</select>
</div>
Actually, no need for selected variable, just bind the flightschedule.status. Try following in REPL.
<script>
let flightschedule = {
timeofdeparture: "",
flightnumber: "",
gatenumber: "",
status: "",
privatejetline_id: null,
};
let questions = [
{ text: "on-time" },
{ text: "delayed" },
{ text: "cancelled" },
];
$: console.log('---->', flightschedule.status)
</script>
<div class="mb-3">
<label for="" class="form-label">Status</label>
<select bind:value={flightschedule.status} class="from-select">
<option value="" disabled>-- Select Status --</option>
{#each questions as question}
<option value={question.text}>{question.text}</option>
{/each}
</select>
</div>
<option value={selected} this line can’t be right. You’re binding all three options to the same value.
You probably want following:
<select bind:value={selected} class="from-select">
<option value="" disabled>-- Select Status --</option>
{#each questions as question}
<option value={question.text}>{question.text}</option>
{/each}
</select>
I need to have this feature, when the cancel button is clicked, all the previous inputs shall be cleared. I mean, if the value in the textfield or scroll-bar should be reset to default. This is how I got now, the value still exists even when I click the cancel button (<button type="delete" onClick={deleteFilter} >X</button>) although the filter is disabled:
const [stateSelected, setStateSelected] = useState('')
const [jobType, setJobType] = useState('');
const [type, setType] = useState('');
var states = statepicker.getStates('us');
document.body.style = 'position:absolute;';
const stateChange = e => {
setStateSelected(e.target.value)
}
const jobChange = e => {
setJobType(e.target.value)
}
const typeChange = e => {
setType(e.target.value)
}
function filterOn(){
if(filter.position != "" || filter.state != "" || filter.type != ""){
return true;
} else{
return false;
}
}
function deleteFilter(){
setFilter({
position: "",
state: "",
type: ""
})
}
const handleSignUp = useCallback(async event => {
event.preventDefault();
setFilter({
position: jobType,
state: stateSelected,
type: type
});
setFilterOpen(false);
setJob([]);
})
return (
<div>
<div className="settings__Section">
<div className="settings__SectionHeader">
Filter
</div>
<form onSubmit={handleSignUp}>
<input className="settings__inputBox" name="occupation" type="occupation" placeholder="Job Title" onChange={jobChange}/>
<select className="settings__inputSelect" onChange={stateChange} value={stateSelected}>
<option value={""} disabled={true}>Select State</option>
{
states.map(state => (
<option value={state} name="state">{state}</option>
))
}
</select>
<select className="settings__inputSelect" onChange={typeChange} value={type}>
<option value={""} disabled={true}>Select Job Type</option>
<option value={"Entry Level"} name="type">Entry Level</option>
<option value={"Internship"} name="type">Internship</option>
<option value={"Fellowship"} name="type">Fellowship</option>
<option value={"Apprenticeship"} name="type">Apprenticeship</option>
</select>
<button type="submit" className="settings__signBtn">Save Filter</button>
</form>
{filterOn() &&
<div>
<p>Position: {filter.position} Location: {filter.state} Job Type: {filter.type}</p>
<button type="delete" onClick={deleteFilter} >X</button>
</div>
}
</div>
</div>
);
<form onSubmit={handleSignUp}>
<input className="settings__inputBox" name="occupation" type="occupation" placeholder="Job Title" onChange={jobChange}/>
<select className="settings__inputSelect" onChange={stateChange} value={stateSelected}>
<option value={""} disabled={true}>Select State</option>
{
states.map(state => (
<option value={state} name="state">{state}</option>
))
}
</select>
<button type="submit" className="settings__signBtn">Save Filter</button>
<button type="reset" >X</button>
</form>
Try with reset button it does the thing here I suppose
Ok, although there is some lines missing in your code i think i know what the problem is.
The filter renders if either position, state, or type is different from empty string.
But when you delete the filter you are only resetting position and state:
function deleteFilter(){
setFilter({
position: "",
state: ""
})
}
So to fix it, just add type to this state function being called:
function deleteFilter () {
setFilter({
position: '',
state: '',
type: ''
})
}
I am trying to update my MongoDB database containing data for a project information form through a PUT request on my action, but I am unable to get the handleSumbit function on my component to call my project action. I am receiving a 404 error. I have no clue what I am missing or have done wrong. Any insight would be appreciated.
My Component:
import React, { useState } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import '../styles/ViewProject.css'
import { updateProjects } from '../actions/project.actions'
const EditProject = ({ project, match }) => {
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [projectName, setProjectName] = useState('')
const [projectType, setProjectType] = useState('')
const [multiple, setMultiple] = useState(false)
const [dueDate, setDueDate] = useState(Date)
const [url, setUrl] = useState('')
const [description, setDescription] = useState('')
const handleSubmit = e => {
e.preventDefault()
updateProjects(name, email, projectName, projectType, dueDate, url, description)
console.log('Data ', name, email, projectName)
}
return(
<form className="viewProjectContainer" onSubmit={handleSubmit}>
{project.map((task, i) => (
<div key={i++} >
{match.params.id === task._id ?
<div className="vp">
<div className="vpLeft">
<div className="vpTitle">
<input className='vpProjectName' defaultValue={task.projectName} onChange={e => setProjectName(e.target.value)} />
</div>
<div className="vpSub">
<p>Submitted by: </p>
<label>Name: </label>
<input className='vpName' defaultValue={task.name} onChange={e => setName(e.target.value)}/>
<label>Email: </label>
<input className='vpEmail' defaultValue={email} onChange={e => setEmail(e.target.value)}/>
</div>
<div className="vpDescription">
<label>{task.multiple === true ? "(Multiple)" : "Single"}</label>
<p>Project Type: </p>
<select className='formInput' onChange={e => setProjectType(e.target.value)} defaultValue={projectType}>
<optgroup label='Digital'>
<option value='banner'>Banner</option>
<option value='emailBlast'>Email Blast</option>
<option value='productImage'>Product Image</option>
<option value='socialMediaAd'>Social Media Ad</option>
<option value='video'>Video</option>
<option value='websiteMockup'>Website Mockup</option>
<option value='other'>Other (Please be specific in Description)</option>
</optgroup>
<optgroup label='Physical Product'>
<option value='bottleOpener'>Bottle Opener</option>
<option value='clothing'>Clothing</option>
<option value='keyChain'>Key Chain</option>
<option value='popSocket'>Pop Socket</option>
<option value='usb'>USB</option>
<option value='other'>Other (Please be specific in Description)</option>
</optgroup>
<optgroup label='Print'>
<option value='businessCard'>Business Card</option>
<option value='brochureBiFold'>Brochure - Bi-fold</option>
<option value='brochureTriSquare'>Brochure - Trifold Square</option>
<option value='brochureTriStandard'>Brochure - Trifold Standard</option>
<option value='catalogMore'>Catalog - Less than 50 pages</option>
<option value='catalogLess'>Catalog - More than 50 pages</option>
<option value='documentFull'>Document - Full Sheet</option>
<option value='documentHalf'>Document - Half Sheet</option>
<option value='flyer4x6'>Flyer - 4x6</option>
<option value='flyer5x7'>Flyer - 5x7</option>
<option value='flyer6x9'>Flyer - 6x9</option>
<option value='postCard4x6'>Post Card 4x6</option>
<option value='postCard5x7'>Post Card 5x7</option>
<option value='postCard6x9'>Post Card 6x9</option>
<option value='poster11x17'>Poster 11x17</option>
<option value='poster24x36'>Poster 24x36</option>
<option value='other'>Other (Please be specific in Description)</option>
</optgroup>
<optgroup label='Other'>
<option value='consultation'>Consultation</option>
<option value='labeling'>Labeling</option>
<option value='other'>Other (Please be specific in Description)</option>
</optgroup>
</select>
<div className="vpDescBox">
<textarea className='updateDescription' defaultValue={description} onChange={e => setDescription(e.target.value)}></textarea>
</div>
</div>
</div>
<div className="vpRight">
<div className="vpTicket">
<p>Ticket Number: {task.ticketNumber}</p>
<label>Submitted: {task.date} </label>
<label>Preferred due date: </label>
<input type='date' defaultValue={task.dueDate} onChange={e => setDueDate(e.target.value)}/>
</div>
<div>
<label>Reference links: </label>
<input type='text' defaultValue={task.url} onChange={e => setUrl(e.target.value)}/>
<label></label>
</div>
<div>
<p>Project Status:</p>
<p>Task Recieved: {task.recieved === true ? "Recieved" : "Not Revieved"}</p>
<p>Task in progress: {task.inProgress === true ? "In Progress" : "Not in Progress"}</p>
<p>Completed: {task.completed === true ? "Complete" : "Incomplete"}</p>
</div>
</div>
</div>: null}
</div>
))}
<div className='buttonsContainer'>
<button type='submit' className='projectViewButton1'><Link to={'/' + match.params.id}>Save</Link></button>
</div>
</form>
)
}
const mapStateToProps = state => ({
project: state.projects.project,
id: state.projects.id
})
export default connect(
mapStateToProps,
{ updateProjects }
)(EditProject)
My action:
export function updateProjects(name, email, projectName, projectType, dueDate, url, description) {
console.log('reducer ', name)
axios.put('api/projects/update/:id', {
name: name,
email: email,
projectName: projectName,
projectType: projectType,
// multiple: multiple,
dueDate: dueDate,
url: url,
description: description
}).then(resp => {
console.log("Data updated: ", resp.data)
})
}
My Backend:
// #route PUT api/projects/update/:id
// #desc Update projects
// #access Private
router.put('/update/:id', async (req, res) => {
try {
const {
name,
email,
projectName,
projectType,
multiple,
dueDate,
reference,
attachment,
description,
ticketNumber,
received,
inProgress,
completed
} = req.body
const project = await Project.findByIdAndUpdate(req.params.id, {
name,
email,
projectName,
projectType,
multiple,
dueDate,
reference,
attachment,
description,
ticketNumber,
received,
inProgress,
completed
})
res.json(project);
} catch (err) {
console.error(err.message)
res.status(500).send('Server Error')
}
})
Thank you for helping!
The endpoint you are hitting with the axios.put is api/projects/update/:id, which is incomplete. You should put your host as well. For example: http://localhost:8000/api/projects/update/:id
And also, you need to specify a proper value for :id in the URL. Not sure if you left that out in purpose for example's sake but just wanna point that one out too haha.
in your react project folder's package.json file :
"proxy":"http://localhost:8000"
your http url should be below :
axios.put('/api/projects/update/', {
params: {
id: 'value of id'
}
});
or :
axios.put(`/api/projects/update/${value of id}`)
Here i am emiting the form values to the server, which currently works fine.However i am unable to select other values from select input apart the default option...please help!
var Query = React.createClass({
getInitialState(){
return{
value:'Sunday'
}
},
change(e){
this.setState({value: e.target.value});
},
join() {
var memberName = React.findDOMNode(this.refs.name).value;
var dayz = React.findDOMNode(this.refs.day).value;
//emits name and day to the server....
this.props.emit('join',{ name: memberName, day: dayz });
},
render(){
return(
<div>
<form action="javascript:void(0)" onSubmit={this.join}>
<input ref="name" type="text" required/>
//unable to select other options apart the first (sunday => Wow)
<select ref="day" onChange={this.Change} value={this.state.value}>
<option value="sunday">Wow</option>
<option value="a">ssd</option>
<option value="Java">Java</option>
<option value="C++">C++</option>
</select>
<button>Join</button>
</form>
</div>
);
}
});
module.exports = Query;
There's a typo in the <select>: it has a capital 'C' rather than a lowercase 'c' like the name of the function. Update this.Change to this.change.
<select ref="day" onChange={this.change} value={this.state.value}>