Laravel with blade - multiple inheritance - laravel

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?

Related

Laravel 5 proper way to require CSS file from view

I've got specific Form component, which is declared as
Form::component('fcRadio', 'components.form.fcradio', ['name', 'options', 'selected' => null]);
and used as
{{ Form::fcRadio('name', $options }}
What I want is somehow attach custom CSS file, so if the page fires this component at least once, the desired CSS file is included to the <head> of my document.
For example, in Joomla it was like
$this->document->addStylesheet('my_awesome_style.css');
Is there any way to achieve the same in Laravel?
UPD:
I've extended the answers below a bit to let it add multiple styles from multiple templates. Finally, it looks like this:
#section('styles')
#parent
{{HTML::style('css/fcradio.css')}}
#stop
It works fine, but if I use the component twice per page, style is also adds twice. How can I allow multiple but unique entries?
So this is typically how I deal with it:
In your folder: resources/views I create a folder called layout. This folder handles the templates for all my pages.
Then I create a file called default.blade.php. In it I put the bulk of the HTML code. Here's an example of how default.blade.php could look (slimmed down, obviously)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
#yield('title')
</title>
<link rel="stylesheet" href="{{ asset('css/main.css') }}">
<!-- Additional per-page css -->
#yield('css')
</head>
<body>
#yield('content')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="js/script.js"></script>
<script src="{{ asset('js/bootstrap.min.js') }}"></script>
<!-- Include per-page JS -->
#yield('js')
</body>
</html>
Right, so essentially what we have so far is the #yield() and asset() helpers.
#yield() is special blade syntax that Laravel uses to say, "Okay. Any time a blade view that is inheriting THIS master template calls the section named in this #yield() I will display that content right here.
asset() is a nifty little helper that basically appends your URL structure onto the string you pass it. So if your url is http://MyGreatSite.com and you use asset('js/script.js') it will spit out a fully qualified URL that will work anywhere on the site (http://MyGreatSite.com/js/script.js). asset() is great because you can use it in blade templates that will get sent out as an email and all of the files will work in an email inbox because they are absolute links.
Right. So now we have this master template and we need to use it. So what I do is create another view in the resources/views directory. Lets say we're doing a contact page. I would make contact.blade.php. Now I want to inherit that master template we created. So we do that like so:
#extends('layout.default)
#section('css')
<link rel="stylesheet" href="{{ asset('css/contact.css') }}">
#stop
#section('title')
Contact Us
#stop
#section('content')
<h1>Contact us</h1>
<p>
Contact us via email: contact#mygreatsite.com
</p>
#stop
#section('js')
<script src="{{ asset('js/contact-form.js') }}"></script>
#stop
Okay, so, first things first. At the very top we tell this blade file that we want to use the template we just made. We use the blade helper #extends() and pass it the path to our view relative to the views directory separated by periods.
Next, we want to create the sections that correspond to the template. We do that by opening the section with #section() and passing the name of the section we want to push this block of content to. We write our content and then we close the section by using #stop. Pretty simple. For images, css, or js, we simply use the asset() helper again.
I know it's a little long-winded, but hopefully that helps and explains the process a little better.
tl;dr: Use #yield(), #section(), and asset().
So I think I understand what you are saying.
In your blade layout file create a section inside the head:
<head>
#yield('componentcss')
</head>
And in the component do:
#section('componentcss')
{{HTML::style('css/fcradio.css')}}
#stop
You could also just include the css but I wouldn't advise this:
#section('componentcss')
<style>
.exampleclass {text-align:center;}
</style>
#stop
Hopefully I have understood you correctly.
I've finally found a bit tricky but working solution:
#hasSection('fcRadioStyle')
#else
#section('fcRadioStyle')
{{Html::style('css/components/fcradio.css')}}
#stop
#section('styles')
#yield('fcRadioStyle')
#append
#endif
This makes by Form::fcRadio append this style only once

thymeleaf spring standard dialect: using template

Hello I have some problems with templating pages.
I am returning from controller a view called list:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout/template">
<div layout:fragment="pageContent">
<p>LIST</p>
</div>
</html>
And I would like to put this into template where I have a lot of html stuff and:
<div layout:fragment="pageContent">Demo static page content</div>
But I am getting in web browser only list view.
How to put one view returned from controller to template using SpringStandardDialect?
So if i understand correctly, you want to inject that fragment which is called pageContent into some other html page (lets call it main.html for sake of it.
First thing to do is change the div in list to the following:
<div th:fragment="pageContent">
<p>LIST</p>
</div>
then in your main.html you would call the fragment via:
<div th:include="list::pageContent"></div>
or
<div th:replace="list::pageContent"></div>
Btw "list::pageContent" indicates that its in base folder, if its located in folder called example then it would be "example/list:pageContent".
here is the great example on Thymeleaf website: http://www.thymeleaf.org/doc/usingthymeleaf.html#including-template-fragments
Hope this helps, if not let me know.

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.

Laravel blade templating discrepancy

I have main layout template /views/web/main_lo.blade.php as
<html>
<head>
<meta charset="UTF-8">
<title>{{$title or 'Default Title'}}</title>
</head>
<body>
<div class="section-1-outer">
#section('section-1')
<div class="section-1-parent">parent section 1</div>
#show
</div>
<div class="section-2-outer">
#section('section-2')
<div class="section-2-parent">parent section 2</div>
#show
</div>
<div class="section-3-outer">
#section('section-3')
<div class="section-3-parent">parent section 3</div>
#show
</div>
<div>
#yield('content')
</div>
</body>
</html>
and a section template as:
#extends('web.main_lo')
#section('section-1')
#parent
<div class='section-1-child'>
<p>Appended to parent</p>
</div>
#stop
#section('section-2')
<div class='section-2-child'>
<p>Replace parent</p>
</div>
#stop
#section('section-3')
<div class='section-3-child'>
<p>Replace parent</p>
</div>
#overwrite
Now here section layout is extending main_lo, here First section-1 which is quite clear that child section will include parent section-1 and content in parent section will also be printed.
Now my confusion is what on earth is difference between section-2 and section-3 implementation as they both replace content of parent section and only content in child get printed. I mean what is need of this extra #overwrite tag when documentation clearly states that
"Note that views which extend a Blade layout simply override sections
from the layout."
and then there is Overwriting Sections using #overwrite which is also for replacing content of parent section.
Laravel view's sections are a bit oddish and the bad part is that it's not obvious from the start.
Sections are actually extending in converse order, the section defined first will be the child and the one later will be the parent. So #parent is actually including the content of the section which may come after.
This is why I think parent and child are not the best terms for this system.
This is not obvious because of the conventional use case - layouts - it looks like the layout sections are the ones defined first. But actually they ran after the content sections are rendered.
This means #overwrite is actually used with the parent section, not the child. Which wouldn't make much sense in your example as you're yielding (#show) in the layout too, meaning you don't want to overwrite there.
The reason for this is actually because #overwrite was made for less conventional use cases, not when you have a layout-content, parent-child relationship.
Most often this happens when you include some partial files - maybe all over the place - where you use the same section names and you run into a problem when the earlier defined section is the one showing instead of the later.

Nesting views with laravel Blade

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.

Resources