如何捕获AJAX请求(SilverStripe 3.4)

Fre*_*ium 1 silverstripe

我有一个适用于整个站点每个页面的表单,需要异步发送它,而又不能将用户带到任何地方。

我不知道要捕获发送的数据...我正在使用Page.php,因为我认为,因为它在它所属的每个页面上;我在SilverStripe网站上浏览了Ajax教程,但实际上并没有涵盖该主题,仅涉及正在研究的示例网站。我看了,看了视频,但还是不明白。

我需要知道的是将数据发送到哪个URL(我假设它是自页面以来适用于所有页面的,对吗?)以及如何捕获请求...
目前,我已准备好脚本来发送信息,但是不要不了解我需要在服务器端做什么。

这是后端atm中的功能,我该怎么做才能使它工作?

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');
    }
 }
Run Code Online (Sandbox Code Playgroud)

更新资料

我想我已经有些工作了。我发现,重新安排自己拥有的东西可以使我更加接近需要的位置。现在的问题$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');
    }
 }
Run Code Online (Sandbox Code Playgroud)

FireFox控制台返回 200 Response: basic return


更新二

好了,因此我已经在服务器端接收了数据,但是在将数据放入时遇到了一个小问题postVars

因此,当我编写更新时,我开始获得403 Forbidden Action 'flagDated' isn't allowed on this handler.回报...我没有更改与AFAIK权限相关的任何内容,这是什么原因引起的?是$allowed_actions吗?因为这是工作的全部时间,因为我最后一次更新... PHP Fatal error: Access level to VirtualPage_Controller::$allowed_actions must be public (as in class Page_Controller)
嗯...我发现,如果我改变 $allowed_action VirtualPage.php private public 它再次工作,我得到了 200 响应......有什么问题吗?为什么该页面影响另一个页面?

Dan*_*sby 5

您将数据提交到表单“操作”(表单元素上的属性)。这是表单处理程序。

我很早以前写了一个要点来处理Ajax表单提交(https://gist.github.com/dhensby/5057163)。

这是一个完整的示例,说明如何设置一个基本表单来接受AJAX和传统默认浏览器行为的提交(这是一种很好的做法):

将表单添加到我们的控制器

首先,我们需要定义表格;您Page_Controller应该看起来像这样:

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',
        ));
    }

}
Run Code Online (Sandbox Code Playgroud)

添加这些功能Page_Controller将使它们在所有页面类型上均可用 -可能不希望如此,您应该考虑创建一个新的页面类型(例如ContactPage)是否适合使用此表单

在这里,我们定义了以下方法:

  • 创建 Form
  • 表单处理程序(将提交保存或发送到某处,在Form成功验证数据后运行)
  • complete动作,其中用户将在成功完成表单提交发送到。

自定义模板以方便内容替换

接下来,我们需要设置模板-修改您的Layout / 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>
Run Code Online (Sandbox Code Playgroud)

这是从默认的简单主题中提取的,其中有一个小的补充,即该表单现在被包装为,<div class="form-holder">以便我们可以轻松地用成功消息替换该表单。

我们还需要创建一个Layout/Page_complete.ss模板-与上面的模板相同,不同的form-holder div是:

<div class="form-holder">
    <% include Form_complete %>
</div>
Run Code Online (Sandbox Code Playgroud)

接下来,创建了Includes/Form_complete包括-使用包含这样我们就可以使它很重要的只是对我们对AJAX请求的响应的页面的这一部分:

<h2>Thanks, we've received your form submission!</h2>
<p>We'll be in touch as soon as we can.</p>
Run Code Online (Sandbox Code Playgroud)

创建JavaScript表单侦听器

最后,我们需要编写JavaScript以通过AJAX发送表单,而不是默认的浏览器行为(将其放置在mysite / javascript / ajaxform.js中):

(function($) {
    $(window).on('submit', '.js-ajax-form', function(e) {
        var $form = $(this);
        var formData = $form.serialize();
        var formAction = $form.prop('action');
        var formMethod = $form.prop('method');
        var encType = $form.prop('enctype');

        $.ajax({
            beforeSend: function(jqXHR,settings) {
                if ($form.prop('isSending')) {
                    return false;
                }
                $form.prop('isSending',true);
            },
            complete: function(jqXHR,textStatus) {
                $form.prop('isSending',false);
            },
            contentType: encType,
            data: formData,
            error: function(jqXHR, textStatus, errorThrown) {
                window.location = window.location;
            },
            success: function(data, textStatus, jqXHR) {
                var $holder = $form.parent();
                $holder.fadeOut('normal',function() {
                    $holder.html(data).fadeIn();
                });
            },
            type: formMethod,
            url: formAction
        });
        e.preventDefault();
    });
})(jQuery);
Run Code Online (Sandbox Code Playgroud)

该javascript将使用AJAX提交表单,并在完成后将其淡出,并用响应替换它,然后将其淡入。

对于高级用户:

在此示例中,您网站上的所有表单都将被“ ajaxified”,这是可以接受的,但有时您需要对此进行一些控制(例如,搜索表单无法像这样很好地工作)。相反,您可以稍微修改代码以仅查找具有特定类的表单。

像这样修改Form方法Page_Controller

public function Form() {
    ...
    $form->addExtraClass('js-ajax-form');
    return $form;
}
Run Code Online (Sandbox Code Playgroud)

像这样修改javascript:

$(window).on('submit', '.js-ajax-form', function(e) {
    ...
})(jQuery);
Run Code Online (Sandbox Code Playgroud)

现在,只有具有类的表单js-ajax-form才会以这种方式起作用。