Reputation: 77
I'm attempting to write data to cloud firestore using cloud functions but no matter what I do I'm getting an error message saying it's a bad request and its an invalid argument. I've tried changing the data.text
as my only thought is it's not the correct call. I've been following Net Ninja's tutorial but in his he only deals with one field.
Cloud Function
exports.addHack = functions.https.onCall((data, context) => {
admin.firestore().collection('Data').add({
name: data.text,
gender: data.text,
age: data.text,
email: data.text,
address: data.text,
number: data.text
})
});
Javascript
It's wrapped in a function because before the user presses the submit I have it check something and then it executes this function however that appears to work fine.
function submitHack() {
const formContainer = document.querySelector('#formContainer');
const addHack = firebase.functions().httpsCallable('addHack');
addHack({
name: document.getElementById("nameField").value,
gender: document.getElementById("genderField").value,
age: document.getElementById("ageField").value,
email: document.getElementById("emailField").value,
address: document.getElementById("addressField").value,
number: document.getElementById("phoneField").value
})
.then(() => {
formContainer.reset();
alert('Submission Successful! Enjoy your visit!')
})
.catch(error => {
alert(error.message);
})
}
HTML
This is the form with all of the inputs I'm trying to write to the database including the button
<section>
<h1>Registration</h1>
<div id="formContainer">
<div class="item">
<label>Full Name:</label><br>
<input type="text" id="nameField" placeholder="Enter Full Name">
</div>
<div class="item">
<label>Gender:</label><br>
<select id="genderField">
<option value="null" selected>Please Select...</option>
<option value="male">Male</option>
<option value="female">Female</option>
<option value="other">Other</option>
</select>
</div>
<div class="item">
<label>Age:</label><br>
<input type="number" id="ageField">
</div>
<div class="item">
<label>Email Address:</label><br>
<input type="text" id="emailField" placeholder="Enter Email Address">
</div>
<div class="item">
<label>Home Address:</label><br>
<textarea type="text" id="addressField" placeholder="Enter Home Address"></textarea>
</div>
<div class="item">
<label>Phone Number:</label><br>
<input type="text" id="phoneField" placeholder="Enter Phone Number">
</div>
<div class="item">
<input type="checkbox" id="checkbox">
<label>I accept the <a id="termsLink" href="https://imgur.com/5lXi3Lc" target="_blank">Terms and Conditions</a></label>
</div>
<button class="call" id="submit">Submit</button>
</div>
Error Message
{"error":{"message":"Bad Request","status":"INVALID_ARGUMENT"}}
Upvotes: 1
Views: 1073
Reputation: 83093
When calling the Callable Cloud Function as follows
addHack({
name: document.getElementById("nameField").value,
gender: document.getElementById("genderField").value,
...
})
you are passing an object with several properties.
So, in the Cloud Function, you need to use these properties, as follows:
exports.addHack = functions.https.onCall((data, context) => {
const name = data.name;
const gender = data.gender;
// ...
});
In addition, since it is a Callable Cloud Function which executes an asynchronous operation (the Firestore add()
method), you need to return a Promise. The data returned by the promise is sent back to the client.
So the following should do the trick (untested):
exports.addHack = functions.https.onCall((data, context) => {
const name = data.name;
const gender = data.gender;
// ...
return admin.firestore().collection('Data').add({
name,
gender,
// ...
})
.then(() => {
return {result: "success"}
})
.catch(error => {
// See https://firebase.google.com/docs/functions/callable#handle_errors
});
});
Of course you can also do:
exports.addHack = functions.https.onCall((data, context) => {
return admin.firestore().collection('Data').add({
name: data.name,
gender: data.gender,
// ...
})
.then(() => {
return {result: "success"}
})
.catch(error => {
// See https://firebase.google.com/docs/functions/callable#handle_errors
});
});
Finally note that it seems that you are not calling the submitHack()
function from the button. I would suggest you start by testing the Cloud Function with some constants, e.g. by doing:
const addHack = firebase.functions().httpsCallable('addHack');
addHack({
name: "test name",
gender: "testGender",
age: ... ,
// ...
})
and when you are sure it works, work on the "wiring" between the form and the Cloud Function call.
Upvotes: 2