I'm using Laravel 4 and I'd like to extend what's already placed in my master.blade.php template.
<!DOCTYPE html>
<html>
<head>
#section('head')
#parent
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>{{$title}}</title>
<meta name="description" content="{{$description}}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ asset('assets/css/main.css') }}">
#show
</head>
<body>
...
For example, my home.blade.php template:
#section('head');
appending to head....
#show
#section('content')
<h2>Hello World</h2>
#show
So I was trying to append "appending to head..." into the template. But it just replaces what's already there. With some research I came to an conclusion that it's not possible, but I'm not sure how else would I do this.. Partials? Includes?
What can I do?
Use this code in the home.blade.php template that extends the master.blade.php:
this could be your home.blade.php
#extends('master')
#section('head')
#parent
{{{ $head_data }}}
#stop
{{-- Content --}}
#section('content')
Here comes you content...
#stop
You can call it from your controller
<?php
class HomeController extends Controller {
public function getIndex()
{
$head_data = 'appending to head....';
return View::make('home', compact('head_data'));
}
}
Related
There are many questions here that are similar to mine, such as:
Pass variable to a component Laravel 9
Cannot access Blade Component variables inside the view
Passing variable from component into a slot
but I have not found a resolution to my problem in any of them. I've also scoured the doc at: https://laravel.com/docs/9.x/blade#components
I would have thought this would be a simple task.
I have the following structure, in Resources/views:
start.blade.php (uses)
components/layout.blade.php (uses)
components/head.blade.php
From my controller, I call:
$data =
[
'total' => $total,
'uses_form' => true
];
return view('start', $data);
Inside start.blade.php, I have:
<x-layout>
<x-slot name="uses_form">
{{ $uses_form }}
</x-slot>
<!-- additional html -->
</x-layout>
Inside layout.blade.php:
<!DOCTYPE html>
<html lang="en">
<x-head :uses_form:$uses_form />
<!-- also tried: #include('includes.header', ['uses_form' => $uses_form])-->
<body>
<div class="container-fluid">
{{ $slot }}
</div><!--container-fluid-->
</body>
</html>
Finally, in head.blade.php:
<head>
<link type='text/css' rel='stylesheet' href='/css/vendor/bootstrap.min.css' />
#if ($uses_form === true)
<link type='text/css' rel='stylesheet' href='/css/form.css' />
#endif
</head>
This results in an:
Undefined variable $uses_form
at:
head.blade.php: line 3
How can I get the variable to be recognized in head.blade.php?
I'm open to other approaches, such as generated the conditional style include, at a higher level, but I rather keep this check in head.blade.php for maintainability.
Using Laravel version 9.48.0
Edit (Additional Notes)
If I var_dump $uses_form from the top of layout.blade.php, I get the following:
object(Illuminate\View\ComponentSlot)#301 (2) {
["attributes"]=> object(Illuminate\View\ComponentAttributeBag)#299 (1) {
["attributes":protected]=> array(0) { }
}
["contents":protected]=> string(1) "1"
}
So, it's already changed form.
You can try to pass the variable $uses_form from the parent component layout.blade.php to the child component head.blade.php using following changes and I hope it will helpful to you.
layout.blade.php look like:
<!DOCTYPE html>
<html lang="en">
<x-head :uses-form="$uses_form"/>
<body>
<div class="container-fluid">
{{ $slot }}
</div><!--container-fluid-->
</body>
</html>
head.blade.php look like:
<head>
<link type='text/css' rel='stylesheet' href='/css/vendor/bootstrap.min.css' />
#if ($usesForm === true)
<link type='text/css' rel='stylesheet' href='/css/form.css' />
#endif
</head>
I got it working. There were a few things needing adjusting, but, mainly, I needed to modify the component classes to accept the parameter data.
Another change that was needed, was to pass the data to the layout component, at the top of start.blade.php, like so:
<x-layout :hasForm="$hasForm">
Also, as indicated in another answer and in comments, I needed to place the variable in quotes.
Finally, I'm not sure if this was part of problem, but I changed the uses_form variable from snake_case to camelCase.
The changes, from the question are such:
Controller:
$data =
[
'total' => $total,
'hasForm' => true
];
return view('start', $data);
start.blade.php
<x-layout :hasForm="$hasForm">
<!-- additional html -->
</x-layout>
app/View/Components/Layout.php
class Layout extends Component
{
public $hasForm;
public function __construct($hasForm)
{
$this->hasForm = $hasForm;
}
}
layout.blade.php
<!DOCTYPE html>
<html lang="en">
<x-head :hasForm:"$hasForm" />
<body>
<div class="container-fluid">
{{ $slot }}
</div><!--container-fluid-->
</body>
</html>
app/Views/Components/Head.php
class Head extends Component
{
public $hasForm;
public function __construct($hasForm)
{
$this->hasForm = $hasForm;
}
}
head.blade.php
<head>
<link type='text/css' rel='stylesheet' href='/css/vendor/bootstrap.min.css' />
#if ($hasForm === true)
<link type='text/css' rel='stylesheet' href='/css/form.css' />
#endif
</head>
Hope this may help someone else, down the line.
I try build a React Laravel webpage.
The main.blade.php responsible the layout and that pass data and React components to other blade
I test my app and make few blade.php
So I try comment out several way this line:
/* const data = {{ Illuminate\Support\Js::from($data)}};*/
but not work. It still perceives it as if it were there
I have to pass data for every route for testing because I can't comment the above line
Route::get('/react', function () {
$data = User::find(1);
return view('reactpractice', compact("data"));
})->name('react');
main.blade.php
<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.0">
<link rel="stylesheet" href="/css/app.css"/>
<title>#yield('title')</title>
<title>{{env('APP_NAME')}}</title>
</head>
<body>
<header>
Motto
</header>
<nav>
Index
About
React
Users
Login
Register
</nav>
#yield('contenttop')
#if(Session::has('successmessage'))
<div class="alert alert-success my-3">
{{Session::get('successmessage')}}
</div>
#endif
#yield('example')
<script>
const data = {{ Illuminate\Support\Js::from($data)}};
const token = '{{#csrf_token()}}'
</script>
<h2> React</h2>
<script src="js/app.js"></script>
</body>
</html>
So how comment script tag content in blade.php?
Rather than comment the line in JavaScript, why not make it conditional?
#if (isset($data))
const data = {{ Illuminate\Support\Js::from($data)}};
#endif
This way, if $data is provided, the JavaScript variable will be created. If $data is missing, it will be ignored and won't break your code.
<!-- Try like this -->
// or /* */
I hope it was helpfull.
Description
I am trying to dynamically load a Livewire component inside a modal, using Livewire. I can successfully load the HTML content in the modal, but any Javascript on the "target" component is not executed.
Exact steps to reproduce
<!-- index.blade.php -->
<div>
<a onclick="showTask(1)">Open task #1</a>
#includeWhen($openTask, 'partials.tasks._task_modal')
</div>
//Index.php
function showTask(int $taskId){
$this->managingTask = true;
$this->openTask = Task::firstWhere('id', $taskId);
}
So in the above code, when a user clicks the a tag, it will open the modal, placed in:
<!-- _task_modal.blade.php -->
<x-jet-dialog-modal wire:model="managingTask">
<x-slot name="content">
#livewire('tasks.show', ['task' => $openTask])
</x-slot>
</x-jet-dialog-modal>
As you can see, the modal component simply refers to another Livewire component called tasks.show. Inside this, I have the following in the view file:
<!-- show.blade.php -->
<div>
<a onclick="test()">Test</a>
</div>
#push('scripts')
<script type="text/javascript">
function test(){
alert("It works!")
}
document.addEventListener('livewire:load', function () {
console.log("Livewire Loaded");
});
</script>
#endpush
This is my layout file:
<!-- app.blade.php -->
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
#livewireStyles
<!-- Scripts -->
<script src="{{ mix('js/app.js') }}" defer></script>
</head>
<body class="font-sans antialiased" >
<div id="root" x-data>
{{$slot}}
</div>
#stack('modals')
#livewireScripts
#stack('scripts')
</body>
</html>
Now, when clicking on the a link inside the show.blade.php Livewire component, I get the following error:
Uncaught ReferenceError: test is not defined
Further, I do not see the "Livewire Loaded" in my console.
Context
Livewire version: 2.3.6
Laravel version: 8.12
Browser: Chrome
I have master layout of laravel blade template main.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>#yield('title','My Site')</title>
</head>
<body>
#yield('container','Content area')
{{ HTML::script('assets/js/jquery-1.9.0.js') }}
</body>
</html>
I extended it for another view index.blade.php
#extend('main')
I want to add javascript links to master layout(main.blade.php) if exists in child layout(index.blade.php)
added code in index.blade.php
$extraJs = array('plugins1.js','plugins2.js');
#section('extraJs')
{{ $extraJs }}
#stop
So, How can I add javascript to master layout if exists in child blade?
In php:
<?php
if(isset($extraJs)):
foreach($extraJs as $js):
?>
<script src="assets/js/<?php echo $js ?>" type="text/javascript" />
<?php endforeach; endif; ?>
You can just add a yield in your main.blade.php, like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>#yield('title','My Site')</title>
</head>
<body>
#yield('container','Content area')
{{ HTML::script('assets/js/jquery-1.9.0.js') }}
#yield('javascripts')
</body>
</html>
Then, in your child layout, you add a section for it, like you did. For example:
#section('javascripts')
#foreach($scripts as $script)
{{ HTML::script('ets/js/' . $script) }}
#endforeach
#stop
If you add another child view which doesn't need to use extra javascripts, Laravel won't complain because the section is optional.
I wouldn't really encourage this method but since you asked. It is definitely possible to pass something "up" in the view tree. You can just define a PHP variable in your view and it will be available anywhere in the layout.
index.blade.php
<?php $extraJs = array('plugins1.js','plugins2.js'); ?>
main.blade.php
#if(isset($extraJs))
#foreach($extraJs as $js)
<script src="{{ asset('assets/js/'.$js) }}" type="text/javascript" />
#endforeach
#endif
As you can see I also converted your code in the layout to blade and made use of the asset() function to generate absolute URLs
Note Instead of doing it this way there are other methods. For example View composers or defining the plugins in the controller.
This is the problem, its not reading #layout()
Inside the folder View/authors/index.blade.php
#layout('layouts.default')
#section('content')
Authors Home Page
#endsection
In the folder Controllers/authors.php
class Authors_Controller extends Base_Controller{
public $restful = true;
public function get_index(){
return View::make('authors.index')->with('title', 'Autores e Livros');
}
}
and inside the folder View/layouts/default.blade.php
basic html
<html>
<head> <title> {{ $title }} </title> </head>
<body>
{{ $content }}
</body>
</html>
Where's my error? why is it not reading?
First: Inside View/layouts/default.blade.php
<html>
<head> <title> {{ $title }} </title> </head>
<body>
#yield('content')
</body>
</html>
And second: Update
I'm like 99% sure that '#layout('layouts.default')' in your View/authors/index.blade.php is not on the first line. It has to be at the top of the page.
It seems in Laravel 4 you should use #extends('layouts.default') instead of #layout('layouts.default')