我通过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());
}
}
但这并没有改变任何事情。如何做到这一点?
编辑8/1/12:
我已经根据blowski和sakfa的答案对我的代码进行了更改,但我遇到了另一个问题:如何捕捉表单错误?我向if添加了processForm else,它按预期工作,但我无法返回错误消息/代码/任何内容,只有错误存在的事实。
这是代码:http://pastebin.com/ppbPM88G这是发送表单后的服务器答案,其中一个必填字段为空:
{"haserrors":true,"error":[]}
基于此处的对话:
您已将return $this->renderText("ok!")
放在processForm
方法中,但未在操作中(如executeCreate
)。将返回行和条件检查移动到executeXX方法。
编辑2012-01-08
我已经删除了我的旧代码片段,因为它们现在没有任何用处,因为您编辑了原始代码,有效地将我的更改包含在其中。
关于你的新问题:
基本上,symfony1API在处理表单时很糟糕,这就是为什么你会遇到这么多问题。
首先,您需要知道,当涉及到验证时,这个api并不是为处理AJAX表单提交而设计的——这是因为sfForm可以验证自己,可以在内部存储错误,并可以将其呈现为HTML——但(据我所知)没有以某种可序列化格式返回错误的例程(比如json_encode很好地编码的fieldname=>errorMessage对数组)。
从你的代码开始,我会代替你做的是:
首先:假设您执行POST请求,则仅为ajax提交处理创建单独的操作
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将错误存储在两个列表中—namedErrors
和globalErrors
。命名错误是为"字段验证器"(即name
字段上的必需字符串验证器)抛出的错误。全局错误是为整个表单(即全局postValidators)抛出的错。每个错误都是由有问题的验证器抛出的sfValidatorError对象。
警告:事实上,这个结构是递归的,但只有当你使用嵌入式表单时,你才会看到它在这种情况下,必须更改以下函数,以包括sfValidatorErrorSchema可以包含另一个sfValidatorError Schema,而不是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());
}
}
现在只需将doSomeMagicToGetFormErrorsAsAnJsonEncodedArray
更改为getJsonEncodedErros
,就可以完成带有验证的基本ajax表单发布了——您现在应该有足够的知识来正确地实现您的逻辑。我已经在当前的symfony 1.4版本上测试过了,所以如果出现任何问题,可能是旧sf版本的问题(你没有告诉我你使用的是哪个版本)
根据我们的对话,我可以看到发生了什么。如果我理解了你的评论,那不是重定向整个页面,只是在对话框中重新呈现原始表单?
用户提交表单后,如果表单有效,则重定向。然而,由于您绕过了重定向,它会到达代码的$this->setTemplate('new')
位,因此再次显示new
表单,其中填充了刚刚完成的表单中的数据。
要绕过它,请在创建操作中使用类似的东西:
if($request->isXmlHttpRequest()) {
$this->renderText(json_encode(array('valid' => $form->isValid())));
} else {
$this->setTemplate('new');
}
您还需要更改Ajax请求,以指定它需要JSON响应。然后,如果表单有效,请关闭对话框(或保存后要执行的任何操作)。