2012-11-01 72 views
15

對我的控制器操作之一的AJAX請求當前返回整頁HTML。Zend Framework 2:爲Ajax調用自動禁用佈局

我只希望它返回特定操作的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); 
    } 
} 

想法?

回答

7

事實上,最好的事情是寫另一個策略。有一個JsonStrategy可以自動檢測Accept頭以自動返回Json-Format,但與使用Ajax-Calls進行fullpages一樣,它不會自動執行任何操作,因爲您可能需要整頁。上面提到的解決方案將是最快的方法。

當全速前進時,您只需要一條附加線。從控制器中始終返回完全限定的ViewModel是最佳做法。像:

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 
    )); 
} 
+0

謝謝,山姆 - 我也更新了我的帖子,包括我嘗試使用該應用程序的Module.php的方法。有關爲什麼setTerminal()對ViewModel沒有影響的想法? –

+0

我的猜測是onBootstrap中沒有ViewModel()存在,一個想法是注入一個viewModel終端(true)到控制器中,並將其用於輸出(我是否有任何意義?) – Sam

0

我回答這個問題,似乎它可能類似 - Access ViewModel variables on dispatch event

附加一個事件回調到dispatch事件觸發。一旦觸發了該事件,它應該允許您通過調用$e->getResult()來獲得操作方法的結果。在返回ViewModel的操作的情況下,它應該允許您執行setTerminal()修改。

6

我認爲問題是,你的視圖模型$e->getViewModel(),負責渲染佈局,而不是行動呼籲setTerminal()。您必須創建一個新的視圖模型,請致電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 ?> 
0

aimfeld解決方案適用於我,但在某些情況下,你使用模板的位置試驗的問題,試圖指定模塊:

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

這裏是最好的解決方案(愚見)。我花了差不多兩天時間才弄明白。目前爲止,互聯網上沒有人發佈關於它的內容。

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

+0

請記住,結果的控制器可能根本不是'ViewModel';即使請求可能不是'Zend \ Http \ Request',所以在編寫事件監聽器時要小心,始終在控制事件中抓取的內容,並記住監聽器會影響整個MVC應用程序週期,而不僅僅是您的模塊。 –

+0

我如何在控制器內訪問這個特定的視圖模型? – jkushner

-1
public function myAjaxAction() 
{ 
    .... 
    // View - stuff that you returning usually in a case of non-ajax requests 
    View->setTerminal(true); 
    return View; 
} 
0

最好是使用JsonModel返回好的JSON和禁用爲您佈局&視圖。

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

這是很好,除非你想發回完成的HTML。 – David

0

我之前有過這個問題,這裏是一個quikc技巧來解決這個問題。

首先,在佈局文件夾中創建一個空的佈局module/YourModule/view/layout/empty.phtml

你應該只能隨聲附和此佈局中的視圖內容這樣<?php echo $this->content; ?>

現在在你Module.php設置控制器佈局,佈局/空對於阿賈克斯請求

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'); 
      } 
     }); 
    } 
}