Zend Framework 2:AJAX调用的自动禁用布局



当前,我的一个控制器操作的一个ajax请求返回完整页面html。

我只希望它返回该特定动作的HTML(.phtml内容)。

以下代码通过手动禁用特定操作的布局来解决问题:

    $viewModel = new ViewModel();
    $viewModel->setTerminal(true);
    return $viewModel;

检测到AJAX请求时,如何使我的应用程序自动禁用布局?我需要为此编写自定义策略吗?非常感谢有关如何做到这一点的任何建议。

此外,我在App 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);
    }
}

想法?

的确,最好的是编写另一种策略。有一个jSonstrategy可以自动检测Accept标头以自动返回JSON-Format,但是就像Ajax-calls以获取完整页面一样,它不会自动做事,因为您可能想获得完整页面。您提到的上述解决方案是快速的方法。

全速前进时,您只有一条额外的线路。最好的做法是始终从控制器内返回完全合格的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
    ));
}

我认为问题是您在视图模型$e->getViewModel()上调用setTerminal(),负责呈现 layout 而不是操作。您必须创建一个新的视图模型,调用setTerminal(true)并将其返回。我使用专用的AJAX控制器,因此无需确定该操作是否为AJAX:

use ZendViewModelViewModel;
use ZendMvcMvcEvent;
use ZendMvcControllerAbstractActionController;
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 ?>

这是最好的解决方案(以我的卑鄙看法)。我花了将近两天的时间来弄清楚。到目前为止,没有人在互联网上发布有关它的信息。

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('ZendMvcControllerAbstractController', 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

让它让它

我回答了这个问题,似乎可能相似 - 访问viewModel变量

将事件回调附加到dispatch事件触发器上。一旦此事件触发,它将允许您通过调用$e->getResult()获得操作方法的结果。对于返回视图模型的操作,应允许您进行setTerminal()修改。

aimfeld解决方案对我有用,但是如果某些人对模板的位置进行实验,请尝试指定模块:

 $this->viewModel->setTemplate('application/ajax/response');

最好的是使用jsonmodel返回nice json并禁用布局&amp; for for for for you。

public function ajaxCallAction()
    {
        return new JsonModel(
            [
                'success' => true
            ]
        );
    }

我遇到了这个问题,这是解决该问题的问题。

首先,在布局文件夹module/YourModule/view/layout/empty.phtml

中创建一个空布局

您应该仅在此布局中回声查看内容<?php echo $this->content; ?>

现在,在您的Module.php中,将控制器布局设置为ajax请求

的布局/空
namespace YourModule;
use ZendMvcMvcEvent;
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');
            }
        });
    }
}
public function myAjaxAction() 
{
    ....
    // View - stuff that you returning usually in a case of non-ajax requests
    View->setTerminal(true);
    return View;
}

最新更新