【问题标题】:SilverStripe submit HTML form through AjaxSilverStripe 通过 Ajax 提交 HTML 表单
【发布时间】:2023-12-17 21:34:01
【问题描述】:

我想通过 Ajax 将数据从简单的 HTML 表单传递到控制器,然后处理数据并返回响应。

目前我有以下内容:

HomePage.ss

<form method="POST" class="form-horizontal submit-form" onsubmit="return checkform(this);">

    <!-- Text input-->
    <div class="form-group">
        <label class="col-md-4 control-label" for="name">Name</label>  
        <div class="col-md-8">
            <input id="name" name="name" type="text" placeholder="insert full Name" class="form-control input-md" required="" />
        </div>
    </div>

    <!-- Button -->
    <div class="form-group">
        <label class="col-md-4 control-label" for="send-btn"></label>
        <div class="col-md-8">
            <button id="send-btn" name="send-btn" class="btn btn-primary">Submit</button>
        </div>
    </div>
</form>

JavaScript

$('form.submit-form').submit(function() {
    $.ajax({
        type: 'POST',
        url: 'processForm',
        data: $(this).serialize(),
        success: function(data) {
            alert('data received');
        }
    });
});

HomePage.php

class HomePage_Controller extends Page_Controller {
    public function events() {
        $events = CalendarEvent::get();
        return $events;
    }

    public function processForm() {
        if (Director::is_ajax()) {
            echo 'ajax received';
        } else {
            //return $this->httpError(404);
            return 'not ajax';
        }
    }
}

在开发人员工具中,我可以看到我得到了带有 404 not found 错误的 xhr processForm。

如何让这个 Ajax 表单与 SilverStripe 控制器一起正常工作?

【问题讨论】:

  • Spidey,有几件事可能是问题所在: - 需要在控制器中为您的方法指定 $allowed_actions - 可能需要在 SilverStripe 中执行表单以获取 SecurityToken,但我' m 不是 100% 开启
  • 我同意 :) 一个简单而完整的示例对我和处于相同情况的任何人来说都很棒。

标签: javascript php jquery ajax silverstripe


【解决方案1】:

您需要了解 SilverStripe 中如何处理 HTTP 请求路由。

当您发送请求 POST /processForm 时,它被视为页面并由 ModelAsController 管理。这就是您收到 404 错误的原因 - 没有 URLSegment = processForm 的 SiteTree 记录。

解决方案 1

使用表单对象。它在运行时自动创建所有路由配置。阅读更多 https://docs.silverstripe.org/en/3.3/tutorials/forms/ https://docs.silverstripe.org/en/3.3/developer_guides/forms/

解决方案 2

当您真的想深入到简单的单一方法请求处理程序时,请使用这种方法。注册自定义控制器和路由。

  1. 你在 mysite/_config/routing.yml 中指定你的路由

    ---
    Name: siteroutes
    ---
    Director:
      rules:
        processCustomForm: CustomFormController
    
  2. 处理您的请求

    class CustomFormController extends Controller
    {
        public function handleRequest( SS_HTTPRequest $request, DataModel $model ) {
            if (!$request->isPost()) {
              // handle invalid request
            }
    
            $name = $request->postVar('name')
            // process your form
        }
    }
    

【讨论】:

    【解决方案2】:

    蜘蛛,

    我做了类似下面的事情。这是一个快速而肮脏的演示,尚未经过测试,但它可能会让你走上正确的道路。如果您不熟悉 SilverStripe 中表单的工作方式,请参阅 SilverStripe 中的前端表单课程。我发现这些课程对个人很有用,并提供了课程代码:http://www.silverstripe.org/learn/lessons/introduction-to-frontend-forms?ref=hub

    Page.php

    <?php
    
    class Page extends SiteTree
    {
    
    
    
    }
    
    class Page_Controller extends Content_Controller
    {
    
        private static $allowed_actions = array(
            'MyForm',
        );
    
        public function MyForm()
        {
            Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.min.js');
            Requirements::javascript(THIRDPARTY_DIR . '/jquery-validate/jquery.validate.min.js');
            Requirements::javascript('/path/to/your/validation/script.js');
    
            $fields = FieldList::create(
                TextField::create('name')
                    ->setTitle('Name')
            );
    
            $actions = FieldList::create(
                FormAction::create('doSubmit')
                    ->setTitle('Submit')
            );
    
            $requiredFields = RequiredFields::create(
                'name'
            );
    
            $form = Form::create($this, 'MyForm', $fields, $actions, $requiredFields);
    
            return $form;
        }
    
        public function doSubmit($data, $form)
        {
            //process $data or create your new object and simpley $form->saveInto($yourObject); then $yourObject->write()
            //then deal with ajax stuff
            if ($this->request->isAjax()) {
                return $this->customise(array(
                    'YourTemplateVar' => 'Your Value'
                ))->renderWith('YourIncludeFile');
            } else {
                //this would be if it wasn't an ajax request, generally a redirect to success/failure page
            }
        }
    
    }
    

    YourValidationScript.js

    (function ($) {
        $(function () {
            $('#MyForm_Form').validate({
                submitHandler: function (form) {
                    $.ajax({
                            type: $(form).attr('method'),
                            url: $(form).attr('action') + "?isAjax=1",
                            data: $(form).serialize()
                        })
                        .done(function (response) {
                            $('.content').html(response);
                        })
                        .fail(function (xhr) {
                            alert('Error: ' + xhr.responseText);
                        });
                },
                rules: {
                    name: "required"
                }
            });
        })
    })(jQuery);
    

    【讨论】:

    • @Spidey 并在您的页面模板中将此表单用作 $MyForm。这个答案是最好的实现方式,请采纳。