I am building a web app and have a question to my drop down menu.
The goal is, that the data can only be submitted, when a number is selected in the dropdown menu.
Just check if the dropdown is set or not should be enough. If the input of the request is invalid, the correct response would be a 400.
app.get('/lbc.js', (req, res) => {
if (req.body.dropdown === undefined || req.body.dropdown === null)
res.status(400).send({ message: "Drop down was not selected" });
return;
}
// continue with whatever you want if submit is possible
}
Your frontend needs to handle this response as well, because now it probably won't make a distinction when it works or not. So if you'd capture the submit event of the form, you could send the request yourself using the fetch api, and do different things for a 200 (when the response succeeded) or something like a 400 (request failed).
EDIT:
You can read up on how to create and handle submit events here:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event
Here you can read how you can send webrequests through javascript:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
These are the steps you need to do:
Put an id on your form, e.g. <form id="myForm" ... >
Start a JavaScript tag i.e. <script> </script>
Within these tags, first get the form reference:
const form = document.findElementById("myForm");
Put a submit event listener on it like how they do in the link
In the event handler function, send the request, and deal with the response (show message if error, do something else if success for instance).
EDIT april 7th:
About your code and your comments I have the following to say:
You have created 2 forms, one for your dropdown and one for your button. Both of them should be in the same <form></form> tag. When you click your submit button, all <input> fields will be sent to whereever your form submits to.
You seem to need to check if all fields are filled in correctly before you send the data to your server. Like I said in my previous answer, you need to create a script that will do this. In this link you can read again in a simple way how to do such a thing
Checking if a field has a value is again done by obtaining the element through it's id. E.g. if you have an input like: <input type="text" id="firstName" name="firstName" />, you can obtain the value of this field in javascript as such: const valueFromField = document.getElementById("firstName").value;
Hopefully this will give you some hints to make some new steps.
In my humble opinion it would probably be a good idea for you to do some basic javascript tutorials to give you some insight on how that stuff works.
According to the given details, Try this.
You can check the value and perform your actions as below.
if(req.body && req.body.dropdown) {
res.send('submit is possible')
} else {
res.send('Please select the amount!')
}
Also use, POST method route
app.post('/test', function (req, res) {
res.send('POST request to the homepage')
})
Read more about Express.js routing
Related
I'm using HTML5 form validation to validate my form. So if I validate it using Javascript, I can do something like that:
if (isInvalid())
{
myControl.setCustomValidity("my error message");
}
And it's working fine. My doubt is about server-side validation. The form is posted back to the same page, and if an error is detected, the input control should be considered invalid from the start, something like that:
<input type="text" name="id" invalid error-message="This id is already used" />
I don't want to use AJAX to make this validation, because I would have to 'hijack' and cancel the form submit, make the validation using AJAX, and then submit the form in javascript.
It is always better to iterate over context
You are not using AJAX and are sending form over http page load
One thing to keep in mind is either ways AJAX or otherwise form will only follow course on clicking of submit button. Hence the name form submission.
With in the form we have a field which may be valid or invalid.
If the field is invalid then run error which seems to work or if field is valid then simply glide through to next step in form submission.
On server side detect if field is invalid or not .... and do what ever is dependant on the context.
Issue on server side is it has nothing to do, nor controls and nor wants to control UI, html display in your browser.
All it handles is request i.e. GET, POST, PUT, HEAD etc and responds accordingly.
Browser sends page request to web server - it may pack form data or it may not pack form data dependant on the context.
Web server fetches the page and forwards if there is any packed form data with the request to the page and there is always lot more data getting passed around other then just form e.g. cookies, User agents, IPs etc
once the page is loaded into process stream you little bit of programming tells it to find form data if there is any and processes that for data to make a response out put.
So we are having a conflict of interest between point no 4 and point no 5.
Thing is your form is ultimately just a payload for HTTP (which is just a payload for tcp in turn and so on).
HTTP inherently does not and should not identify data types in payload, it is just an array for HTTP. KEYWORD FOCUS array.
You can select how to represent data in the array
It may look something like this
GET /?say=Hi&to=Mom HTTP/2.0
Host: foo.com
read more here how forms are sent to webserver
So bottom line forms are only going in some form of array format, we know arrays always have key value pair e.g. ['say' => 'hi'] there is key and there is value.
usually java-script does not offer out of the box key value pairing for arrays it has values and uses their index as key e.g. ['hi', 'there'] behind the scene is equivalent to in some hackyway to [0 => 'hi', 1 => 'there'] just keep that in mind java script does not offer multidimensional arrays out of the box.
so how does java script handle arrays or how we define it we it goes like this
var say = ['hi'];
now you may see whats happening around say=Hi in form data. There is massive array of Get with in which are key value pairs separated by &
for php sake it looks something like this
$_GET = [
'say' => 'hi',
'to' => 'mom']
we detect in page through $_GET['say'] which returns the value against it.
This is universal and will remain this for a long time to come.
What you are trying to do it attempting to detect on server from form data wither any of the key value pair has valid value or not.
Well reason why url sending is so fast it happens in less then 2 seconds gone from one part of the planet to another. While response as in downloading the web-page is so slow because inherently do not send html code through url request as show in example above. they send militaristic information understood universally.
This in turn means since there is html going to server then sever cannot detect any attributes they only have key value pair. So out attribute detection is out of window. Through error and trials we developers get the hang of this explicit revelation.
Anyways so how do we deal with this;
Some make cookies some make extra hidden fields
Then trigger on submit event on form to do the magic they need to do
some even run server side validation by running validation function on server e.g.
if($_GET['say' != 'hi'){do this thing something} else { do that thing}
Trust me there are always some kind of function or loop run on server side to make validation. WE have not found default validation way as of yet.
So we use form on submit event
document.getElementById('myform').onsubmit = function() {
var cheking = document.getElementById('myfield').value;
if(cheking != 'what ever you want'){
alert('fail!');
return false; // prevent the form to submit
}
}
This is the general idea dont submit form which is half crooked but incase it does need be sent then slight change of code
document.getElementById('myform').onsubmit = function() {
var cheking = document.getElementById('myfield');
if(cheking.value != 'what ever you want'){
cheking.value = 'invalid';
alert('fail!');
}
}
form will submit and on server side for that key we will have value as invalid so php side would be
if($_GET['myfield' = 'invalid'){stop processing or whatever else } else { keep on processing}
Because this had been going on for so and so and so long it became a standard of its own through input pattern attribute which takes care of all of the above on client side and is pretty much what you have done.
input pattren
bunch of regex to help you along
<!DOCTYPE html>
<html>
<body>
<h1>The input pattern attribute</h1>
<form action="">
<label for="country_code">Country code:</label>
<input type="text" id="country_code" name="country_code" pattern="[A-Za-z]{3}" required oninvalid="runvalidity(this)" oninput="this.setCustomValidity('')"
title="Three letter country code"><br><br>
<input type="submit">
</form>
<script>
function runvalidity(ele){
ele.setCustomValidity('Enter country name please');
ele.value = "invalid";
}
</script>
</body>
</html>
we created a pattern which on on submit event will manage and wont send form the in JavaScript we have run bunch of events on input field where we call custom function which makes UI as you wanted and alters the input value. if for any reason form does go through with invalid value we can then run server side validation as shown above using the same logic.
nevertheless browser will only send count_name=invalid or country_name=usa etc
Hope gist helps you understand whats behind the scene. my suggestion will be develop a UI context then fit in code logic (key word logic) matching both on client and server side.
I personally use pasterns and filet through same conditions on server side. some time client side logic can be tightened up so much there is lesser need to compare on server side. Again it depends how one fits in their code logic.
I have two tabs on my UI.
First tab (default), there is one input textbox and when user submits it, a http call is sent to server
Second tab - Same input textbox + list of checkboxes out of which at least one has to be selected. Then on submit http call is sent.
Both of these cases work fine by themselves.
Now, the problem is - I want my stream to trigger only when form is submitted and not on tab switch. However, I do want the value of tab clicked.
However, currently after the form is submitted once, its being triggered on every tab switch as well ( probably because then it has both selected tab & account available).
Below is the code snippet.
I am not sure what i am missing. Any suggestions are highly appreciated.
detailsByAccount$: Observable<MyType> = this.selectedTab$.pipe(
switchMap((tab) => {
//account$ = account submitted through form
return this.account$.pipe(
switchMap((account) => {
alert(`${account} -------- ${tab}`);
// Server Http call to get the response
if (tab === 'X') {
return this.myService.getDetails(account)
}
return this.myService.getOtherDetails(account);
})
);
}),
);
i would do it like this:
detailsByAccount$: Observable<MyType> = this.account$.pipe(
withLatestFrom(this.selectedTab$),
switchMap(([account, tab]) => {
alert(`${account} -------- ${tab}`);
// Server Http call to get the response
if (tab === 'X') {
return this.myService.getDetails(account)
}
return this.myService.getOtherDetails(account);
})
);
the withLatestFrom operator will not trigger the stream but when account$ is triggered, it will grab the latest value from selectedTab$ and pass it along. It will not trigger though if selectedTab$ has not emitted at least once.
So for this scenario, turns out I had to use BehaviorSubject and it made things little tricky. Below is the answer that I ended up using. Any improvements/optimizations are always appreciated.
Premise of Question -
Two tabs β
Input form.
Input form with a list of checkboxes.
There is a different validator for different tabs. Whenever the form validation passes, form submit is enabled.
Two important things to consider are β Tab has to be selected and the stream should be triggered only after form is submitted.
My first approach was mentioned in the question. However, the issue was http call was being made on every tab switch.
Now, to fix it what I did was β I refactored it so itβs triggered always on account submitted rather than tab selected and then I used take(1) in the inner stream, so it completes itself every time. After I did this this issue got resolved.
detailsByAccount$: Observable<MyType> = this.account$.pipe(
switchMap((account) => {
return this.selectedTab$.pipe(
switchMap((tab) => {
alert(`${account} -------- ${tab}`);
// Server Http call to get the response
if (tab === 'X') {
return this.myService.getDetails(account);
}
return this.myService.getOtherDetails(account);
}),
take(1)
);
})
);
Hope this helps someone. If anyone has any better suggestions, please let me know.
Happy Learning
Vatsal
I need to determine on client side whether an email record is about to be send. In addition, I rather not customizing the vanilla send button.
Is there a way to do it?
My scenario: I need to display a message to the user on send, but not on reply or on forward. Currently, the message is displayed onSave like so:
var SAVE_MODES = { SEND: 7 };
function onSave (eContext) {
if (eContext.getEventArgs().getSaveMode() == SAVE_MODES.SEND) {
displayMyMessage();
}
}
However, the condition evaluates to true not only on send, but also on reply, and on forward, which is undesired.
Got it, simply check against the value of statecode. If it's value is 0 (i.e, open), display the message (else, the email is on a state wherein the "reply" and the "forward" buttons are displayed).
I have two google forms, which send data to two tabs in a single spreadsheet.
I have set up a script with two functions. I would like the first function to run on submission of the first form. And, the second function to run on submission of the second form.
Problem is: when setting up a trigger onformsubmit, it does not allow you to specify which form.
Therefore, whenever completing the first form, it runs both functions.
Question: how can I restrict the functions from running only when the specific form is submitted?
As I suggested in the comments, you can determine the origin of the form submission by analyzing the response object's content.
Here is a basic example to illustrate : it will send you an email to tell which form has been submitted but you can of course use the same condition test to select the action you want to run.
function formSubmitOriginTest(e){
// Logger.log(JSON.stringify(e));
// example value : {"namedValues":{"Untitled Question 2":["test"],"Timestamp":["8/17/2014 11:22:47"]},"values":["8/17/2014 11:22:47","test"],"source":{},"range":{"rowStart":3,"rowEnd":3,"columnEnd":2,"columnStart":1},"authMode":{}}
if(e.namedValues["Untitled Question 2"]!=undefined){// only form B has one question with this exact title, that's enough to identify it.
MailApp.sendEmail(Session.getActiveUser().getEmail(),'form B has been submitted','');// optionally include the answers in the email body if you want
}else{
MailApp.sendEmail(Session.getActiveUser().getEmail(),'form A has been submitted','');// optionally include the answers in the email body if you want
}
}
Another way this can be done is by looking at the sheet name that comes in the response's event object via the range property. Here's an example of how I determined the form that triggered the submission:
// set the sheet name that stores the form responses you care about here:
function getSourceSheetName() { return 'Form Responses 1'; }
function submit(eventObj) {
var range = eventObj.range;
var eventSourceSheetName = range.getSheet().getName();
var givenSourceSheetName = getSourceSheetName();
// if the source sheet (from form response sheet) is not the same as the specified form response sheet, quit (return) so extra forms don't trigger the code
if (eventSourceSheetName.toUpperCase() !== givenSourceSheetName.toUpperCase() ) {
Logger.log('A different form just submitted data - quit code');
return;
}
// you now know which form submitted the response, so do whatever you want!
// ... your code goes here
}
Basically, this code grabs the name of the sheet that the Form response comes from via range.getSheet().getName(). Next, it checks if that name is a specified name we're looking for (specified in the function getSourceSheetName().
I think it's also possible to get the active sheet name via:
eventObj.source.getActiveSheet().getName();
In case you don't want to use "Range".
I hope this helps!
I was just looking at some documentation and found this:
Documentation forForm
It states:
Creates and returns a FormTriggerBuilder tied to the given form.
Also:
var form = FormApp.openById('1234567890abcdefghijklmnopqrstuvwxyz');
ScriptApp.newTrigger('myFunction')
.forForm(form)
.onFormSubmit()
.create();
onFormSubmit
That code seems to be tied to a specific form.
Let's say a user gets a page /form/
GET /form/
He then fills in the form and sends a post request
POST /form/
The server attempts to validate user input and determines input to be invalid.
Currently the history chain for the users is
GET /form/
POST /form/
Now the server redirects the user to the GET /form/ page so it can fill in the form again (with error messages).
His history looks like
GET /form/ with filled in form fields
GET /form/ without filed in form fields
How do I send the user back without the user losing the details he entered in his first form?
What techniques are there for redirecting users back to their GET /form/ page and not forcing them to re-enter their information.
Below is my express (node.js) specific server side code for this example.
The validation middleware:
validate().on("error", function _error(msg) {
// store error message on request object
req.flash(msg, validateUserMessage[msg]);
}).on("valid", function _valid() {
// handle the rest of /POST/
next();
}).on("invalid", function _invalid() {
// redirect user back to last page, the /GET/ form
res.redirect("back");
}).run(function _validateUsers(check, sanitize) {
// validation logic.
});
The routing:
// GET /form/
app.get("/form", function _signUpView(req, res) {
// render /form/
res.render("auth/signup", req.flash());
});
// POST /form/
// validation middleware used here.
app.post("/form", secure.validateUser, function _signUpCreate(req, res) {
model.create(req.body, function _create() {
// create thing in database
});
});
DO NOT redirect on invalid input. Do it on valid input only.
On invalid input, respond to the POST request with the same form, but this time populated with the POST data that you just received.
I have decided to summarise the comments below into my answer:
To me, there seems to be only two sure ways of doing this:
1. Passing the user input parameters back from the server to the browser and repopulate the form either:
a) Using a parameters object passed to the view and populating each field using your severside language
b) Passing back a Json object and populating the form using loadJson
2. Using HTML5 local storage - which also requires JavaScript
If you do not persisit your data using either the server or JavaScript, then surely you are limiting yourself to relying on the browser - which is something you have no control over.
Good luck - if you do find a solution then please post it as your answer as I would be very intersted to see how you succeeded.