如何捕获AJAX请求(SilverStripe 3.4)
我有一个表单,它应用于整个站点的每个页面,需要异步发送,而不需要将用户带到任何地方 我想不出如何捕捉发送的数据。。。我之所以使用Page.php,是因为我假设它位于它所属的每个页面上;我在SilverStripe网站上浏览了ajax教程,但这并没有真正涵盖这个主题,只是正在开发的示例网站。我读了它,看了视频,还是不明白 我需要知道的是将数据发送到哪个URL(我假设它是任意的,因为页面适用于所有页面,对吗?)以及如何捕获请求…如何捕获AJAX请求(SilverStripe 3.4),silverstripe,Silverstripe,我有一个表单,它应用于整个站点的每个页面,需要异步发送,而不需要将用户带到任何地方 我想不出如何捕捉发送的数据。。。我之所以使用Page.php,是因为我假设它位于它所属的每个页面上;我在SilverStripe网站上浏览了ajax教程,但这并没有真正涵盖这个主题,只是正在开发的示例网站。我读了它,看了视频,还是不明白 我需要知道的是将数据发送到哪个URL(我假设它是任意的,因为页面适用于所有页面,对吗?)以及如何捕获请求… 目前,我已经准备好了发送信息的脚本,但不明白我需要在服务器端做什么 这
目前,我已经准备好了发送信息的脚本,但不明白我需要在服务器端做什么 这是我在后端自动取款机里的东西,我能做些什么来让它工作呢 Page.php
class Page_Controller extends ContentController {
private static $allowed_actions = array(
'flagDated'
);
public function flagDated(SS_HTTPRequest $request){
echo $request;
if($request->isAjax()){
//
}
}
public function init() {
parent::init();
Requirements::javascript('themes/three-two/js/flag-dated.js');
}
}
更新 我想我已经有些成功了。我发现重新安排我所拥有的东西会让我更接近我需要的地方。现在的问题是,
$request->isAjax()
失败,并且返回basic return
…我仍然不确定我做错了什么--我发现在请求末尾添加
?ajax=1
可以解决这个问题
class Page extends SiteTree {
// ...
public static $allowed_actions = array(
'flagDated'
);
}
class Page_Controller extends ContentController {
public function flagDated(SS_HttpRequest $request){
if($request->isAjax()){
return '$request';
}
return 'basic return';
}
public function init() {
parent::init();
Requirements::javascript('themes/three-two/js/flag-dated.js');
}
}
FireFox控制台返回200
响应:基本返回
更新II 好的,我在服务器端接收数据,但在将数据导入
postVars
时遇到了一个小问题
因此,当我编写更新时,我开始得到403
禁止此处理程序上不允许执行“flagDated”操作。
返回。。。我没有改变任何与权限有关的事情,是什么原因造成的?是不是$allowed\u actions
?因为自从我上次更新后它一直在工作<代码>PHP致命错误:对VirtualPage\u控制器的访问级别::$allowed\u操作必须是公共的(如在类页面\u控制器中)
嗯。。。我发现如果我将
中的中的
更改为public
,它会再次工作,我会得到一个200
响应。。。这里有什么问题?为什么该页面会影响其他页面?您将数据提交到表单“action”(表单元素上的属性)中。这是表单处理程序
我很久以前写了一篇要点来处理ajax表单提交()
下面是一个完整的示例,介绍如何设置一个基本表单,该表单接受AJAX和传统默认浏览器行为提交的内容(这是一个良好的实践):
将表单添加到控制器
首先,我们需要定义我们的形式;您的Page\u控制器应如下所示:
class Page_Controller extends ContentController {
/**
* A list of "actions" (functions) that are allowed to be called from a URL
*
* @var array
* @config
*/
private static $allowed_actions = array(
'Form',
'complete',
);
/**
* A method to return a Form object to display in a template and to accept form submissions
*
* @return Form
*/
public function Form() {
// include our javascript in the page to enable our AJAX behaviour
Requirements::javascript('framework/thirdparty/jquery/jquery.js');
Requirements::javascript('mysite/javascript/ajaxforms.js');
//create the fields we want
$fields = FieldList::create(
TextField::create('Name'),
EmailField::create('Email'),
TextareaField::create('Message')
);
//create the button(s) we want
$buttons = FieldList::create(
FormAction::create('doForm', 'Send')
);
//add a validator to make sure the fields are submitted with values
$validator = RequiredFields::create(array(
'Name',
'Email',
'Message',
));
//construct the Form
$form = Form::create(
$this,
__FUNCTION__,
$fields,
$buttons,
$validator
);
return $form;
}
/**
* The form handler, this runs after a form submission has been successfully validated
*
* @param $data array RAW form submission data - don't use
* @param $form Form The form object, populated with data
* @param $request SS_HTTPRequest The current request object
*/
public function doForm($data, $form, $request) {
// discard the default $data because it is raw submitted data
$data = $form->getData();
// Do something with the data (eg: email it, save it to the DB, etc
// send the user back to the "complete" action
return $this->redirect($this->Link('complete'));
}
/**
* The "complete" action to send users to upon successful submission of the Form.
*
* @param $request SS_HTTPRequest The current request object
* @return string The rendered response
*/
public function complete($request) {
//if the request is an ajax request, then only render the include
if ($request->isAjax()) {
return $this->renderWith('Form_complete');
}
//otherwise, render the full HTML response
return $this->renderWith(array(
'Page_complete',
'Page',
));
}
}
将这些函数添加到Page Orthor 会使它们在<>强>所有< /强>页类型上可用——这可能不需要,并且您应该考虑是否创建一个新的页面类型(如CONTACTPAGE)更适合于在
上具有这种形式?
在这里,我们定义了以下方法:
- 创建
表单
- 表单处理程序(要将提交的内容保存或发送到某处,在
表单
成功验证其数据后运行)
- 一个
完成
操作,用户在成功完成表单提交后将发送到该操作
定制模板以方便内容替换
接下来,我们需要设置模板-修改布局/Page.ss文件:
<% include SideBar %>
<div class="content-container unit size3of4 lastUnit">
<article>
<h1>$Title</h1>
<div class="content">$Content</div>
</article>
<div class="form-holder">
$Form
</div>
$CommentsForm
</div>
接下来创建include/Form_complete
include-使用include很重要,这样我们就可以呈现页面的这一部分来响应AJAX请求:
<h2>Thanks, we've received your form submission!</h2>
<p>We'll be in touch as soon as we can.</p>
这个javascript将使用AJAX提交表单,完成后将淡出表单,替换为响应,然后淡入
对于高级用户:
在本例中,您站点上的所有表单都将“ajaxified”,这可能是可以接受的,但有时您需要对此进行一些控制(例如,搜索表单不会像这样工作)。相反,您可以稍微修改代码,以便只查找具有特定类的表单
修改控制器页面上的表单
方法,如下所示:
public function Form() {
...
$form->addExtraClass('js-ajax-form');
return $form;
}
对javascript进行如下修改:
$(window).on('submit', '.js-ajax-form', function(e) {
...
})(jQuery);
现在只有类为js ajax form的表单才会以这种方式工作。我已经设法让它工作。
这是我的解决方案,任何人都可以看到如何使用SilverStripe实现ajax,而不管用例是什么
HTML
非常基本,只是向用户提供一些字段来输入内容
<div class="flag-dated-container hidden">
<div class="modal-window">
<div class="header">
<h1>Flagging $Title</h1>
<div class="close" data-action="close" title="Close">X</div>
</div><!-- . header -->
<form>
<input type="text" placeholder="This content is..." />
<textarea placeholder="Explain the issue in full detail..."></textarea>
</form>
<div class="buttons">
<div data-action="close">Cancel</div>
<div data-action="send">Send</div>
</div><!-- . buttons -->
</div><!-- . modal-window -->
</div><!-- . flag-dated -->
PHP
这是我遇到最多麻烦的部分。$allowed\u actions
需要位于控制器中,并设置为专用。我在JS脚本中设置的标题
和正文
是使用$request->postVars('myVar')中相同的变量进行访问的代码>
我不久前写了这个要点是为了帮助你:不确定,但也许我提供的答案有帮助?它使用基于AJAX的表单提交。基本上,您只需编写一个常规表单和提交处理程序,然后通过JS/AJAX而不是普通表单提交来提交表单。在后端没有太多的变化…这看起来非常像我需要的!我已经添加了我目前拥有的代码,这就是我所能做的,接下来我需要做什么?只是想澄清一下,我遇到的问题不是ajax方面,而是如何在框架中接收数据。旁注:不管怎样,谢谢你的链接,它有文档吗?或者这是使用它所需要的全部注释吗?没有其他文档。你能链接到你一直在关注的视频和文档吗?当然。这是主要的一个,然后几乎任何搜索结果哟
$(window).on('submit', '.js-ajax-form', function(e) {
...
})(jQuery);
<div class="flag-dated-container hidden">
<div class="modal-window">
<div class="header">
<h1>Flagging $Title</h1>
<div class="close" data-action="close" title="Close">X</div>
</div><!-- . header -->
<form>
<input type="text" placeholder="This content is..." />
<textarea placeholder="Explain the issue in full detail..."></textarea>
</form>
<div class="buttons">
<div data-action="close">Cancel</div>
<div data-action="send">Send</div>
</div><!-- . buttons -->
</div><!-- . modal-window -->
</div><!-- . flag-dated -->
var container = document.getElementsByClassName('flag-dated-container')[0];
// Interaction functionality
container.addEventListener('click', function(e){
var target = e.target,
userInput = container.querySelectorAll('input, textarea');
if(target.dataset.action === 'send'){
/*
My function in the controller is called 'flagDated'
so that's what I append to the end of the URL
and the ?ajax=1 is to ensure it passes the isAjax() check
in the controller
*/
var r = new XMLHttpRequest(),
url = window.location + 'flagDated?ajax=1',
data = '';
// Create the param to send
data = 'title=' + encodeURIComponent(userInput[0].value);
data += '&body=' + encodeURIComponent(userInput[1].value);
r.onreadystatechange = function(){
if(r.readyState === 4 && r.status === 200){
// Success, do something
}
else if(r.readyState !== 4 && (r.status === 400 || r.status === 500)){
// failed
}
}
r.open('POST', url); // We use the current URL because it doesn't matter what the target is
r.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
r.send(data);
}
});
class Page_Controller extends ContentController {
private static $allowed_actions = array(
'flagDated'
);
public function flagDated(SS_HttpRequest $request){
if($request->isAjax() && $request->isPost()){
$title = $request->postVar('title');
$body = $request->postVar('body');
$email = new Email(
'from@email.com',
'to@email.com',
'Flagged as Dated: ' . $title,
$body
);
$email->send();
}
else
// Not ajax or post, do something else.
}
public function init() {
parent::init();
Requirements::javascript('themes/three-two/js/flag-dated.js');
}
}