Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel: how to render only one section of a template?

I'm trying to use pjax on my site, which means that for a full page request I render the whole template (this is normal behaviour), but on pjax requests I would like to render just one section. My templates all extend a master template.

How can I most elegantly do that?

like image 912
duality_ Avatar asked Feb 26 '13 18:02

duality_


People also ask

What does {{ }} mean in Laravel?

By default, Blade {{ }} statements are automatically sent through PHP's htmlentities function to prevent XSS attacks. If you do not want your data to be escaped, you may use the following syntax: Hello, {!! $name !!}. Follow this answer to receive notifications.

What is yield and section in Laravel?

In Laravel, @yield is principally used to define a section in a layout and is constantly used to get content from a child page unto a master page.

What is blade in Laravel?

Blade is the simple, yet powerful templating engine that is included with Laravel. Unlike some PHP templating engines, Blade does not restrict you from using plain PHP code in your templates.

Why does Laravel use the blade template engine?

Laravel Blade template engine enables the developer to produce HTML based sleek designs and themes. All views in Laravel are usually built in the blade template. Blade engine is fast in rendering views because it caches the view until they are modified. All the files in resources/views have the extension .


2 Answers

This is kind of an old question but I would like to throw down another solution.

Lets say you have a view layout called main.blade.php and another view that extends main called 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

Just a simple basic template to get things started. In your controller if you return a View::make('page') you will get the complete HTML but Laravel provides a way to return specific sections. Here is an example of how to display the content you want based on if its an ajax call or not from within your controller:

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

Now when you make an ajax call to the page it will only return the content section rather than the entire HTML.

like image 157
JoeMoe1984 Avatar answered Sep 17 '22 13:09

JoeMoe1984


Why wouldn't you just replace the actual content in the rendered page using a div or html element?

I do this all the time with jQuery. I simply build my initial page and send content to my views that render sections in my master layout.

Let's say I had a left navigation column and then an article in the right column. The user clicks a button to display the next article, so that's what I want to replace.

First build the initial view from your controller

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

Now in your homepage view

@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

Assuming you're using a resourceful controller you could use your show() function, but if you just wanted a teaser on the homepage you could easily create a new function for that as well.

In your show() or newFunctionWhateverYouCallIt() you can just get the article by id

Article::find($id);

Then send that off to a view to be rendered.

return View::make('article');

And finally the article view you called included the when you first built the page and again after updating via Jquery or pjax

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

Please note I haven't tested this code so I'm sure there are a few mistakes, but you get the general idea of the logic for updating a single section of your page.

like image 38
Joshua Avatar answered Sep 18 '22 13:09

Joshua