How to create a new page layout in Laravel/Livewire - laravel

This is a complete new application using Laravel 9 and Livewire
By default you have two layouts, guest and app. I want to create a new layout for all my admin things.
So, first I create a component
php artisan make:component AdminLayout
This creates \app\View\Components\AdminLayout.php, it read as:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class AdminLayout extends Component {
public function render() { return view('layouts.admin'); }
}
As any of the other two AdminLayout.php or GuestLayout.php
So now I write app\resources\views\layouts\admin.blade.php which is a stantandard HTML with the {{ $slot }} blade directive, something as...
<html>
<head>
...
<title>Admin Page</title>
...
#livewireStyles
#vite([...])
</head>
<body>
<main class="...">
{{ $slot }}
</main>
#livewireScripts
</body>
</html>
Then I create the admin routes... The Index class is in \app\Livewire\Admin\Index.php and it is correctly imported
Route::get('', Index::class)->name('home');
The Index.php reads as
class Index extends Component {
public function render() { return view('livewire.admin.index'); }
}
The \app\resources\views\livewire\admin\index.blade.php reads:
<x-admin-layout>
Hello
</x-admin-layout>
So everything seems to be right... now I have two problems that I can't spot/solve. When I load the http:://server.test/admin it should load this page. 1) It doesn't change the title in the page for Admin Page, 2) It always loads the #livewire('navigation-menu'), and looks like the followin picture:
If I add things above the {{ $slot }} or below, they are rendered. If I add another #livewire('navigation-menu') it is rendered. But I'm not able to take it out, even when I'm not telling to display it.
Any idea?
I just noticed that if I add a comment in the guest layout or the admin layout, it simply ignores it. If I add a comment in the app layout it somehow "propagates" to both the guest and admin layout. Is this the expected behaivour?

Related

How to structure views for admin layout in laravel blade?

The goal is to create an admin area in my laravel project. I have a question about how to structure views and controllers to create the admin layout using laravel components.
Say I have a single controller (app/Http/Controllers/CategoryController.php) at the moment:
class CategoryController extends Controller
{
public function index()
{
return view('category.index');
}
}
View (resources/views/categories/index.blade.php):
<x-app-layout>
Categories Index Page
</x-app-layout>
The base layout is defined in resources/views/layouts/app.blade.php.
Functionality that is inside CategoryController is for admins only. I want to create an admin layout that inherits from the base layout. The category views then go inside the admin layout. The admin layout has a sidebar on the left with a navigation. The navigation points to controllers like CategoryController and UserController. The admin layout will expose various admin functionality.
What I've tried:
views/admin/admin.blade.php:
<x-app-layout>
<h1>TEST</h1>
{{$slot}}
</x-app-layout>
and views/admin/categories/index.blade.php:
<x-admin>
Categories Index Page
</x-admin>
Error:
Unable to locate a class or view for component [admin].
Any ideas what I'm doing wrong here? How should one structure the views for suche use case?
Create a resources/views/layouts/admin.blade.php that looks something like this:
#extends('layouts.app')
#section('content')
<div class="navigation">
...YourNavbar...
</div>
<div class="content">
#yield('content')
</div>
#overwrite
(Edit the code inside to match how you want your navbar/content to look like)
Now your resources/views/categories/index.blade.php should use #extends('layouts.admin') instead of #extends('layouts.app')
Edit: this is assuming your app.blade.php has a #yield('content') to show content

anyway to remove not needed css in laravel using blade

I have 4 blade page
=> layout.blade.php
=> index.blade.php
=> contact.blade.php
In layout.blade.php i have two yield
One Is:
#yield('css') // to add additional css
Another One Is:
#yield('script') //to add additional script
index.blade.php extends layout.blade.php
so that i can add section('css') and section('script') for additional css or script only for index.blade.php page
Now the problem is: In layout.balde.php has all the common link and script But i don't want those link to every page. i want some way to; not to load a specific link or some link in some page that extends layout.blade.php.
Example:
=> layout.blade.php
-> <link href="one.css">
-> <link href="two.css">
=> index.blade.php extends layout.blade.php
-> <link href="one.css"> // because index extends layout
-> <link href="two.css"> // because index extends layout
=> contact.blade.php extends layout.blade.php
-> <link href="one.css"> // because index extends layout (i don't want to load this link)
-> <link href="two.css"> // because index extends layout
Note
I NEED SOME DYNAMIC WAY TO SAY FROM contact.blade.php TO OFF THIS LINK OR SOME LINK THAT COME FROM layout.blade.php
#yield only use one time from #section
So use #push
#stack in you main layout and many #push in multiple views
In your layout.blade.php add #stack('scripts')
And in index.blade.php add
#push('scripts')
<script src="/index.js"></script>
#endpush
And in contact.blade.php add
#push('scripts')
<script src="/contact.js"></script>
#endpush
You can push multiple css or js or content with #push and #stacks
See https://laravel.com/docs/5.8/blade#stacks
If you want to disable some css or js in specific page you can make check if page is contact
In web.php add route name to contact page
Add this to layout.app.php
#if(request()->route()->getName() != "contact")
Load your css here as page not contact
#endif
So if you open contact page the css not loaded as route name is contact

Parameter in Route::get caused style to disappear?

I'm still new to Laravel. Anyway, I'm making a small system of viewing and creating articles to be shown in the main site. I wanted to create a page that displays an article from the database, using a parameter from the URL, like this:
http://localhost:8000/read/1
The above, for example, will display the article with 'id' value of 1 in the database.
So it works just fine, but problem is, after I got it to work (which took me some time since I'm a newbie), the whole style just disappears from the page. I tried to rewrite everything but it still didn't work. New pages that I create include the style just fine.
This is my route line:
Route::get('read/{id}', array('as' => 'read', 'uses' => 'NewsController#readArticle'));
NewsController readArticle function:
public function readArticle($id) {
$article = NewsMessage::where('id', $id) -> first();
return View::make('news.read', array('article' => $article));
}
And the file read.blade.php (located in views/news/read.blade.php)
#extends('layouts.main')
#section('content')
{{ $article -> title }}
#stop
So the whole PHP code works fine and I manage to get the title. But for some reason, the whole style disappears and this is what I see:
http://puu.sh/ctO6J/db30fbe102.png
So any idea, what have I dont wrong that caused this? The other pages work just fine with the style included.
Thank you!
The issue is that the path to the image is incorrectly specified.
You can either use the built in asset methods or something like {{ URL::to('/')/imagepathhere/filename.jpg }}
Assuming you have your styles links wrote as:
#extends('layouts.main')
#section('styles')
<link href="css/custom.css" rel="stylesheet" />
<link href="css/styles.css" rel="stylesheet" />
#endsection
#section('content')
{{ $article -> title }}
#endsection
Correct Syntax:
#extends('layouts.main')
#section('styles')
<link href="{{ asset('css/custom.css') }}" rel="stylesheet" />
<link href="{{ asset('css/styles.css') }}" rel="stylesheet" />
#endsection
#section('content')
{{ $article -> title }}
#endsection
And make sure your css folder is located at public folder when calling with asset() helper.
This issues of disappearing the whole page styles is causing by accessing the image or css file or any other resources, and the solution is to use asset() helper function.
NOTE: YOUR ROUTES AND CONTROLLER HAS NO ISSUE, YOU DON'T NEED TO TOUCH EITHER.

Laravel 4 - Extending the layout using blade templating

I have just setup my Laravel 4.2 application and am following some online tutorials about authentication.
The tutorials are telling me to add
protected $layout = "layouts.main";
and then when calling a view, call it like so
$this->layout->content = View::make('users.register');
But, if im following the Laravel website in creating my templates, it tells me to add
#extends('layouts.main')
At the beginning of my users/register view
Do i need to bother about the 2 bits of code i added at the beginning if im using that #extends call?
Im really confused.
Cheers
No, docs don't say you should do that.
You either do define controller layout (a), or return the view which extends layout (b)
A: Controller layout
/**
* The layout that should be used for responses.
*/
protected $layout = 'layouts.master';
/**
* Show the user profile.
*/
public function showProfile()
{
$this->layout->content = View::make('user.profile');
}
B: View extending layout view
// app/views/layout/master.blade.php
<html>
<head>
<title></title>
</head>
<body>
<header>
#yield('header')
</header>
<section>
#yield('content')
</section>
<footer>
#yield('footer')
</footer>
</body>
</html>
// app/views/profile.blade.php
#extends('layout/master')
#section('header')
Header content here
#stop
#section('content')
Master content here
#if (Auth::user()->isAdmin)
#include('admin-panel')
#endif
#stop
#section('footer')
Footer content here
#stop
// Controller
/**
* Show the user profile.
*/
public function showProfile()
{
return View::make('profile');
}

Laravel 4 content yielded before layout

I am using a fresh build today of Laravel 4.
I have a dashboardController
class DashboardController extends BaseController {
protected $layout = 'layouts.dashboard';
public function index()
{
$this->layout->content = View::make('dashboard.default');
}
}
I have a simple route
Route::get('/', 'DashboardController#index');
I have a blade layout in views/layouts/dashboard.blade.php
For the sake of saving everyone from all of the actual HTML ill use a mock up.
<html>
<head>
<title></title>
</head>
<body>
#yield('content')
</body>
</html>
I have a default blade file in views/dashboard/ that has the following (edited for simplicity)
#section('content')
<p>This is not rocket science</p>
#stop
For some reason the content gets generated before the layout.
I am using a different approach to set the layouts globally to routes using a custom filter. Put the following filter into the app/filters.php
Route::filter('theme', function($route, $request, $response, $layout='layouts.default')
{
// Redirects have no content and errors should handle their own layout.
if ($response->getStatusCode() > 300) return;
//get original view object
$view = $response->getOriginalContent();
//we will render the view nested to the layout
$content = View::make($layout)->nest('_content',$view->getName(), $view->getData())->render();
$response->setContent($content);
});
and now instead of setting layout property in the controller class, you can group the routes and apply the filter as shown below.
Route::group(array('after' => 'theme:layouts.dashboard'), function()
{
Route::get('/admin', 'DashboardController#getIndex');
Route::get('/admin/dashboard', function(){ return View::make('dashboard.default'); });
});
When creating the views, make sure to use the #section('sectionName') in all the sub views and use #yield('sectionName') in the layout views.
I find it easier to do my layout like this for example. I would create my master blade file like so
<html>
<body>
#yield('content');
</body>
</html
And in the blade files that I want to use the master at the top i would put
#extends('master')
then content like so
#section('content')
// content
#stop
Hope this helps.
When you use controller layouts, i.e. $this->layout->..., then you get access to data as variables, not sections. So to access content in your layout you should use...
<html>
<head>
<title></title>
</head>
<body>
<?php echo $content; ?>
</body>
</html>
And in your partial, you would not use #section or #stop...
<p>This is not rocket science</p>

Resources