Undefined variable in a child view - laravel

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

Related

Pass data to included blade view

Let's say that I have the following main view:
<div>
<div>
#yield('content')
</div>
<div>
#include('sidebar')
</div>
<div>
#include('footer')
</div>
</div>
How would I make sure that the included views have their own data? For example, in the sidebar I want to display, let's say, new blog post comments. In the footer I want to display new users and blog posts. Maybe using #include is not the right way to accomplish this?
In your applications, app service providers boot method do something like
View::composer('sidebar',function($view){
$comments= Blog::latest()->comments;
$view->with('comments',$comments);
})
View::composer('footer',function($view){
$users= User::latest();
$view->with('users',$users);
})
//sidebar
Then in the view file do something like
#foreach($comments as $comment)
{{$comment->data}}
#endforeach`
You may want to use View Composers in such case.
Write your logic in View Composer then call it using a service provider, in the boot method
View::composer(
['partials.content', 'partials.sidebar', 'partials.footer], 'App\Http\ViewComposers\MyViewComposer'
);
I'm tried this and it's working with me :
#include('content',array("key"=>"value"))

Blade templating variable reference

I have a list of items which I want to render in the following way:
#foreach($campaignList as $campaign)
<div class="col-md-{{12/$columns}}">
#include('admin.includes.campaign_card',['campaign'=>$campaign,'link'=>true])
</div>
#endforeach
The admin.includes.campaign_card template (with debug)
#extends('admin.includes.base_campaign_card')
{{$campaign}} // Here the data is okay
#section('options')
{{$campaign}} //Here however I get the first item on each loop
#endsection
Basically the campaign object within the section remains the same when looping.
It seems that the issue is related to the fact that you can have just one section with a given name at a time.
There is way to force blade to rerender with #overwrite directive (which is not in the docs apparently) instead of #endsection.
Github comment

Laravel 5.4 render parent view before child view

Is it possible to force laravel to execute the parent view then the child view ? I use a master view with some view composers to create a menu and set some variables, then in my sitemap subview, because the master view is computed after I end up having my menu not created yet.
#extends('layout.master')
#section('content')
{{-- Render this after layout.master --}}
#endsection
Maybe I missed some possibility here.
If you watch code that blade generate in storage/framework/views/some_name.php you can see next code:
<?php echo $__env->yieldContent('content'); ?>
It`s working something like PHP inlcude, when code come to this line it come in to this file with content.
That`s why you can not load master view and then subview.

Blade: extending a template in multiple subviews

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>{{$view}}</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.
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
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.

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