如何将 Polymer 表单提交到 PHP 并显示响应
How to submit Polymer forms to PHP and display response
使用 Polymer 1.0,我设置了铁表单来提交简单的联系表单。这个想法是使用 PHP 将表单提交到数据库 table,然后在不刷新的情况下将来自 PHP 端的响应显示到浏览器中 - 典型的 AJAX。不过,我对 Polymer 环境很着迷 - 似乎应该有一个正确的方法来做到这一点,但数小时的搜索和修补并没有取得成果。
我确实使用 Polymer Starter Kit (lite) 启动了这个项目,它使用脚本 (app.js) 添加事件侦听器等。到目前为止,我还没有破坏这个功能,尽管文档中的所有示例都没有这样做,所以这让事情变得有点复杂,因为我仍然习惯于一般的 Polymer。
这是我目前所知道的。非常感谢您提供的任何建议。
index.html
<!-- this is where the output should be displayed -->
<div id="output"></div>
<!-- this is the web form -->
<form is="iron-form" id="contactus-form" method="post" action="/">
<input type="hidden" name="action" value="contactus-form">
<paper-input id="contactus-field-Name" name="Name" label="Name" value="test"></paper-input>
<paper-button onclick="submitHandler(event)">Send</paper-button>
</form>
...
<script src="script/app.js"></script>
<script>
function submitHandler(event) {
Polymer.dom(event).localTarget.parentElement.submit();
}
</script>
app.js
(function(document) {
'use strict';
addEventListener('iron-form-submit', function(e) {
// this works and displays the POSTed values in the browser
document.querySelector('#output').innerHTML = JSON.stringify(e.detail);
// I'm looking for a way to first submit this data through PHP and
// display the output of that process in the #output div rather than the
// raw form input itself.
}
})(document);
失败的方法 1
我尝试在 index.html 中添加一个 iron-ajax 元素并从 app.js[=143 引用它=] 如下所示。不幸的是,当它尝试添加事件监听器时,整个应用程序崩溃了。这看起来很奇怪,因为 app.js 中还有许多其他片段以相同的方式添加事件侦听器。
index.html
<iron-ajax id="contactus-output" url="/form/contact.php" params="" handle-as="json"></iron-ajax>
<!-- same form as before goes here -->
app.js
var coutput = document.querySelector('#contactus-output');
coutput.addEventListener('response', function() {
// nothing fancy here yet, just trying to see if I can do this
document.querySelector('#output').innerHTML = 'hello world';
}
失败的方法 2
我找到 This Answer on SO 并决定尝试 iron-form-response
活动。我现在收到的输出是 [object HTMLElement]
,这至少是一些东西,但我不确定它是否真的有效。
其他一切保持不变,我将表单的目标更改为指向我的 php 脚本,然后将 app.js 中的内容替换为以下内容:
app.js
addEventListener('iron-form-response', function(e) {
document.querySelector('#output').innerHTML = e.detail;
});
我离得更近了吗?
不放弃
使用我上面第二个失败的方法,铁形式似乎在发出请求,因为当我监听 'iron-form-response' 事件时,它确实触发了。
然而,唯一得到 returned 的是 [object HTMLElement]
- 不知道如何处理它。我尝试吐出它的一些属性(如 developer.mozilla.org - .title
、.properties
、.style
等记录的那样),但它们似乎是空的。 iron-form 真的是 return 一个 HTMLElement 对象还是这是一个错误?我认为它会 return 来自 PHP 脚本的结果,我将表单提交给它,就像正常的 XMLHttpRequest
一样。如果铁型以某种方式将其压缩成物体,有没有办法将其再次拉出?
TL;DR
我认为这整件事归结为:当我的 iron-form 处于 index.html 和 [=183= 时,如何正确添加事件监听器(对于 iron-form-request
) ] 由 app.js 引导,就像 Polymer 1.0 入门套件中默认发生的那样?
进一步简化:当我不创建元素(只是使用它)时,如何将事件侦听器正确添加到 Polymer 的影子DOM?
BUG?
在下面user2422321的精彩回答的帮助下,正在执行iron-request并收到成功的iron-request响应。然而,它的 "response" 属性 returns NULL 即使 "succeeded" returns 为真,也没有错误,并且 XHR 完全解析。 "get" 和 "post" 方法都使用相同的 NULL 结果进行了测试。
我看到 10 天前在 GitHub 中精确记录了一个与这些症状相匹配的错误,尽管它没有引起太多关注:Issue 83。这很不幸,但它似乎是一个错误。在修复元素本身之前,我不相信会有任何方法可以使它正常工作。
IRON-REQUEST 想看什么?!
随着我进一步探索,我发现即使 XHR 直接 returning "null",即使它具有正确的 responseURL 和 "OK" 的 statusText。我开始怀疑我正在尝试 运行 的实际 PHP 脚本(目前只输出 "Hello World")是否有问题。
iron-form-request
是否需要结果中的特定格式或数据类型?我尝试将 header('Content-Type: text/plain');
添加到我的 PHP 文件,然后我尝试将其格式化为经过验证的 JSON 字符串,但响应仍然是 null
。好像没什么效果。
Old school direct XMLHttpRequest
工作正常...甚至在提交请求之前铁形式是否畸形?
我确实设置了一个处理程序来捕获 iron-form-error 但收到了 none。根据回复中的每一条信息,世界上的一切都是完美的。只是...空响应。一遍又一遍……这真是令人难以置信的沮丧。
解决方案!(有点)
好吧,我实在是太绝望了,开始翻阅 iron 源代码本身。看起来 iron-form 目前仍然有些问题,如果响应格式正确 json 只有 return 的内容。在iron-request.html中,似乎允许以下类型,但不要上当。我只能让 json 工作——我想剩下的最终会落到实处。
- json (application/json)
- 正文 (text/plain)
- html (text/html)
- xml (application/xml)
- 数组缓冲区 (application/octet-stream)
因此,目前,我们需要将响应格式设置为 JSON 并包含一个 DOCTYPE 声明以匹配。
就我而言,这看起来是这样(感谢 user2422321 对我的帮助):
index.php
<div id="output">{{myOutput}}</div>
<form is="iron-form" id="contactUsForm" method="get" action="/contactus.php" on-iron-form-response="_onResponseRetrieved">
<paper-input id="Name" name="Name" value="text" label="Name"></paper-input>
<paper-button id="contactSubmitButton" on-tap="_submitHandler">Submit</paper-button>
</form>
app.js
(function(document) {
...
app._onResponseRetrieved = function(e) {
this.myOutput = e.detail;
console.log(e);
};
app._submitHandler = function(e) {
this.$.contactUsForm.submit();
});
...
})(document);
最后,这是最后一块重要的拼图。我以前没有考虑过这个文件输出的内容会非常重要,因为直接 XMLHttpRequests return 无论文件输出什么。
contactus.php
<?php
// This is the line I added
header('Content-Type: application/json');
// Actual Code goes here
// Then make sure to wrap your final output in JSON
echo '{"test":"this is some test json to try"}';
有了所有这些部分,它就可以工作了,e.detail.response
包含我们从 contactus.php.[=35 回显的 JSON 响应=]
不太确定我明白什么不起作用,但我认为应该这样做 "pure" 聚合物方式(我的意思是尽可能少 Javascript ).
<div id="output">{{myOutput}}</div>
<!-- this is the web form -->
<form is="iron-form" id="contactUsForm" method="post" action="/" on-iron-form-response="_onResponseRetrieved">
<input type="hidden" name="action" value="contactUsForm">
<paper-input id="contactus-field-Name" name="Name" label="Name" value="test"></paper-input>
<paper-button on-tap="_submitHandler">Send</paper-button>
</form>
_onResponseRetrieved: function(e)
{
//I'm not 100% sure what e.detail actually contain, but the value your looking for should be inside there somewhere
this.myOutput = e.detail;
}
_submitHandler: function(e)
{
//Note that I renamed the id of your form :)
this.$.contactUsForm.submit();
}
我也看到建议 onclick
应该是 on-tap
以便它在移动设备上正常工作,因此我更改了它。
UI 现在应该在您收到服务器响应后立即更新!
-
编辑:
因为您使用的是 Polymer Starter Kit,它在 index.html
中执行一些主要逻辑,所以有些事情有点不同。在 Polymer 文档中,通常会给出一些示例,其中它们显示元素内的一些代码,而 index.html
看起来或功能并不完全像一个元素,这确实会造成混淆。在我自己的项目中,我实际上跳过了 index.html
中的所有逻辑,因为我认为它看起来很混乱和复杂,但是当回头看时,它并没有那么奇怪(在我看来仍然不漂亮)。我不确定这一点,但是 index.html
的设置方式可能是设置 custom-elements 的方式,如果你想分开代码 (javascript) 和外观 (html/css).
所以为了让你的代码工作:
在 app.js
中,您会看到这一行:
var app = document.querySelector('#app');
您可以将 app
变量视为 custom-element。
在 index.html
中,您可以看到这一行,有点像:"if you click on me I will call the method onDataRouteClick
in the element app
":
<a data-route="home" href="/" on-click="onDataRouteClick">
那么,为什么会调用元素app
上的方法呢?那是因为上面的行是 child 的:<template is="dom-bind" id="app">
(注意 id 与此无关,除了我们通过该 id 将它定位在 Javascript 之外,所以当我说话时关于 app
object 我说的是 Javascript).
在 app.js
中,我们可以通过执行以下操作来定义调用 onDataRouteClick
时会发生什么:
app.onDataRouteClick = function() {
var drawerPanel = document.querySelector('#paperDrawerPanel');
if (drawerPanel.narrow) {
drawerPanel.closeDrawer();
}
};
我不知道为什么,但他们一直使用这条线来查找 objects:
var drawerPanel = document.querySelector('#paperDrawerPanel');
但是当你在 app
的范围内时,你实际上可以使用它来代替,我认为它更像是 Polymerish:
var drawerPanel = this.$.paperDrawerPanel;
-
抱歉,如果您已经知道所有这些,现在我们如何让您的代码工作?
在 app.js
中添加:
app._onResponseRetrieved = function(e)
{
//I'm not 100% sure what e.detail actually contain, but the value your looking for should be inside there somewhere
this.myOutput = e.detail;
console.log(e); //Check the console to see exactly where the data is
};
app._submitHandler = function(e)
{
//Note that I renamed the id of your form :)
//We are in the scope of 'app' therefore we can write this
this.$.contactUsForm.submit();
};
在 index.html
中你会得到类似的东西(显然它应该在 template
元素中):
<div id="output">{{myOutput}}</div>
<!-- this is the web form -->
<form is="iron-form" id="contactUsForm" method="post" action="/" on-iron-form-response="_onResponseRetrieved">
<input type="hidden" name="action" value="contactUsForm">
<paper-input id="contactus-field-Name" name="Name" label="Name" value="test"></paper-input>
<paper-button on-tap="_submitHandler">Send</paper-button>
</form>
我正在使用 Polymer 2,我遇到了类似的问题。
这是我的元素文件:
<template is="dom-bind">
<iron-ajax
auto
id="ajax"
url="test.php"
handle-as="json"
method="POST"
body='{"email":"ankita@gmail.com", "lastlogin":"Feb 21st 2016", "notifications":6}'
content-type = "application/json"
last-response="{{responseObject}}" >
</iron-ajax>
<login-element details="[[responseObject]]"></login-element>
</template>
而登录-element.html 看起来像这样:
<dom-module id="login-element" >
<template>
<!--<form action="test1.php" method="post" enctype='application/json'>-->
<!--Name: <input type="text" name="name"><br>-->
<!--E-mail: <input type="text" name="email"><br>-->
<!--<input type="submit" onclick="submitForm()">-->
<!--</form>-->
<h2>{{details.email}}</h2>
</template>
<script>
Polymer({
is:"login-element",
properties:{
details:Object
}
});
</script>
和test.php
<?php
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($data);
exit;
使用 Polymer 1.0,我设置了铁表单来提交简单的联系表单。这个想法是使用 PHP 将表单提交到数据库 table,然后在不刷新的情况下将来自 PHP 端的响应显示到浏览器中 - 典型的 AJAX。不过,我对 Polymer 环境很着迷 - 似乎应该有一个正确的方法来做到这一点,但数小时的搜索和修补并没有取得成果。
我确实使用 Polymer Starter Kit (lite) 启动了这个项目,它使用脚本 (app.js) 添加事件侦听器等。到目前为止,我还没有破坏这个功能,尽管文档中的所有示例都没有这样做,所以这让事情变得有点复杂,因为我仍然习惯于一般的 Polymer。
这是我目前所知道的。非常感谢您提供的任何建议。
index.html
<!-- this is where the output should be displayed -->
<div id="output"></div>
<!-- this is the web form -->
<form is="iron-form" id="contactus-form" method="post" action="/">
<input type="hidden" name="action" value="contactus-form">
<paper-input id="contactus-field-Name" name="Name" label="Name" value="test"></paper-input>
<paper-button onclick="submitHandler(event)">Send</paper-button>
</form>
...
<script src="script/app.js"></script>
<script>
function submitHandler(event) {
Polymer.dom(event).localTarget.parentElement.submit();
}
</script>
app.js
(function(document) {
'use strict';
addEventListener('iron-form-submit', function(e) {
// this works and displays the POSTed values in the browser
document.querySelector('#output').innerHTML = JSON.stringify(e.detail);
// I'm looking for a way to first submit this data through PHP and
// display the output of that process in the #output div rather than the
// raw form input itself.
}
})(document);
失败的方法 1
我尝试在 index.html 中添加一个 iron-ajax 元素并从 app.js[=143 引用它=] 如下所示。不幸的是,当它尝试添加事件监听器时,整个应用程序崩溃了。这看起来很奇怪,因为 app.js 中还有许多其他片段以相同的方式添加事件侦听器。
index.html
<iron-ajax id="contactus-output" url="/form/contact.php" params="" handle-as="json"></iron-ajax>
<!-- same form as before goes here -->
app.js
var coutput = document.querySelector('#contactus-output');
coutput.addEventListener('response', function() {
// nothing fancy here yet, just trying to see if I can do this
document.querySelector('#output').innerHTML = 'hello world';
}
失败的方法 2
我找到 This Answer on SO 并决定尝试 iron-form-response
活动。我现在收到的输出是 [object HTMLElement]
,这至少是一些东西,但我不确定它是否真的有效。
其他一切保持不变,我将表单的目标更改为指向我的 php 脚本,然后将 app.js 中的内容替换为以下内容:
app.js
addEventListener('iron-form-response', function(e) {
document.querySelector('#output').innerHTML = e.detail;
});
我离得更近了吗?
不放弃
使用我上面第二个失败的方法,铁形式似乎在发出请求,因为当我监听 'iron-form-response' 事件时,它确实触发了。
然而,唯一得到 returned 的是 [object HTMLElement]
- 不知道如何处理它。我尝试吐出它的一些属性(如 developer.mozilla.org - .title
、.properties
、.style
等记录的那样),但它们似乎是空的。 iron-form 真的是 return 一个 HTMLElement 对象还是这是一个错误?我认为它会 return 来自 PHP 脚本的结果,我将表单提交给它,就像正常的 XMLHttpRequest
一样。如果铁型以某种方式将其压缩成物体,有没有办法将其再次拉出?
TL;DR
我认为这整件事归结为:当我的 iron-form 处于 index.html 和 [=183= 时,如何正确添加事件监听器(对于 iron-form-request
) ] 由 app.js 引导,就像 Polymer 1.0 入门套件中默认发生的那样?
进一步简化:当我不创建元素(只是使用它)时,如何将事件侦听器正确添加到 Polymer 的影子DOM?
BUG?
在下面user2422321的精彩回答的帮助下,正在执行iron-request并收到成功的iron-request响应。然而,它的 "response" 属性 returns NULL 即使 "succeeded" returns 为真,也没有错误,并且 XHR 完全解析。 "get" 和 "post" 方法都使用相同的 NULL 结果进行了测试。
我看到 10 天前在 GitHub 中精确记录了一个与这些症状相匹配的错误,尽管它没有引起太多关注:Issue 83。这很不幸,但它似乎是一个错误。在修复元素本身之前,我不相信会有任何方法可以使它正常工作。
IRON-REQUEST 想看什么?!
随着我进一步探索,我发现即使 XHR 直接 returning "null",即使它具有正确的 responseURL 和 "OK" 的 statusText。我开始怀疑我正在尝试 运行 的实际 PHP 脚本(目前只输出 "Hello World")是否有问题。
iron-form-request
是否需要结果中的特定格式或数据类型?我尝试将 header('Content-Type: text/plain');
添加到我的 PHP 文件,然后我尝试将其格式化为经过验证的 JSON 字符串,但响应仍然是 null
。好像没什么效果。
Old school direct XMLHttpRequest
工作正常...甚至在提交请求之前铁形式是否畸形?
我确实设置了一个处理程序来捕获 iron-form-error 但收到了 none。根据回复中的每一条信息,世界上的一切都是完美的。只是...空响应。一遍又一遍……这真是令人难以置信的沮丧。
解决方案!(有点)
好吧,我实在是太绝望了,开始翻阅 iron 源代码本身。看起来 iron-form 目前仍然有些问题,如果响应格式正确 json 只有 return 的内容。在iron-request.html中,似乎允许以下类型,但不要上当。我只能让 json 工作——我想剩下的最终会落到实处。
- json (application/json)
- 正文 (text/plain)
- html (text/html)
- xml (application/xml)
- 数组缓冲区 (application/octet-stream)
因此,目前,我们需要将响应格式设置为 JSON 并包含一个 DOCTYPE 声明以匹配。
就我而言,这看起来是这样(感谢 user2422321 对我的帮助):
index.php
<div id="output">{{myOutput}}</div>
<form is="iron-form" id="contactUsForm" method="get" action="/contactus.php" on-iron-form-response="_onResponseRetrieved">
<paper-input id="Name" name="Name" value="text" label="Name"></paper-input>
<paper-button id="contactSubmitButton" on-tap="_submitHandler">Submit</paper-button>
</form>
app.js
(function(document) {
...
app._onResponseRetrieved = function(e) {
this.myOutput = e.detail;
console.log(e);
};
app._submitHandler = function(e) {
this.$.contactUsForm.submit();
});
...
})(document);
最后,这是最后一块重要的拼图。我以前没有考虑过这个文件输出的内容会非常重要,因为直接 XMLHttpRequests return 无论文件输出什么。
contactus.php
<?php
// This is the line I added
header('Content-Type: application/json');
// Actual Code goes here
// Then make sure to wrap your final output in JSON
echo '{"test":"this is some test json to try"}';
有了所有这些部分,它就可以工作了,e.detail.response
包含我们从 contactus.php.[=35 回显的 JSON 响应=]
不太确定我明白什么不起作用,但我认为应该这样做 "pure" 聚合物方式(我的意思是尽可能少 Javascript ).
<div id="output">{{myOutput}}</div>
<!-- this is the web form -->
<form is="iron-form" id="contactUsForm" method="post" action="/" on-iron-form-response="_onResponseRetrieved">
<input type="hidden" name="action" value="contactUsForm">
<paper-input id="contactus-field-Name" name="Name" label="Name" value="test"></paper-input>
<paper-button on-tap="_submitHandler">Send</paper-button>
</form>
_onResponseRetrieved: function(e)
{
//I'm not 100% sure what e.detail actually contain, but the value your looking for should be inside there somewhere
this.myOutput = e.detail;
}
_submitHandler: function(e)
{
//Note that I renamed the id of your form :)
this.$.contactUsForm.submit();
}
我也看到建议 onclick
应该是 on-tap
以便它在移动设备上正常工作,因此我更改了它。
UI 现在应该在您收到服务器响应后立即更新!
-
编辑:
因为您使用的是 Polymer Starter Kit,它在 index.html
中执行一些主要逻辑,所以有些事情有点不同。在 Polymer 文档中,通常会给出一些示例,其中它们显示元素内的一些代码,而 index.html
看起来或功能并不完全像一个元素,这确实会造成混淆。在我自己的项目中,我实际上跳过了 index.html
中的所有逻辑,因为我认为它看起来很混乱和复杂,但是当回头看时,它并没有那么奇怪(在我看来仍然不漂亮)。我不确定这一点,但是 index.html
的设置方式可能是设置 custom-elements 的方式,如果你想分开代码 (javascript) 和外观 (html/css).
所以为了让你的代码工作:
在 app.js
中,您会看到这一行:
var app = document.querySelector('#app');
您可以将 app
变量视为 custom-element。
在 index.html
中,您可以看到这一行,有点像:"if you click on me I will call the method onDataRouteClick
in the element app
":
<a data-route="home" href="/" on-click="onDataRouteClick">
那么,为什么会调用元素app
上的方法呢?那是因为上面的行是 child 的:<template is="dom-bind" id="app">
(注意 id 与此无关,除了我们通过该 id 将它定位在 Javascript 之外,所以当我说话时关于 app
object 我说的是 Javascript).
在 app.js
中,我们可以通过执行以下操作来定义调用 onDataRouteClick
时会发生什么:
app.onDataRouteClick = function() {
var drawerPanel = document.querySelector('#paperDrawerPanel');
if (drawerPanel.narrow) {
drawerPanel.closeDrawer();
}
};
我不知道为什么,但他们一直使用这条线来查找 objects:
var drawerPanel = document.querySelector('#paperDrawerPanel');
但是当你在 app
的范围内时,你实际上可以使用它来代替,我认为它更像是 Polymerish:
var drawerPanel = this.$.paperDrawerPanel;
-
抱歉,如果您已经知道所有这些,现在我们如何让您的代码工作?
在 app.js
中添加:
app._onResponseRetrieved = function(e)
{
//I'm not 100% sure what e.detail actually contain, but the value your looking for should be inside there somewhere
this.myOutput = e.detail;
console.log(e); //Check the console to see exactly where the data is
};
app._submitHandler = function(e)
{
//Note that I renamed the id of your form :)
//We are in the scope of 'app' therefore we can write this
this.$.contactUsForm.submit();
};
在 index.html
中你会得到类似的东西(显然它应该在 template
元素中):
<div id="output">{{myOutput}}</div>
<!-- this is the web form -->
<form is="iron-form" id="contactUsForm" method="post" action="/" on-iron-form-response="_onResponseRetrieved">
<input type="hidden" name="action" value="contactUsForm">
<paper-input id="contactus-field-Name" name="Name" label="Name" value="test"></paper-input>
<paper-button on-tap="_submitHandler">Send</paper-button>
</form>
我正在使用 Polymer 2,我遇到了类似的问题。
这是我的元素文件:
<template is="dom-bind">
<iron-ajax
auto
id="ajax"
url="test.php"
handle-as="json"
method="POST"
body='{"email":"ankita@gmail.com", "lastlogin":"Feb 21st 2016", "notifications":6}'
content-type = "application/json"
last-response="{{responseObject}}" >
</iron-ajax>
<login-element details="[[responseObject]]"></login-element>
</template>
而登录-element.html 看起来像这样:
<dom-module id="login-element" >
<template>
<!--<form action="test1.php" method="post" enctype='application/json'>-->
<!--Name: <input type="text" name="name"><br>-->
<!--E-mail: <input type="text" name="email"><br>-->
<!--<input type="submit" onclick="submitForm()">-->
<!--</form>-->
<h2>{{details.email}}</h2>
</template>
<script>
Polymer({
is:"login-element",
properties:{
details:Object
}
});
</script>
和test.php
<?php
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($data);
exit;