Laravel: как отображать только один раздел шаблона?

Я пытаюсь использовать pjax на своем сайте, что означает, что для запроса полной страницы я отображаю весь шаблон (это нормальное поведение), но при запросах pjax я хотел бы отображать только один раздел. Все мои шаблоны расширяют основной шаблон.

Как я могу сделать это наиболее элегантно?


person duality_    schedule 26.02.2013    source источник


Ответы (4)


Это старый вопрос, но я хотел бы предложить другое решение.

Допустим, у вас есть макет представления с именем main.blade.php и другое представление, расширяющее основное, с именем page.blade.php<. /сильный>

main.blade.php

<!DOCTYPE html>
<html lang="en-GB">
<head>
    <title>My Title</title>

    @section('head')
        <link rel="stylesheet" href="{{ URL::asset('css/style.css') }}">
    @show
</head>
<body>

    @yield('content')

    @section('footer')
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <script type="text/javascript" src="{{ URL::asset('js/main.js') }}"></script>
    @show
</body>
</html>

page.blade.php

@extends('main')

@section('content')
    <div class="container">
        This is a rendered page
    </div>
@stop

Просто простой базовый шаблон для начала работы. В вашем контроллере, если вы вернете View::make('page'), вы получите полный HTML, но Laravel предоставляет способ вернуть определенные разделы. Вот пример того, как отображать контент, который вы хотите, на основе того, является ли это вызовом ajax или нет из вашего контроллера:

my_controller.php

function get_index() {
    $view = View::make('page');

    if(Request::ajax()) {
        $sections = $view->renderSections(); // returns an associative array of 'content', 'head' and 'footer'

        return $sections['content']; // this will only return whats in the content section

    }

    // just a regular request so return the whole view

    return $view;
}

Теперь, когда вы делаете ajax-вызов на страницу, он возвращает только раздел содержимого, а не весь HTML.

person JoeMoe1984    schedule 08.06.2014
comment
@Inigo Я только что еще раз взглянул на это и решил, что то, как я это делал раньше, было немного небрежным в его проверке. Поэтому отредактировал часть запроса. - person JoeMoe1984; 23.07.2014
comment
@user151841 user151841 Я тестировал это на Laravel 5.2.39, и оно все еще работает как есть. Я не думаю, что вам нужно было бы делать что-то другое. - person JoeMoe1984; 22.06.2016

Почему бы вам просто не заменить фактический контент на отображаемой странице с помощью элемента div или html?

Я делаю это все время с jQuery. Я просто создаю свою начальную страницу и отправляю контент в свои представления, которые отображают разделы в моем основном макете.

Допустим, у меня была левая навигационная колонка, а затем статья в правой колонке. Пользователь нажимает кнопку, чтобы отобразить следующую статью, поэтому я хочу заменить ее.

Сначала создайте начальный вид из вашего контроллера.

public function index()
{  
  $article = Article::first();
  Return View::make('homepage', compact('article'));
}

Теперь на главной странице

@extends('layouts.master')

@section('leftNavigation')
     @include('homepageLeftNavigation')
@stop

@section('article')
   <div id="articleContent">
     @include('article') <!-- see below, you'll update this include with the js below -->
   </div>
@stop

@section('script')
@parent
{{-- <script> --}}
//in JQuery I would do something like this
$('a.nextArticle').click(function(){
   var next = $('.nextArticle').attr("id");
   var next = next + 1;
   $('#articleContent').load({{ URL::to('articles/' + next ) }};
});
@stop

Предполагая, что вы используете находчивый контроллер, вы можете использовать функцию show(), но если вам просто нужен тизер на главной странице, вы также можете легко создать новую функцию для этого.

В вашем show() или newFunctionWhateverYouCallIt() вы можете просто получить статью по идентификатору

Article::find($id);

Затем отправьте это в представление для визуализации.

return View::make('article');

И, наконец, просмотр статьи, который вы вызвали, включал в себя, когда вы впервые создали страницу, и снова после обновления через Jquery или pjax.

     {{ $article->title }}
     {{ $article->body  }}
     {{ $article->date }}
     <a href="#" class="nextArticle" id="{{ $article->id }}">Next Article ></a>

Обратите внимание, что я не тестировал этот код, поэтому уверен, что есть несколько ошибок, но общее представление о логике обновления отдельного раздела вашей страницы вы получили.

person Joshua    schedule 18.04.2013

Моим лучшим ответом сейчас было бы заявить, что, по вашему мнению, он должен расширять главный шаблон (макет) только в том случае, если запрос не вызывается через AJAX:

@if(!Request::ajax())
    @extends('master.template')
@endif

Обратите внимание, однако, что это решение может быть не лучшим для ваших конкретных шаблонов (я могу только догадываться об этом). Вам нужно убедиться, что каждый шаблон/представление содержит только то, что не повторяется, например, боковые панели и т. д. Например, если у вас есть область содержимого, которую необходимо обновить с помощью pjax, то ваше представление должно содержать только то, что следует изменить.

person Mike Rockétt    schedule 27.02.2013
comment
Это не идеально, но довольно близко. Если это сработает (еще не пробовал) и никто не предложит лучшего решения, я приму этот ответ. - person duality_; 01.03.2013

Внутри действия вашего контроллера явно верните частичное представление, которое вы хотите отобразить:

public function action_someajax()
{
    ...
    return View::make('mypartial', $data);
}

Это приведет к частичному отображению вместо макета контроллера.

person Jürgen Paul    schedule 28.02.2013
comment
Как это сработает? Вот (почти) то, как я это использую сейчас: return View::make('page', $data); и эта страница, затем @extends('master'). - person duality_; 28.02.2013
comment
@duality_ Чтобы это работало, вам нужно указать свой шаблон в контроллере, а не в каждом из ваших представлений. - person Jürgen Paul; 28.02.2013
comment
Не идти. Какой дизайн расширяет шаблон, зависит от дизайна, а не от кода/контроллера. Поэтому это решение должно быть принято в представлении. - person duality_; 28.02.2013
comment
Однако вы сказали: Все мои шаблоны расширяют главный шаблон. - person Jürgen Paul; 01.03.2013
comment
Точно. Посмотрите на ответ Майка. - person duality_; 01.03.2013
comment
Это расширение происходит в шаблоне (там, где оно должно быть), а не в коде. - person duality_; 01.03.2013