Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blade: extending a template in multiple subviews

Tags:

laravel

blade

I am using Blade to include multiple sub-views into a single set of tabs in a blade app. All of the sub-views have the same overall structure (a sidebar and a main section). Because of this, I have created a template and each sub-view extends the template. Here is the structure:

Main.blade.php

<div id="tabs">
  <ul>
    @foreach($views as $view)
    <li><a href="#{{$view}}">{{$view}}</a></li>
    @endforeach
  </ul>
  @foreach($views as $view)
  <div id="{{$view}}">
    @include($view)
  </div>
  @endforeach
</div>

template.blade.php

{{-- formatting stuff --}}
  @yield('content 1')
{{-- more formatting stuff --}}
  @yield('content-2')
{{-- more formatting stuff --}}

tab-*.blade.php

@extends('template')

@section('content-1')
This is tab [whatever number]
@stop

@section('content-2')
Lorem Ipsum
@stop

The obvious problem here is that, as each sub-view extends the same template, the @yield('content') exists 3 times, and all 3 included sub-views have their own @section('content'). What appears to be happening is that the first sub-view's implementation of the content section is getting placed in all 3 yields.

My intent here is obvious. I want each included sub-view to implement it's own instance of the template, place it's content in the content section, THEN get pulled into the main page. Can this be done?

If I flatten the tab-*.blade.php files and stop using the template, it works fine. The problem here is that I end up with a lot of code repetition that would be better placed in a template. This is an emergency option, but I'd like to do it the "proper" way.

NOTE

I have tried to redesign this to avoid the problem, but I really can't come up with another solution. While @include is typically used to pull in small, static pieces (a header, a footer, etc.), I have not read anything that states this as a restriction. It seems to me that the best approach is to store each view once and pull them into the main page when needed, so that's how I've designed it.

like image 595
ewok Avatar asked Aug 02 '14 09:08

ewok


2 Answers

Try using the @overwrite command instead of @stop

Example:

@extends('template')

@section('content-1')
     Stuff goes here...
@overwrite

@section('content-2')
     More stuff goes here...
@overwrite

Source: https://github.com/laravel/framework/issues/1058#issuecomment-17194530

like image 146
MASNathan Avatar answered Sep 29 '22 06:09

MASNathan


I came up with a hack that seems to work. In template.blade.php, I use the following:

{{-- formatting stuff --}}
  @yield(isset($tab) ? "content-1-$tab" : 'content-1')
{{-- more formatting stuff --}}
  @yield(isset($tab) ? "content-2-$tab" : 'content-2')
{{-- more formatting stuff --}}

Then, in main.blade.php, I execute @include('view', ['tab'=>$view]). This seems to cause each instance of content-1 and content-2 do be named distinctly, allowing the 2 subviews to implement the sections separately. This also should allow any other views that implement this template to continue to function without having to change anything.

like image 28
ewok Avatar answered Sep 29 '22 06:09

ewok