Nesting views with laravel Blade - laravel

I have searched SO, and dug in the Laravel documentation but I am not sure I quite understand if what I would like to do can be done.
I am using Laravel 4. I want to know how I can nest views in other views.
For example, I have a base layout.. lets call it layout.blade.php
<html>
<head>
<title>{{ $title }}</title>
</head>
<body>
#yield('nav')
#yield('content')
</body>
</html>
Next I have a blade for a page called home:
#extends('layout')
#section('nav')
<p>NAVIGATION</P>
#end
#section('content')
<p>HELLO WORLD!</P>
#end
I have a couple different navigation layouts, one for admins, another for super users, and another for regular users.
Is there a way to add another blade view inside the section('nav')?
#section('nav')
// do something magical here?
#end
It doesn't make sense that for every blade layout I need to repeat the navigation code when several snippets can be reused.

You can do this
#section('nav')
#include('another')
#include('magical')
#include('snippet')
#end

Another solution, in case you were wishing to dynamically load different subviews, you can nest using the View Class. E.g. you could have the following in a Route / Controller:
return View::make('home')->nest('subnav','home/nav', array('some' => 'data');
and then in your home.blade.php, you could do this:
#extends('layout')
#section('nav')
<p>NAVIGATION</p>
{{ $subnav }}
#end
#section('content')
<p>HELLO WORLD!</p>
#end
This can be done with an include and a variable as well (#include($viewname, array('some' => 'data')) however I'd say its cleaner as it removes the logic from the view, particularly if your nested views aren't always the same blade file.

Even though this is late you can also do this:
eg. in an admin.php you can have this:
#extends('home')
#section('nav')
// navigation
#endsection
#section('content')
// admin page content
#endsection
Not saying this is better or not i'm just answering your question on nesting views with blade, this is how i nest my views.

Related

Laravel with blade - multiple inheritance

I know there was many question like this one but I still can't handle with that problem.
I have master layout where I put common elements for all subsites in my app.
(Inside common directory)
<!DOCTYPE html>
<html lang="pl">
<head>
#include('common.head')
</head>
<body>
<div id="l-wrap">
#include('common.header')
<article id="l-content">
#yield('content')
#include('common.dealer-area')
</article>
#include('common.footer')
#include('common.cookies')
</div>
If I understand correctly: if I want elements 'stick' to master template I make include, these elements will be this same on every subpage.
Second blade inheritance after first one and looks like this:
(Inside homepage directory)
#extends('common.template')
#section('content')
#yield('slider')
#endsection
And there is third blade which inheritance after second one:
#extends('home-page.template')
#section('slider')
<div class=slider> Some slider elements
</div>
#endsection
But view from third section doesn't show at all. I tried with #yield, #section...#endsection, or #section...#stop but it doesn't helped.
When I give second parameter in #yield function, after 'slider' in second blade:
#yield('slider', 'some text')
It shows correctly so I think problem is the last one blade, the third one, do I use inheritence incorrectly?

laravel blade template - how to remove a part from extended page

Note: Like i said in the comment, i am working relatively large project. I can't change existing codes. Just try to add some code blocks for one page.
I have a template blade. It has meta yield. But also included one meta.blade.php, that contains all meta tags. But i don't want to include metapage for some of my pages. There is the template for visualization:
my_template
<header>
#yield('meta')
#include('metapage')
#yield('style')
#yield('js')
</header>
my view.blade.php
#extends('my_template')
#section('meta')
<meta description...>
#endsection
#section('style')
//content
#endsection
#section('js')
//content
#endsection
My question is: Is there a way to make something like this:
#extends('my_template')->except('metapage')
I know there isn't exist something like that. But i need that. I hope somebody can give me a solution.
There is a certain solution which I do:
First one is to create multiple template and extend them as your requirements.
Second one is to disable sub parts.
Third one to create parent template having little things, then create child template which is extending parent and do extra things here. use it as your need.
If You are working on existing project and you have a lot of pages then First & third one is a better solution for it because you could make changes only in front end without affecting class code.
You could make the meta a component rather than an include, then your template would look the same and your view would be e.g.
#extends('my_template')
#section('meta')
#component('meta')
#slot('description', 'my amazing description')
#endcomponent
#endsection
// other code here as usual
Your component is then responsible for checking what exists and what doesn't, e.g. like this:
#isset($description)
<meta name="description" content="{{ $description }}">
#endisset
#isset($title)
<title>{{ $title }}</title>
#endisset
// etc, the title is just an example
Documentation: https://laravel.com/docs/5.6/blade#components-and-slots
Take the Tag Name Which You Want To ignore And Apply the CSS
ex: If I need to Remove the Footer From the Extended Page make
footer {
display: none;
}

What's the difference between Laravel Blade's `#yield` and `#include`?

I'm learning Laravel (starting at version 5.3) and these two Blade directives look very similar, the only difference I know is that #include injects the parent's variables and can also send other variables.
What's the difference between #yield and #include?
When should I use #yield?
When should I use #include?
#yield is mainly used to define a section in a layout. When that layout is extended with #extends, you can define what goes in that section with the #section directive in your views.
The layout usually contains your HTML, <head>, <body>, <header> and <footer>s. You define an area (#yield) within the layout that your pages which are extending the template will put their content into.
In your master template you define the area. For example:
<body>
#yield('content')
</body>
Let's say your home page extends that layout
#extends('layouts.app')
#section('content')
// home page content here
#endsection
Any HTML you define in the content section on your homepage view in the 'content' section will be injected into the layout it extended in that spot.
#include is used for reusable HTML just like a standard PHP include. It does not have that parent/child relationship like #yield and #section.
I highly suggest reading the Laravel Blade documentation for a more comprehensive description.
#include and #yield are two completely different types of operations to import code into the current file.
#include - import the contents of a separate file into the current file at the location in which it is placed. i.e.:
Layout file:
< some html or other script >
#include('include.file_name') // "include." indicates the subdirectory that the file is in
< more html or other script >
Include File ( a blade file with a block of code ):
< some cool code here >
The contents of 'file_name' ( also a blade file ) is then imported in where the #include directive is located.
#yield imports code from a "section" in the child file ( the "view" blade file. ) i.e.:
Layout file:
< some html or other script >
#yield('needed_section_name')
< more html or other script >
The following section is needed in the "view" blade file that is set to "extend" that layout file.
"View" blade file:
#extends('layout.file_name')
... code as neeeded
#section('needed_section_name')
< some cool code here >
#stop
...
more code as needed
Now the layout file will import in the section of code that matches the naming used.
More on the subject here....
The difference between #yield and #include is how you use them.
If you have a static kind of content, like a navbar, this part of the page will always be in the same place in the layout. When you use #include in the layout file, the navbar will be put once per layout. But if you use #yield you will be enforced to make a #section of the navbar on every page that #extends the layout.
#yield is, on the other hand, a better choice when content is changing on all the pages but you still want to use the same layout everywhere. If you use #include you'll have to make a new layout for every page, because of the difference of content.
Today I was trying to figure out this difference as well, and where to use each, and why would I want to use one over the other. Please be warned this answer is verbose and probably very over-explained.
Snapey from the Laracasts forums got me started thinking about them properly:
https://laracasts.com/discuss/channels/laravel/whats-the-difference-between-atinclude-and-atyield
First off, #include is going to include an entire file, just like the PHP include function. That's great if you're just dumping an entire file of content into the <body> of your page, for example the following is going to include everything inside of 'content.blade.php':
<!-- layout.blade.php -->
<body>
#include('content')
</body>
<!-- content.blade.php -->
<div>
<div>
<p>Hey this is my content.</p>
</div>
<div>
<span>and stuff</span>
</div>
</div>
But #yield, in conjunction with #extends and the #section and #endsection directives, will allow you to have your content chunked into separate sections, but kept all in one file. Then you can #yield it into the layout in separate chunks. The visual that comes to mind is shuffling one half of a deck of cards into the other half, in a classic "riffle" shuffle:
<!-- content.blade.php -->
#extends('layout')
#section('top_content')
<h1>Hey I'm the title</h1>
#endsection
#section('middle_content')
<p>Hey how's it going</p>
#endsection
#section('other_content')
<p>It's over now.</p>
#endsection
<!-- layout.blade.php -->
<body>
<div>
#yield('top_content')
</div>
<p>Some static content</p>
<div>
#yield('middle_content')
</div>
<p>Some more static content</p>
<div>
#yield('other_content')
</div>
<div>Static footer content of some kind</div>
</body>
Secondly and maybe more importantly, the flow of control is sort of inverted, in a way that makes everything much more coherent. In the first example, with #include, you'd be calling the layout file with the view helper, in sort of a top-down way. For example this might be your code:
Route::get('/', function () {
return view('layout');
});
But with #yield and #extends, (as in the second example) you call the content file itself, and the content file will first look at the #extends directive to drape itself with the layout file, like it is putting on a coat. So it happens in reverse, in a sense, like bottom-up. Then the #yield directives inject the content as specified. The content file is who you are talking to in your router/controller:
Route::get('/', function () {
return view('content');
});
You call the content view, it looks at the #extends directive to pick the layout, and then the #yield directives in the layout file inject the matching #section sections into the layout.
So this way is much more useful because in practice you'll be referring to different content when you refer to different views.
If you were only using the #include statement to build your views, then you'd have to pass a different content slug to the layout file that you are calling every time, maybe like this:
Route::get('/welcome', function () {
return view('layout', ['content' => 'welcome']);
});
Route::get('/profile', function () {
return view('layout', ['content' => 'profile']);
});
<!-- layout.blade.php -->
<body>
#include($content)
</body>
And that seems like a mess to me.
That all being said, #include seems like a great way to include a little snippet in your layout file (the one called by the #extends directive), like the nav bar, or the footer, or something you just want to separate out of your layout file for organizational purposes.
#yield should be used when your contents will be changed
#include should be used for contents that wont change. e.g header, footer
#include used for reusable code like navbar, we have to design navbar one time and use it in our whole site.
#yield used for sections that change again and again like body.
for example you have already your layout structure where you #include('some scripts or style'). it will not allow you to change its directive while #yield you can change its content. means you create a section to yield into your layout.blade.php. you can use yield also if you have a specific script or style in each page.
#include('layouts.nav') //default when you call layout.blade.php
<div class="container">
#yield('content') //changes according to your view
</div>
#include('layouts.footer') //yes you can use #yield if you have specific script.

Undefined variable in a child view

i have created a master layout and extending it to a child view this way:
master.blade.php (short version):
<body>
#section('content')
#foreach($articles as $article)
{{ $article->title }}
#endforeach
#show
</body>
Then a child view called child.blade.php:
#extends('master')
#section('content')
<p>Some static content</p>
#stop
However, when i am visiting a page with child.blade.php i am getting an error:
Undefined variable: articles (View: /app/views/master.blade.php)
Why am i getting this error? I don't have this variable in my child.blade.php, so i guess - child view inherits master's variables by default? But why? I didn't used #parent
What you really want is View Composer. This way you can share the data between several views without repeating yourself. In your case whenever your child.blade.php view will be rendered additional data you want to pass will be added.
Read more at docs: View Composers
If you don't want to use View composer you need to pass the articles to your child.balde.php

Using include in different situations

I have a boilerplate that has various includes, one being:
#include('nav')
I would like to use the same boilerplate for the CMS of my site, but use a different nav.
What would be the best way of getting the boilerplate to include a different nav when the user is using the CMS:
#include('nav-cms')
This is more of an architectural question, and the answer is that you can probably do this many, many ways. However, the answers can be Laravel specific, so here goes:
One method would be to change the include statement to be:
#include($navView)
And then either in your controller, or using view composer, you should set that variable appropriately.
Alternatively, you can do it using sections:
// layout.blade.php
<html>
<head></head>
<body>
#section('nav')
#include('nav')
#show
#yield('content')
</body>
</html>
// some-frontend-view.blade.php
#extends('layout')
#section('content')
Content here
#stop
// some-cms-view.blade.php
#extends('layout')
#section('nav')
#include('nav-cms')
#overwrite
#section('content')
CMS content here
#stop
That way it assumes frontend nav, and then you override it in the CMS for the CMS nav. Alternatively, instead of defaulting to 'nav' in the layout, you could use #yield, and specify it in the some-frontend-view.blade.php file as in the some-cms-view.blade.php file.

Resources