一个Ajax请求的我的控制器动作之一返回当前整个页面的HTML。
我只希望它为特定的操作返回HTML(一个.phtml内容)。
下面的代码很差解决通过手动禁用用于特定动作的布局问题:
$viewModel = new ViewModel();
$viewModel->setTerminal(true);
return $viewModel;
我怎样才能让我的应用程序自动禁用布局中检测到AJAX请求时? 我需要为此编写自定义的策略? 如何做到这一点任何意见是非常赞赏。
此外,我试过下面的代码在我的应用程序Module.php - 它被正确地检测AJAX但setTerminal()不禁止的布局。
public function onBootstrap(EventInterface $e)
{
$application = $e->getApplication();
$application->getEventManager()->attach('route', array($this, 'setLayout'), 100);
$this->setApplication($application);
$this->initPhpSettings($e);
$this->initSession($e);
$this->initTranslator($e);
$this->initAppDi($e);
}
public function setLayout(EventInterface $e)
{
$request = $e->getRequest();
$server = $request->getServer();
if ($request->isXmlHttpRequest()) {
$view_model = $e->getViewModel();
$view_model->setTerminal(true);
}
}
思考?
Answer 1:
事实上,最好的办法是写另一个策略。 有一个JsonStrategy它可以自动检测accept头自动返回JSON格式的,但与Ajax的呼吁fullpages,有它的好,它并不会自动做的事情,因为你可能希望得到一个完整的页面。 上述方案中你提到的将是快速的路要走。
当去全速,你只能有一个附加行。 它总是从你的控制器内返回完全合格的ViewModels的最佳做法。 喜欢:
public function indexAction()
{
$request = $this->getRequest();
$viewModel = new ViewModel();
$viewModel->setTemplate('module/controller/action');
$viewModel->setTerminal($request->isXmlHttpRequest());
return $viewModel->setVariables(array(
//list of vars
));
}
Answer 2:
我认为这个问题是你调用setTerminal()
在视图模型$e->getViewModel()
是负责渲染的布局 ,而不是行动。 你必须创建一个新的视图模型,调用setTerminal(true)
,并将其返回。 我使用一个专用的Ajax控制器,所以没有必要确定该动作是否是阿贾克斯与否:
use Zend\View\Model\ViewModel;
use Zend\Mvc\MvcEvent;
use Zend\Mvc\Controller\AbstractActionController;
class AjaxController extends AbstractActionController
{
protected $viewModel;
public function onDispatch(MvcEvent $mvcEvent)
{
$this->viewModel = new ViewModel; // Don't use $mvcEvent->getViewModel()!
$this->viewModel->setTemplate('ajax/response');
$this->viewModel->setTerminal(true); // Layout won't be rendered
return parent::onDispatch($mvcEvent);
}
public function someAjaxAction()
{
$this->viewModel->setVariable('response', 'success');
return $this->viewModel;
}
}
在AJAX / response.phtml只需以下几点:
<?= $this->response ?>
Answer 3:
这里是最好的解决方案(愚见)。 我花了差不多两天的时间弄明白。 关于发布在互联网上,没有人到目前为止,我认为。
public function onBootstrap(MvcEvent $e)
{
$eventManager= $e->getApplication()->getEventManager();
// The next two lines are from the Zend Skeleton Application found on git
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
// Hybrid view for ajax calls (disable layout for xmlHttpRequests)
$eventManager->getSharedManager()->attach('Zend\Mvc\Controller\AbstractController', MvcEvent::EVENT_DISPATCH, function(MvcEvent $event){
/**
* @var Request $request
*/
$request = $event->getRequest();
$viewModel = $event->getResult();
if($request->isXmlHttpRequest()) {
$viewModel->setTerminal(true);
}
return $viewModel;
}, -95);
}
我还是不太满意,虽然。 我想创建一个插件作为一个听众,并通过配置文件,而不是onBootstrap方法来配置它。 但是,我会让这为下一次= P
Answer 4:
我回答这个问题,似乎它可能类似- 访问视图模型上的调度事件变量
附加一个事件回调到dispatch
事件触发。 一旦这个事件触发它应该让你通过调用来获得操作方法的结果$e->getResult()
在返回视图模型的动作的情况下,它应该让你做setTerminal()修改。
Answer 5:
aimfeld解决方案对我的作品,但在某些情况下,你使用模板的位置试验的问题,试图指定模块:
$this->viewModel->setTemplate('application/ajax/response');
Answer 6:
最好是使用JsonModel返回好的JSON和关闭布局和视图为您服务。
public function ajaxCallAction()
{
return new JsonModel(
[
'success' => true
]
);
}
Answer 7:
我收到这个问题,这里是一个quikc招解决了。
首先,在布局文件夹中创建一个空的布局module/YourModule/view/layout/empty.phtml
你应该只能随声附和此布局中的视图内容这样<?php echo $this->content; ?>
<?php echo $this->content; ?>
现在,在您的Module.php
设置控制器布局,布局/空的Ajax请求
namespace YourModule;
use Zend\Mvc\MvcEvent;
class Module {
public function onBootstrap(MvcEvent $e) {
$sharedEvents = $e->getApplication()->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
if ($e->getRequest()->isXmlHttpRequest()) {
$controller = $e->getTarget();
$controller->layout('layout/empty');
}
});
}
}
Answer 8:
public function myAjaxAction()
{
....
// View - stuff that you returning usually in a case of non-ajax requests
View->setTerminal(true);
return View;
}
文章来源: Zend Framework 2: Auto disable layout for ajax calls