Javascript创建帖子,Symfony控制器处理并重定向,但新页面不会显示

Javascript创建帖子,Symfony控制器处理并重定向,但新页面不会显示,javascript,symfony,twig,fancytree,Javascript,Symfony,Twig,Fancytree,我是Symfony、PHP和Javascript的初学者。我正在努力使用基于Fancytree的Javascript树表单。多亏了这个论坛,我把所有的事情都做好了,把表单数据发回给控制器,处理请求并重定向到一个成功页面。问题是成功页面永远不会显示。Firefox调试器也没有显示错误。我不再进步了,我被卡住了 这是我的控制器: namespace Solar\DataBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\C

我是Symfony、PHP和Javascript的初学者。我正在努力使用基于Fancytree的Javascript树表单。多亏了这个论坛,我把所有的事情都做好了,把表单数据发回给控制器,处理请求并重定向到一个成功页面。问题是成功页面永远不会显示。Firefox调试器也没有显示错误。我不再进步了,我被卡住了

这是我的控制器:

namespace Solar\DataBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Config\Definition\Exception\Exception;

class DefaultController extends Controller
{

    /**
     * Test data sent to Twig and javascript tree
     * 
     * @Route("/form_tree_demo", name="form_tree_demo")
     * @Method({"GET", "POST"})
     */
    public function formTreeDemoAction(Request $request)
    {
        $test = 'Test string';
        $testArray =
        array(
            array(
                'name'=> '1',
                'title' => '1',
                'children' =>
                array(
                    array('name' => '1.1',
                        'title' => '1.1'
                    ),
                    array('name' => '1.2',
                        'title' => '1.2'
                    )
                )
            ),
            array(
                'name'=> '2',
                'title' => '2',
                'children' =>
                array(
                    array('name' => '2.1',
                        'title' => '2.1'
                    ),
                    array('name' => '2.2',
                        'title' => '2.2'
                    )
                )
            )
        );
        $form = $this->createFormBuilder()
            ->add('save', SubmitType::class, array('label' => 'Post to the controller'))
            ->getForm();

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {

            //for debug
            //throw new Exception(var_dump($form->getData()));

            return $this->redirectToRoute('success', array('message' => 'Post handled'));
        } 

        return $this->render('formtreedemo.html.twig',
            array(
                'tree_form' => $form->createView(), 
                'test_array' => json_encode($testArray)
            )
        );
    }

    /**
     * @Route("/success", name="success")
     */
    public function successAction()
    {
        return $this->render('success.html.twig');
    }
}
以下是细枝表格:

{% extends 'base.html.twig' %}

{% block body %}
    <h1>A demo form with Fancytree</h1>
    {{ form_start(tree_form) }}
        <div id="tree" name="selNodes">
        </div>
        Additional data: <input type="text" name="otherFormData" /><br><br>
    {{ form_end(tree_form) }}
{% endblock %}

{% block javascripts %}
    <script type="text/javascript" src="{{asset('assets/vendor/jquery/dist/jquery.js')}}"></script>
    <script type="text/javascript" src="{{asset('assets/vendor/jquery-ui/jquery-ui.js')}}"></script>
    <script type="text/javascript" src="{{asset('assets/vendor/bootstrap/dist/js/bootstrap.js')}}"></script>
    <link rel="stylesheet" type="text/css" id="skinSheet" href="{{asset('assets/vendor/fancytree/src/skin-lion/ui.fancytree.css')}}" />
    <script type="text/javascript" src="{{asset('assets/vendor/fancytree/src/jquery.fancytree.js')}}"></script>

    <script type="text/javascript">
        $(function(){
            $("#tree").fancytree({
                checkbox: true,
                selectMode: 2,
                source:$.parseJSON('{{test_array}}'.replace(/&quot;/ig,'"'))
            });
            $("form").submit(function() {
                $("#tree").fancytree("getTree").generateFormElements();
                jQuery.ajax({
                    type: "POST",
                    url: "{{path("form_tree_demo")}}",
                    data: formData
                });
                return false;
            });
        });
    </script>
{% endblock %}
{%extends'base.html.twig%}
{%block body%}
带有Fancytree的演示窗体
{{form_start(tree_form)}
其他数据:

{{form_end(tree_form)} {%endblock%} {%block javascripts%} $(函数(){ $(“#树”).fancytree({ 复选框:正确, 选择模式:2, 来源:$.parseJSON({{test_array}}.replace(/“/ig,”)) }); $(“表格”)。提交(函数(){ $(“#树”).fancytree(“getTree”).generateFormElements(); jQuery.ajax({ 类型:“POST”, url:“{path(“form_tree_demo”)}”, 数据:formData }); 返回false; }); }); {%endblock%}
最后是IE控制台转储:

URL                                                         Method  Result  Type                      Initiateur
/web/app_dev.php/form_tree_demo                               GET    200    text/html                 actualiser
/web/assets/vendor/bootstrap/dist/css/bootstrap.css           GET    200    text/css                  <link rel="stylesheet">
/web/assets/vendor/bootstrap/dist/css/bootstrap-theme.css     GET    200    text/css                  <link rel="stylesheet">
/web/assets/vendor/jquery/dist/jquery.js                      GET    200    application/javascript    <script>
/web/assets/vendor/jquery-ui/jquery-ui.js                     GET    200    application/javascript    <script>
/web/assets/vendor/bootstrap/dist/js/bootstrap.js             GET    200    application/javascript    <script>
/web/assets/vendor/fancytree/src/skin-lion/ui.fancytree.css   GET    200    text/css                  <link rel="stylesheet">
/web/assets/vendor/fancytree/src/jquery.fancytree.js          GET    200    application/javascript    <script>
/web/app_dev.php/_wdt/115370                                  GET    200    text/html                 XMLHttpRequest
/web/assets/vendor/fancytree/src/skin-lion/icons.gif          GET    200    image/gif                 background-image
/web/app_dev.php/form_tree_demo                               POST   302    text/html                 XMLHttpRequest
/web/app_dev.php/success?message=Post%20handled               GET    200    text/html                 XMLHttpRequest
URL方法结果类型启动器
/web/app_dev.php/form_tree_demo GET 200 text/html实现器
/web/assets/vendor/bootstrap/dist/css/bootstrap.css获取200文本/css
/web/assets/vendor/bootstrap/dist/css/bootstrap-theme.css获取200文本/css
/web/assets/vendor/jquery/dist/jquery.js GET 200 application/javascript
/web/assets/vendor/jqueryui/jquery-ui.js GET 200 application/javascript
/web/assets/vendor/bootstrap/dist/js/bootstrap.js GET 200 application/javascript
/web/assets/vendor/fancytree/src/skin lion/ui.fancytree.css获取200个文本/css
/web/assets/vendor/fancytree/src/jquery.fancytree.js GET 200 application/javascript
/web/app_dev.php//u wdt/115370 GET 200 text/html XMLHttpRequest
/web/assets/vendor/fancytree/src/skin lion/icons.gif获取200图像/gif背景图像
/web/app_dev.php/form_tree_demo POST 302 text/html XMLHttpRequest
/web/app_dev.php/success?message=Post%20handled GET 200 text/html XMLHttpRequest
其他信息: 我在Windows8、OpenSuse和Ubuntu虚拟机服务器下运行Symfony3.2。到处都是同样的结果。不推荐使用的Dynatree也有相同的结果

如蒙帮助,不胜感激


Jean Michel

您需要处理ajax的成功/失败,并从那里加载新页面。目前,您正在控制器中返回重定向调用的html,javascript函数不以任何方式处理返回,只返回false

如果控制器中的表单只响应ajax,那么成功后,将返回要重定向到的url,然后让javascript执行重定向

如果表单只处理ajax调用,我个人会创建一个路由/函数来处理它。
这就是为什么您可以执行一些检查(如
$request->isXmlHttpRequest()
)以确保调用仅来自ajax

例如

然后是你的javascript

<script type="text/javascript">
        $(function(){
            $("#tree").fancytree({
                checkbox: true,
                selectMode: 2,
                source:$.parseJSON('{{test_array}}'.replace(/&quot;/ig,'"'))
            });
            $("form").submit(function(e) {
                e.preventDefault();
                var formData = $("#tree").fancytree("getTree").generateFormElements();
                var jqxhr = $.ajax({
                    type: "POST",
                    url: "{{path('ajax_action')}}",
                    data: formData
                })
                .done(function(data) {
                    if (data.success === true) {
                        window.location.href = data.url;
                    }
                })
                .fail(function(data) {
                    alert('error');
                })
                .always(function(data) {

                });
                return false;
            });
        });
</script>

$(函数(){
$(“#树”).fancytree({
复选框:正确,
选择模式:2,
来源:$.parseJSON({{test_array}}.replace(/“/ig,”))
});
$(“表格”)。提交(功能(e){
e、 预防默认值();
var formData=$(“#树”).fancytree(“getTree”).generateFormElements();
var jqxhr=$.ajax({
类型:“POST”,
url:“{path('ajax_action')}}”,
数据:formData
})
.完成(功能(数据){
如果(data.success==true){
window.location.href=data.url;
}
})
.失败(功能(数据){
警报(“错误”);
})
.始终(功能(数据){
});
返回false;
});
});

谢谢您的帮助。我在控制器中尝试过:if($request->isXmlHttpRequest()){echo“isXmlHttpRequest”;}它不会返回。触发JS警报(错误)。浏览器返回一个白色页面,其中包含:{“success”:true,“url”:“\/solar\/web\/app\u dev.php\/success”}。此外,在php中,“$form”是空的(data=null)。@jmichel\如何在javascript中创建formData?另外,因为您是通过ajax提交的,所以symfony表单事件正在运行,因此表单是空的。将ajax帖子分离到它自己的routeOK。在我尝试之前,请告诉我我的方法是否正确:我想用PHP准备树数据(活动节点、折叠的分支等),用JS收集用户更新,发送回PHP并持久化数据库。这是一个好的布局吗?@jmichel_u流程很好,只需要一个路由/函数来准备要发送到视图的数据,另一个路由/函数来处理ajax。ajax成功后,您可以重定向到另一条路径,或者只发送回更新的html以重新呈现html(javascript),无论您喜欢什么。
<script type="text/javascript">
        $(function(){
            $("#tree").fancytree({
                checkbox: true,
                selectMode: 2,
                source:$.parseJSON('{{test_array}}'.replace(/&quot;/ig,'"'))
            });
            $("form").submit(function(e) {
                e.preventDefault();
                var formData = $("#tree").fancytree("getTree").generateFormElements();
                var jqxhr = $.ajax({
                    type: "POST",
                    url: "{{path('ajax_action')}}",
                    data: formData
                })
                .done(function(data) {
                    if (data.success === true) {
                        window.location.href = data.url;
                    }
                })
                .fail(function(data) {
                    alert('error');
                })
                .always(function(data) {

                });
                return false;
            });
        });
</script>