No body on AMP form submit - forms

Hi guys I'm learning how to use AMP and coming to an issue where my api requests are coming back with an empty body. My get route works fine and my post route works for non-AMP form submissions.
If someone could let me know what Im doing wrong it'd be appreciated!
HTML for the AMP form, from the amp website & contains no amp errors on load.
<form method="post" action-xhr="/subscribe" target="_top" style="width: 75%; margin: auto;">
<fieldset>
<label>
<span>Name:</span>
<input type="text" name="name" required>
</label>
<br>
<label>
<span>Email:</span>
<input type="email" name="email" required>
</label>
<br>
<input type="submit" value="Subscribe">
</fieldset>
<div submit-success>
<template type="amp-mustache">
Subscription successful!
</template>
</div>
<div submit-error>
<template type="amp-mustache">
Subscription failed!
</template>
</div>
</form>
API routes, get works fine and the post works for non-AMP forms
module.exports = function (app) {
// Subs get
app.get("/api/all", function (req, res) {
Sub.findAll({}).then(function (results) {
res.json(results);
});
});
// Subs post
app.post("/subscribe", function (req, res) {
console.log("Sub Data:");
console.log(req.body);
});
};

The first and the foremost thing to work for AMP form is to use the following script
<script async="" custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
Secondly your action-xhr must be full domain path and must be HTTPS
From this
action-xhr="/subscribe"
To this
action-xhr="https://yourdomain.com/subscribe"

Related

Amp-form does not redirect to another page

I have one input bar which must redirect to another https page (contains google-search) on submit. The code of the form is the next:
<form class="navbar-form navbar-left hide-inputs buscadoMovilLine" role="search" target="_blank" action-xhr="https://www.tuotromedico.com/buscadorg.php" action="https://www.tuotromedico.com/buscadorg.php" method="get">
<div class="form-group buscador">
<input class="SearchInputMovil2 inl" type="text" placeholder="Buscar..." class="form-control" name="q">
<button class="inl" type="submit" class="btn btn-default"><i class="fa fa-search lupaBuscarMovilBoton2" aria-hidden="true"></i></button>
</div>
</form>
I have added the amp-form extension too. The official documentation says this:
Redirecting after a submission
amp-form also allows publishers to redirect users to a new page after a submission happens through AMP-Redirect-To response header.
Note that you'd also have to update your Access-Control-Expose-Headers
response header to include AMP-Redirect-To to the list of allowed
headers.
The redirect URL must be absolute HTTPS URL otherwise AMP will throw
an error and redirection won't happen.
https://www.ampproject.org/es/docs/reference/components/dynamic/amp-form
But im not sure how have i to specify that.
I know 2 ways, this is for node:
app.post('/register', function (req, res) {
let form = new formidable.IncomingForm();
form.parse(req, function (err, fields) {
res.setHeader('AMP-Access-Control-Allow-Source-Origin', 'https://example.com/');
if (fields.first_name && fields.last_name) {
res.setHeader('AMP-Redirect-To', 'https://example.com/some-key');
res.status(200).json(fields);
} else {
res.status(400).json({error: 'Please select a size.'});
}
});
and the second, in amp you can use navigateTo()
<form class="proceed__form" method="post" id="requirements-form"
action-xhr="https://localhost:4040/check-requirements"
target="_top"
on="submit-success:AMP.navigateTo(url='https://google.com')"
>
</form>
OR you can get variable from response
(res.status(200).json({message: 'success', navigateTo: domain + '/profile'});)
<form class="proceed__form" method="post" id="requirements-form"
action-xhr="https://localhost:4040/check-requirements"
target="_top"
on="submit-success:AMP.navigateTo(url=event.response.navigateTo)"
>
</form>

Processing multiple forms from an only template

I have two forms into a template, how can I identify every html form in order
to process it into my handler?
Is possible get the form name in the post handler code?
I'm using nosurf, therefore I must generate and check the
token in the same request, maybe I'm doing wrong..
<form action="/form" method="post" name="form1">
<label class="control-label">Set A</label>
<div class="controls">
<input type="text" id="my" name="my">
</div>
<div style="display:none;">
<input name="_formkey" type="hidden" value="{{.token}}">
</div>
</form>
<form action="/form" method="post" name="form2">
<label class="control-label">Set thing</label>
<div class="controls">
<input type="text" id="thing" name="thing">
</div>
<div style="display:none;">
<input name="_formkey" type="hidden" value="{{.token}}">
</div>
</form>
My Handler
func myHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method{
case "GET":
data:=map[string]interface{}{
"key":nosurf.Token(req),
}
if err := renderTemplate(w, "base", data); err != nil {
log.Error(err)
}
case "POST":
// how?
if r.FormValue("my"){}
...
if r.FormValue("thing"){}
...
}
}
Thanks
Is possible get the form name in the post handler code?
I don't think that's possible, but you can send the form name in another hidden input field.

How to find data from multiple input fields on the server side (Express.js/Node.js)?

I have a form with multiple description text fields, file chose field and submit button for the Cross-Domain request (CORS variant):
<form class="upload" id="upload_form" enctype="multipart/form-data" method="post" action="http://localhost:3001/upload/1234567890">
<div class="row-fluid">
<div class="span5 row-fluid" id="description" style="margin-left:0px;">
<div>
<label>Title</label>
<input class="span12" type="text" placeholder="Title" id="description_title" name="description_title"/>
<label>Author</label>
<input class="span12" type="text" placeholder="Author" id="description_author" name="description_author"/>
<label>Tags</label>
<input class="span12" type="text" placeholder="Tags" id="description_tags" name="description_tags"/>
<label>Description</label>
<textarea class="span12" id="description_textarea" name="description_textarea" rows="5" style="resize:none"></textarea>
<div id="buttons" class="row-fluid" style="margin-top: 5px">
<div class="span12">
<span class="span5 btn btn-primary btn-file" id="chose_files_btn" onclick="filechose_button.click()">chose files
<input id="filechose_button" type="file" name="fileData" data-url="http://localhost:3001/upload/1234567890"/></span>
<button id="upload_button" type="submit" name="upload" class="span5 offset2 btn btn-success" disabled="true" onclick="$('#upload_form').trigger('upload_fired');">upload</button>
</div> <!-- span12 -->
</div> <!-- buttons -->
</div> <!-- well -->
</div> <!-- video_description -->
</div> <!-- row-fluid -->
</form>
The Node.js (Express.js) server has a route:
app.post('/upload/:id', function(req, res){
console.log(req.fields);
...
});
The problem is, I can not find the data from input fields: req.fields gets undefined.
How can I find the data (text description and a file) from the req on the server?
Update:
Great! req.body really get access to all the fields, BUT:
console.log(req.body)
prints:
{ description_title: 'aaa',
description_author: 'bbb',
description_tags: 'ccc',
description_textarea: 'ddd',
upload: '' }
but where is the fileData field? I mean, where the file I upload with the description (aforementioned fields)?
Update 2: Done!
Files are not in the body attribute, but in the req.files
Thanks for Adam and andyfan!
As said by Adam if you see these two lines
app.use(express.bodyParser());
app.use(express.methodOverride());
in app.js file of express, then you can read fields as given below.
app.post('/upload/:id', function(req, res){
console.log(req.body.description_title);
console.log(req.body.description_author);
console.log(req.body.description_tags);
console.log(req.body.description_textarea);
console.log(req.files);
res.send("Done!");
});
You can read more about how to handle files in express at this link http://howtonode.org/really-simple-file-uploads
You want req.body so long as you have express.methodOverride() in your configuration before the routes.
In your route try console.log(req.body); to see what object you get there. For the route parameters it is req.params.
console.log(object); can be your best friend when trying to find the objects your looking for and the data structure they are contained in.

One click to trigger several search forms?

I have 1 main search form with a submit button and several secondary search forms with submit buttons.
What I would like to do is when I enter text and click on the submit button of the main search form, the same text gets copied in all of the secondary search forms and all the submit buttons of the secondary search forms get automatically hit.
The HTML code for the mains earch form is shown below:
<form action="query.php" method="get">
Search: <input type="text" name="item" size="30">
<input type="submit" value="send">
</form>
One of the several secondary search forms is shown below:
<FORM action="http://www.dpbolvw.net/interactive" method="GET" target="_blank">
<div style="float: left; padding: 0 3px 0 0;">
<INPUT type="text" name="src" size="9"
value="<?php
$input = $_GET['item'];
echo $input;?>" style="width: 110px; height: 22px;margin:0; padding: 0; font-size:140%;">
</div>
<div style="float: left; padding: 0 3px 0 0;">
<input type="image" name="submit" value="GO" src="http://images.guitarcenter.com/Content/GC/banner/go.gif"
alt="Search" style="font-size:140%">
/div>
<input type="hidden" name="aid" value="1234"/>
<input type="hidden" name="pid" value="1234"/>
<input type="hidden" name="url" value="http://www.guitarcenter.com/Search/Default.aspx"/>
</form>
Notice the php code that I put in the "value" field of the secondary search form:
<?php
$input = $_GET['item'];
echo $input;?>
This automatically copies the text that I entered in the main search form into the secondary search form. I thus figured out how to do that.
The problem is to "simulate" an "Enter" keystroke or a click on the "GO" button with the mouse on the secondary search form when the user hits the Enter key or hits the "SEND" button with the mouse on the main search form.
Thank you for your insight!
I'm not sure what the point of that would be, It looks like all of these are search forms all pointing to different sites. Web browsers won't allow that. They can navigate to one page at a time. When you post a form to a page you are navigating to that page. Therefore, you are trying to navigate to several pages at once. It's like trying to be in Paris and London at the same time. I don't see how your plan will work the way you're describing it.
That said, You can use client-side javascript to call
document.forms[0].submit();
so if you can come up with a plan that does not involve trying to have the user see all the different search results in one window, you could try this on your first form...
<form action="query.php" method="get" onSubmit="document.forms(1).Submit();">
You should use AJAX (JQuery) as Brandon Suggested. Read http://docs.jquery.com/Events/submit
Example:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(document).ready(function(){
$("#submit").click(function() {
//Do you stuff here like triggering other submits
//Like:
$("input#submit2").click();
$("input#submit3").click();
return false;
});
});
</script>
</head>
<body>
<form action="javascript:alert('success!');">
<div>
<input type="text" />
<input type="submit" id="submit" />
</div>
</form>
<form >
<div>
<input type="text" />
<input type="submit" id="submit2" />
</div>
</form>
<form >
<div>
<input type="text" />
<input type="submit" id="submit3" />
</div>
</form>
</body>
</html>
Take a look at the submit() event in jQuery. That is going to be your key.
I am assuming that you are planning on submitting via ajax? Otherwise it is futile.
So you could do something like this-
Give all of your forms a certain class, let's call it 'ajax_search_forms'. So now you can actually hook into the submit event.
$('.ajax_search_forms').submit(function(){
var search_string = $('input[name=src]').val();
$('.ajax_search_forms').each(function(){
$.ajax({
url : $(this).attr('action'),
data : 'search_string=' + search_string,
success : function(html){
// Do something with the result
}
});
});
// Return false is VERY important so that the form submission does not continue
return false;
});

Facebook form post data not present on backend

I am attempting to post form data to my app using Facebook. My form is integrated with a dialog and I am using form.submit() to submit the form. Please see my code. The post data does not appear on the backend (e.g. load-cargo-radio, city-id, train-id), but the fb_sig* data does. Does anyone know if there are any caveats regarding posting form data with Facebook? Thanks!
Note: I have tried both using my server domain and my fb callback url for the form action. Neither works.
<div id="action_prompt">
Loading cargo...
</div>
<fb:js_string var="fbjs_load_cargo_select">
<div id="load_cargo_select">
<form id="load_cargo_select_form" action="http://railsacrosseurope.com/turn/load_cargo_select" method="POST">
<p>Your train has stopped in the city of Arhus.</p>
<p>Arhus produces the following goods:</p>
<ul>
<li>Dairy</li>
</ul>
<p>Your train is hauling the following goods:</p>
<ul>
<li>Timber</li>
</ul>
<p>What would you like to do?</p>
<input type="radio" id="load_cargo_radio" value="1">Load new goods</input>
<input type="radio" id="load_cargo_radio" value="2">Discard existing goods</input>
<input type="hidden" id="city_id" value="3" />
<input type="hidden" id="train_id" value="15" />
<input type="submit" id="submit" value="Submit" />
</form>
</div>
</fb:js_string>
.
.
.
<script type="text/javascript">
var dialog = new Dialog().showChoice('Load Cargo', fbjs_load_cargo_select, 'Okay', 'Pass');
dialog.onconfirm = function() {
// Submit the form if it exists, then hide the dialog.
frm = document.getElementById('load_cargo_select_form');
if (frm) { frm.submit(); }
dialog.hide();
};
dialog.oncancel = function() {
form = document.getElementById('redirect_form');
form.setAction('http://apps.facebook.com/rails_across_europe/turn/move_trains_auto/');
form.submit();
}
</script>
[/code]
The problem was not with Facebook. The problem was that I left out the "name" attribute for my input elements.