Symfony:添加记录后更改响应

发布于 2024-12-25 13:32:29 字数 1822 浏览 1 评论 0原文

我通过 ajax (使用 jquery)打开一个表单,我想保存它而不重新加载整个页面。我必须在哪里更改代码才能获得文本响应(例如“好的!”)而不是重定向到编辑页面?

这是我的js:

$("#newcatlink").click(function() {
    $.ajax({
    'url': "category/new",
    'success': function(data, textStatus, jqXHR) {
            $("#mdialog").html(data);
            $("#_form_jqhide").hide();
            $("#mdialog").dialog({
                modal: true,
                width: 500,
                resizable: false,
                buttons: {
                    Save: function() {
                        $.ajax({
                            'type': 'POST', 
                            'url': 'category/create', 
                            'data': $("#categoryform").serialize(),
                            'success': function(data, textStatus, jqXHR) {
                                alert(data);
                            }
                        });
                    },
                    Cancel: function() {
                        $(this).dialog("close");
                    }
                }
            });
        }
    });
});

我像这样更改了actions.class.php中的processForm操作:

...
if ($form->isValid())
{
  $Category = $form->save();

        if($request->isXmlHttpRequest()) {
            return $this->renderText("ok!");
        } else {
            $this->redirect('category/edit?id='.$Category->getId());
        }
}

但它没有改变任何东西。如何做到这一点?

编辑2012年8月1日:

我已经根据blowski和sakfa的答案对我的代码进行了更改,但我遇到了另一个问题:如何捕获表单错误?我将 processForm else 添加到 if 中,它按预期工作,但我无法返回错误消息/代码/任何内容,只有错误存在的事实。

这是代码: http://pastebin.com/ppbPM88G 这是发送表单后的服务器响应,其中一个必填字段为空:

{"haserrors":true,"errors":[]}

Im opening a form via ajax (using jquery) and i want to save it without reloading whole page. Where i have to change code, to get text response (eg. "ok!") instead of redirection to edit page?

this is my js:

$("#newcatlink").click(function() {
    $.ajax({
    'url': "category/new",
    'success': function(data, textStatus, jqXHR) {
            $("#mdialog").html(data);
            $("#_form_jqhide").hide();
            $("#mdialog").dialog({
                modal: true,
                width: 500,
                resizable: false,
                buttons: {
                    Save: function() {
                        $.ajax({
                            'type': 'POST', 
                            'url': 'category/create', 
                            'data': $("#categoryform").serialize(),
                            'success': function(data, textStatus, jqXHR) {
                                alert(data);
                            }
                        });
                    },
                    Cancel: function() {
                        $(this).dialog("close");
                    }
                }
            });
        }
    });
});

I changed processForm action in actions.class.php like this:

...
if ($form->isValid())
{
  $Category = $form->save();

        if($request->isXmlHttpRequest()) {
            return $this->renderText("ok!");
        } else {
            $this->redirect('category/edit?id='.$Category->getId());
        }
}

but it didnt change anything. How to do this?

edit 8/1/12:

I've made changes to my code according to blowski and sakfa answers, but i get another issue: how to catch form errors? I added to processForm else to if and it works as expected but i cant get error message/code/whatever back, only a fact that error exists.

Here is code: http://pastebin.com/ppbPM88G
and this is server answer after sending form with one required field empty:

{"haserrors":true,"errors":[]}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瑾夏年华 2025-01-01 13:32:29

基于此处的对话:

您已将 return $this->renderText("ok!") 放入 processForm 方法中,但未执行操作(例如 executeCreate)。将返回行和条件检查移至executeXXX 方法。

编辑 2012-01-08

我删除了旧的代码片段,因为它们现在没有任何用处,因为您编辑了原始代码,有效地合并了我的更改。

至于你的新问题:

基本上 symfony1 api 在处理表单时很糟糕,这就是为什么你有这么多问题。

首先,您需要知道这个 api 并不是设计用于处理 AJAX 表单提交的验证 - 这是因为 sfForm 可以验证自身,可以在内部存储它的错误并可以将它们呈现为 HTML - 但没有例程(据我所知)以某种可序列化格式返回错误(例如 fieldname=>errorMessage 对的数组,json_encodes 很好)。

从您的代码开始,我在您的位置上要做的是:

首先:创建单独的操作仅用于ajax提交处理,假设您执行POST请求

public function exucuteAjaxFormSubmission(sfWebRequest $request)
{
    //this action handles ONLY ajax so we can safely set appropriate headers
    $this->getResponse()->setContentType('text/json');

    $form = new form();
    $form->bind($request->getPostParameters());

    if ($form->isValid()) {
        //do your logic for positive form submission, i.e. create or update record in db
        return json_encode('ok'); //notify client that everything went ok
    } else {
        return $this->doSomeMagicToGetFormErrorsAsAnJsonEncodedArray();
    }
}

现在到doSomeMagicToGetFormErrorsAsAnJsonEncodedArray部分:您想要获取表单错误json 格式。为此,我们将向您的表单类添加一个简单的方法(因为这是验证逻辑的“接口”)。

一些理论:sfForm 在内部将验证错误存储在名为 sfValidatorErrorSchema 的结构中。 sfValidatorErrorSchema 将错误存储在两个列表中 - namedErrorsglobalErrors。命名错误是为“字段验证器”抛出的错误(即 name 字段上必需的字符串验证器)。全局错误是为整个表单抛出的错误(即全局 postValidators)。每个错误都是由违规验证器抛出的 sfValidatorError 对象

警告:事实上,这个结构是递归的,但只有在使用嵌入式表单时您才会看到它,在这种情况下,必须更改以下函数以包括 sfValidatorErrorSchema 可以包含另一个函数的情况sfValidatorErrorSchema,而不是 sfValidatorError ..我希望你不要使用嵌入式表单,因为这在 symfony 中比普通表单 API 更糟糕,

但是说得够多了,如果你只想要代码,那么将这些方法复制粘贴到你的表单类中:

class myForm extends sfForm { 
    (...)

    /** a helper method to convert error schema to an array */
    public function getSerializableErrors()
    {
        $result = array();
        foreach ($this->getErrorSchema()->getNamedErrors() as $fieldName => $error) {
            $result[$fieldName] = $error->getMessage();
        }
        foreach ($this->getErrorSchema()->getGlobalErrors() as $error) {
            $result['_globals'][] = $error->getMessage();
        }

        return $result;
    }

    /** screw array, just give me ready to send json! */
    public function getJsonEncodedErrors()
    {
        return json_encode($this->getSerializableErrors());
    }
}

现在只需更改即可。 doSomeMagicToGetFormErrorsAsAnJsonEncodedArraygetJsonEncodedErros ,您就完成了基本的 ajax 表单发布通过验证 - 你现在应该有足够的知识来正确实现你的逻辑,我已经在当前的 symfony 1.4 版本上测试了这个,所以如果出现任何问题,可能是旧 sf 版本的问题(你没有告诉我你使用哪个版本)

Based on conversations here:

you have put return $this->renderText("ok!") in processForm method not in action (like executeCreate). Move the return line and condition check to executeXXX method.

edit 2012-01-08

i have removed my old snippets of code, because they're not for any use now, since you edited your original code effectively incorporating my changes there.

as to your new question:

basically symfony1 api sucks when dealing with forms, thats why you have so many problems.

First of all you need to know that this api is not designed to deal with AJAX form submission when it comes to validation - that's because sfForm can validate itself, can store it's errors internally and can render them as HTML - but there is no routine (as far as I know) to return errors in some serializable format (like an array of fieldname=>errorMessage pairs which json_encodes nicely).

to begin with your code, what I would do in your place was:

First: create separate action just for ajax submission handling, assuming you do POST request

public function exucuteAjaxFormSubmission(sfWebRequest $request)
{
    //this action handles ONLY ajax so we can safely set appropriate headers
    $this->getResponse()->setContentType('text/json');

    $form = new form();
    $form->bind($request->getPostParameters());

    if ($form->isValid()) {
        //do your logic for positive form submission, i.e. create or update record in db
        return json_encode('ok'); //notify client that everything went ok
    } else {
        return $this->doSomeMagicToGetFormErrorsAsAnJsonEncodedArray();
    }
}

Now to the doSomeMagicToGetFormErrorsAsAnJsonEncodedArray part: you want to get form errors in json format. For that we will add a simple method to your form class (as this is your 'interface' to validation logic).

Some theory: internally sfForm stores validation errors in a structure called sfValidatorErrorSchema. sfValidatorErrorSchema stores errors in two lists - namedErrors and globalErrors. Named errors are ones thrown for 'field validators' (i.e. required string validator on name field. Global errors are those thrown for whole form (i.e. global postValidators). Each error is a sfValidatorError object thrown by offending validator.

warning: in fact this structure is recursive, but you will see it only if you use embedded forms in this case following function must be changed to include situation where sfValidatorErrorSchema can contain another sfValidatorErrorSchema, not sfValidatorError.. I hope you don't use embedded forms, because this in symfony sucks even more than plain form API.

But enough talking, if you just want code then copy paste these methods into your form class:

class myForm extends sfForm { 
    (...)

    /** a helper method to convert error schema to an array */
    public function getSerializableErrors()
    {
        $result = array();
        foreach ($this->getErrorSchema()->getNamedErrors() as $fieldName => $error) {
            $result[$fieldName] = $error->getMessage();
        }
        foreach ($this->getErrorSchema()->getGlobalErrors() as $error) {
            $result['_globals'][] = $error->getMessage();
        }

        return $result;
    }

    /** screw array, just give me ready to send json! */
    public function getJsonEncodedErrors()
    {
        return json_encode($this->getSerializableErrors());
    }
}

Now just change doSomeMagicToGetFormErrorsAsAnJsonEncodedArray to getJsonEncodedErros and you're done with basic ajax form posting with validation - you should have enough knowledge now to properly implement your logic. I have tested this on current symfony 1.4 version, so if anything goes wrong it may be a problem of old sf version (you didnt tell me which version you use)

方圜几里 2025-01-01 13:32:29

根据我们的谈话,我可以看到发生了什么。如果我理解你的评论,它不是重定向整个页面,它只是重新渲染对话框内的原始表单?

用户提交表单后,如果它有效,则进行重定向。但是,由于您绕过了重定向,因此它会到达 $this->setTemplate('new') 代码位,因此会再次显示 new 表单,使用刚刚填写的表格中的数据进行填充。

要解决这个问题,请在创建操作中使用类似的内容:

if($request->isXmlHttpRequest()) {
  $this->renderText(json_encode(array('valid' => $form->isValid())));
} else {
  $this->setTemplate('new');
}

您还需要更改 Ajax 请求以指定它需要 JSON 响应。然后,如果表单有效,请关闭对话框(或保存后您想要执行的任何操作)。

Based on our conversation, I can see what's happening. If I've understood your comments, it's not redirecting the whole page, it's just re-rendering the original form inside the dialog box?

After the user submits the form, if it's valid, then it redirects. However, because you're bypassing the redirect, it reaches the $this->setTemplate('new') bit of code instead, so shows the new form again, populated with the data from the just-completed form.

To get around it, use something like this in the create action:

if($request->isXmlHttpRequest()) {
  $this->renderText(json_encode(array('valid' => $form->isValid())));
} else {
  $this->setTemplate('new');
}

You'll also want to change your Ajax request to specify that it's expecting a JSON response. Then, if the form was valid, close the dialog box (or whatever you want to do after the save).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文