Is there a way to destructure and access the middle elements? - javascript

On a React component I have a form that, when submitted, calls the following function, where I want to extract the data from the form:
const onSubmitFormData = (event) => {
// 1. Manual way
const formData = {
name: event.target.name.value,
email: event.target.email.value,
password: event.target.password.value,
}
// 2. Automated way??
const {name: {value}, email, password} = event.target.${}.value;
//...
}
What I wanted was to use destructuring to get the values from the ids on the form. The problem is that, for each id, I have to get id.value. And if there were 1000 fields on the form, it would be tedious and error prone to write the code as in the manual way...ofc I'm assuming there would be someone willing to fill that 1000-field form!
Jokes aside, is there a way to do this with destructuring or any similar way?

You can do it just by adding one line of code that:
Generates an array of elements with Object.values(form)
map each element to => [key, value]
So for element el it's el => [el.name, el.value]
Creates an object from that array with Object.fromEntries()
If the variable form references the form element then the line is:
Object.fromEntries(Object.values(form).map(el => [el.name, el.value]))
Then destructure away!
function logValues(e){
e.preventDefault();
const form = e.target
const formData = Object.fromEntries(Object.values(form).map(el => [el.name, el.value]))
const {name, email, password} = formData
console.log(`
Name: ${name}
Email: ${email}
Password: ${password}`)
}
<form id="test" onsubmit={logValues(event)}>
<input name="name" placeholder="Name">
<input name="password" placeholder="Password">
<input name="email" placeholder="Email">
<button>Log Values</button>
</form>

Related

Can't run UpdateDoc function when using Redux and FireBase

PersonalSlice.js
export const updatePersonal = createAsyncThunk("personal/updatePersonal", async (id, {getState})=>{
const personalDoc = doc(db, "Personal", id)
await updateDoc(personalDoc, getState().personal.updatePersonal );
});
Main.js
const updateName = useSelector((state) => state.personal.updatePersonal.name);
const handleUpdateNameChange = (e) => {
dispatch(changeUpdatePersonalName(e.currentTarget.value))
}
const handleUpdateSubmit = (e) => {
e.preventDefault();
dispatch(updatePersonal({updateName , updateSurname, updateBirthday, updateStartDate, updateDepartment, updatePhone, updateMail}))
}
<Form onSubmit={handleUpdateSubmit}>
<p className="text-center" style={{ color: "#39ace7" }}>İsim</p>
<Form.Control
size = "sm"
type="text"
name="updatePersonal"
onChange={handleUpdateNameChange}
value={updateName}
required
autoFocus
/>
I can't send the data I want to update in the form to FireBase. My fault is most likely in the parameters.
If you are starting a new project and/or are not required to have your Firebase data loaded into redux, you might want to give reactfire a try before trying react-redux-firebase. In reference to the above function call ,if the profile object contains a key or a list of keys as parameters, you can populate those parameters with the matching value from another location on firebase.
Setting config like this:
userProfile: 'users', // where profiles are stored in database
profileParamsToPopulate: [
'contacts:users'
]
}
Results in profile with populated contacts parameter:
displayName: 'ABC',
email: 'abc#xyz.com',
contacts: [
{
email: 'efg#xyz.com',
displayName: 'EFG'
},
{
email: 'pqr#xyz.com',
displayName: 'PQR
}
]
}
Please check the link here to understand the parameters call usage and related questions Update Data in Firebase and Update function in Firebase for reference.Also check the helpful documentation for configuration for redux-firebase

Node.js - Using input parsed from form to route to a specific URL

I am trying to allow a user to enter their name and have it added to the URL.
for example if the users input is John it redirects the user to "/profile/John"
So far I have tried to define a variable name from the parsed input from my html form.
html code;
<h4>Search for your profile by entering your name below.</h4>
<form class="" action="/" method="post">
<input type="text" name="name" placeholder="Enter your name">
<button type="submit" name="button">Search</button>
</form>
Node code;
app.get('/',function(req,res){
var name = String(req.body.name);
});
app.post("/profile/:" + name, (req,res)=>{
var data = {
age: 19,
job: 'Student',
hobbies: ['Fishing','Video games','Anime','Basketball']
};
res.render('profile',{name: req.params.name, data: data});
});
But I get this error;
^
app.get('/profile/:' + name, (req,res)=>{
^
ReferenceError: name is not defined
app.get('/',function(req,res){
// var name = String(req.body.name);
});
Above is not necessary part.
You should handle like below
app.post("/profile/:name", (req,res)=>{
var name = String(req.params.name)
var data = {
age: 19,
job: 'Student',
hobbies: ['Fishing','Video games','Anime','Basketball']
};
res.render('profile',{name: req.params.name, data: data});
});
You can check the details in this question
you need to put name inside the path quotes,
like this
app.get('/profile/:name',(req,res) =>{ }
the : after / indicates that the next value is dynamic
check out ExpressJS - URL Building

Image to Base64 with NodeJS (Express)

I'm doing a test, and I need to convert an image to base64 to store in my DB
forget about DB, I just need the base64 as a string.
This is my form:
<form action="/cadastrado" method="POST">
<! -- other irrelevants inputs -->
<input type="file" name="input_file" id="input_file" onchange="converterParaBase64()" required><br>
<button type="submit" onclick="base64()">CADASTRAR</button>
</form>
This is my route after submit the form:
app.post("/cadastrado", (req, res) => {
const {input_nome, input_telefone, input_cpf, input_email, input_file} = req.body;
console.log(req);
return res.json({
nome: input_nome,
telefone: input_telefone,
cpf: input_cpf,
email: input_email,
// base64image: input_file.toBase64 (I need something like this)
});
});
I'm doing greate about using the strings inputs, like nome, telefone, cpf and email (variables in PT-BR)
But I can't say the same with input_file
When I console.log(req.body) i get this:
{
input_nome: '1',
input_telefone: '2',
input_cpf: '3',
input_email: '4',
input_file: 'levia.jpg'
}
I need to convert this levia.png image into base64 as a string.
How I can do it ?
UPDATE 1:
Seems like the image in json, is just the file name.
It is possible to convert in client-side and after send to server-side ?
Try this
var fs = require('fs');
app.post("/cadastrado", (req, res) => {
const {input_nome, input_telefone, input_cpf, input_email, input_file} = req.body;
console.log(req);
var bitmap = fs.readFileSync(input_file);
var base64File = new Buffer(bitmap).toString('base64');
return res.json({
nome: input_nome,
telefone: input_telefone,
cpf: input_cpf,
email: input_email,
base64image: base64File
});
});
so I figured out how to resolve my problem.
Kind of vicarious what I did. I don't know if in future this can result in a problem, so I want to share with you.
Basically I create a input and edit his value in client side. Of course, I don't want a big input with a Base64 code messing with my poor HTML, so I styled with display: none. This input is inside the form, and it is sent to my req.body.
Snippets
index.html page with form:
...
<input type="file" id="input_file" name="input_file" onchange="convBase64()" required />
...
script.js with some logic
...
document.getElementById('input_base64').value = `${stringBase64}`;
...
css to hide the input with encoded image:
#input_base64 {
display: none;
}
This invisible input is inside the form. When the form is submitted, the input value is sent to body of request.

push array of strings to mongoDB with mongoose

I am not sure how to go about saving an array of strings from an input field to mongoDB with mongoose.
Ideally I would like to enter text several times in the same input field that creates an array. So I would end up having something like this.
title: "This is my Title"
actions: [ "walking", "smiling", "laughing"]
EJS File:
<form action="/blogs" method="POST">
<input type="text" placeholder="title" name="title" id="title" >
<input type="text" name="actions" id="actions" >
<button >submit</button>
</form>
blog.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const blogSchema = new Schema(
{
title: {
type: String,
required: true,
},
actions: [
{
type: String,
},
],
},
{ timestamps: true }
);
const Blog = mongoose.model("Blog", blogSchema);
module.exports = Blog;
app.js
app.post('/blogs', (req, res) => {
const blog = new Blog ({
title: req.body.title,
actions: req.body.tags,
});
blog.save()
.then((result) => {
res.redirect('/blogs')
})
.catch((erro) => {
console.log(erro)
})
})
Any guide on how to approach this? Right now my only solution is to create multiple input fields, but that is not correct.
If the actions tags are predefined and specific you can use html select multiple. That way actions property will be sent as an array of strings
<form action="/blogs" method="POST">
<input type="text" placeholder="title" name="title" id="title" >
<label for="actions">Actions:</label>
<select name="actions" id="actions" multiple>
<option value="walking">walking</option>
<option value="smiling">smiling</option>
<option value="laughing">laughing</option>
</select>
<button >submit</button>
</form>
And inside the controller you handle this way
// req.body.actions is already an array.
const blog = new Blog(req.body);
blog.save()
.then((result) => {
res.redirect('/blogs')
})
.catch((erro) => {
console.log(erro)
})
If, in any case, you want to use a text input to write the actions separated by space or comma, the actions property will be sent as a string. Then you can convert the string to array inside the controller.
// In case of multiple spaces, replace with single space.
// Then split string to array of strings
let actions = req.body.actions.replace(/ +/g, " ").split(" ")
const blog = new Blog ({
title: req.body.title,
actions
});
// rest of code
Whatever you choose to do, the actions will be stored as array of strings in the database.
Possibly you are sending an array as a string to the mongo. You can check this by checking the type of req.body.tags like so:
console.log(typeof req.body.tags)
If this returns a String, make sure you send the content as JSON to the database.

How to update a document in Meteor with multiple input fields and a single update button

I've got a modal that pops up and lets the user update some fields in the collection. For example, it would have multiple input fields for a client's address (the modal has a single button to perform the update):
...
<input type="text" id="full-name-change-modal">
<input type="text" id="address-change-modal">
<input type="text" id="city-change-modal">
<input type="text" id="state-change-modal">
...
So if the user wants to change the full name of the client, the update would only include those fields where the appropriate input wasn't empty. In this case the update would read something like:
Collection.update({ _id: documentNameAddress._id}, {$set: {FullName: <name from input> }});
If the user wanted to change the address, city, state and zip, it'd need to read:
Demographic.update({ _id: documentNameAddress._id}, {$set: {Address: <address from input>, City: <city from input>, State: <state from input>, Zip: <zip from input> });
I'd rather not have a separate button for every field if possible. How could I do this?
You'll end up with one optional update for Collection and then you can build up update for Demographic based on the non-empty fields in the form:
Template.myTemplate.events({
'click button':function(ev){
var FullName = $("#full-name-change-modal").val();
if ( FullName ) Collection.update({ _id: documentNameAddress._id}, {$set: {FullName: FullName }});
var query = {};
var Address = $('#address-change-modal').val();
if ( Address ) query.Address = Address;
var City = $('#city-change-modal').val();
if ( City) query.City = City;
var State = $('#state-change-modal').val();
if ( State ) query.State = State;
if ( Object.keys(query).length ) Demographic.update(query);
}
});

Categories