Zend Framework 2: Автоматическое отключение макета для Ajax вызовов

голоса
16

Запрос 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);
    }
}

Мысли?

Задан 01/11/2012 в 11:58
пользователем
На других языках...                            


8 ответов

голоса
8

В самом деле, лучше всего было бы написать еще одну стратегию. Существует JsonStrategy, который может автоматически обнаружить заголовок принять автоматически возвращать 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
    ));
}
Ответил 01/11/2012 в 13:32
источник пользователем

голоса
0

Я ответил на этот вопрос , и кажется , что это может быть похоже - Access ViewModel переменных на событии отправки

Приложить обратный вызов событий для dispatchтриггера событий. После того, как это событие триггеров позволит вам получить результат метода действия по телефону $e->getResult(). В случае действия возвращающего ViewModel это должно позволить вам сделать модификацию setTerminal ().

Ответил 01/11/2012 в 14:52
источник пользователем

голоса
6

Я думаю , что проблема в том , что вы вызываете 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 ?>
Ответил 30/11/2012 в 15:27
источник пользователем

голоса
0

aimfeld решение работает для меня, но в случае, если некоторые из вас поэкспериментировать проблемы с расположением шаблона, попробуйте указать модуль:

 $this->viewModel->setTemplate('application/ajax/response');
Ответил 19/12/2013 в 15:14
источник пользователем

голоса
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

Ответил 14/02/2014 в 00:16
источник пользователем

голоса
-1
public function myAjaxAction() 
{
    ....
    // View - stuff that you returning usually in a case of non-ajax requests
    View->setTerminal(true);
    return View;
}
Ответил 17/06/2014 в 01:38
источник пользователем

голоса
0

Лучше всего использовать JsonModel, который возвращает хороший и JSON отключить макет & представление для вас.

public function ajaxCallAction()
    {
        return new JsonModel(
            [
                'success' => true
            ]
        );
    }
Ответил 13/02/2015 в 20:33
источник пользователем

голоса
0

Я имел эту проблему раньше, и вот quikc трюк, чтобы решить, что.

Прежде всего, создайте пустой макет в папке макета module/YourModule/view/layout/empty.phtml

Вы должны повторить только содержание вида в этой схеме этот путь <?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');
            }
        });
    }
}
Ответил 13/07/2016 в 13:26
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more