Laravel Blade Changing Active Class Bootstrap - laravel

How will I change the active class in twitter bootstrap when i visit another page with Laravel Blade Templating ?

here is an example this might can help
You could define a variable in your blade template
<?php $nav_profile = 'active'; ?>
#extends ('layouts.app')
#section ('content')
..
..
#endsection
And then in the layouts file;
<ul class="nav nav-tabs">
<li role="presentation" class="{{ $nav_home or '' }}">Home</li>
<li role="presentation" class="{{ $nav_profile or '' }}">Profile</li>
<li role="presentation" class="{{ $nav_messages or '' }}">Messages</li>
</ul>
So, if the page includes a variable called nav_profile then insert 'active' into the class. The 'or 'part inserts an empty string if the variable is not present.

I have found a simple solution for this problem. This solution has very simple trick.
And it will work for all links throughout the page.
<script>
function addActiveClass(){
var objs = document.getElementsByTagName('a'); // take all 'a' tags
for(var i = 0; i < objs.length; i++){
if(objs[i].href == window.location.href){ // check if the user is on this link
objs[i].className = objs[i].className + " active"; // add additional 'active' class
}
}
}
addActiveClass();
</script>
Adding this code to the end of your page will do the magic.

Related

Laravel calling controller function from blade file not working

I have a Laravel project where I'm trying to call a controller function from blade file called nav.blade.php, but I'm getting following error:
syntax error, unexpected fully qualified name
"\App\Http\Controllers\ProductC...", expecting ":".
nav.blade.php
{{ use \App\Http\Controllers\ProductController; }}
<div class="container">
<ul class="navbar-nav mr-auto">
{{ $is_admin = ProductController::isAdmin(); }}
#if($is_admin == "admin")
<li class="nav-item">
<a class="nav-link" href="/posts">Admin</a>
</li>
#endif
</ul>
</div>
ProductsController.php
public static function isAdmin()
{
$user_id = Auth::id();
$user = User::findOrFail($user_id);
$is_admin = $user->role;
if($is_admin==="admin"){
return "admin";
}elseif($is_admin==="moderator"){
return "moderator";
}else{
return "user";
}
}
You access the static controller function from the blade template.
<?php
$isAdmin= App\Http\Controllers\ProductController::isAdmin();
?>
{{ }} are used to echo anything you want. If you want to import a class, one solution is to do like the following:
<?php
use \App\Http\Controllers\ProductController;
$is_admin = ProductController::isAdmin();
?>
<div class="container">
<ul class="navbar-nav mr-auto">
#if($is_admin == "admin")
<li class="nav-item">
<a class="nav-link" href="/posts">Admin</a>
</li>
#endif
</ul>
</div>
But this isn't a best practice I recommend you to move isAdmin() method from ProductController and set it as global function of your system so you can directly access it from your view without importing a controller.
Never EVER use a controller in a Blade. That is not good in any way and would require me a lot of explanation that is already in some blogs...
A controller is ONLY used for accessing something through a URL, do something and done, it is not a Service class where you do business logic anywhere you want.
So, move that method to a Service class (do not confuse with Service Provider) and use it in the blade. It would still be better to pass that variable to the view and not using any class just for that...

Homepage won't show newly added records but other pages do

I'm using a Laravel 5.7 in an old web project last year 2019 but now I encountered a very weird bug.
This is a website that when you add a new game, it will show to the menu list and if it is featured it will show to the homepage content.
this is the table ['game_id', 'name', 'key', 'status', 'order', 'is_featured']
in the header view I put this code:
<ul class="nav-menu">
<li class="{{ ($page == "games" ? 'menu-active' : '') }} submenu dropdown"><a href="/games" >Games</a>
<ul class="dropdown-menu">
#foreach(GetPublishedGames() as $game)
<li class="nav-item">{{$game->name}}</li>
#endforeach
</ul>
</li>
...
calling this helper code GetPublishedGames()
function GetPublishedGames(){
$data = DB::table("game")->where("status", 1)->orderBy("order")->get();
return $data;
}
in the homepage controller I had this line
"feat_games" => Game::where("status", 1)->where("is_featured", 1)->orderBy("order")->limit(5)->get(),
that calls in the homepage view:
#if(count($feat_games))
#foreach($feat_games as $feat_game)
<div class="feat-game-item wow fadeInUp">
... some content ...
</div>
#endforeach
#endif
I have no idea why this happening, it works before in the local and development stage. I did tried to clear cache.
any idea?

Recursive display of data with blade, laravel

My Controller:
class Comments extends Controller {
public function GenerateComments($id){
$theme = DB::table('New_Themes')
->where('id', $id)
->get();
$Comments = NewTheme_Comment::where('id_theme', $id)->get();
return view('comments', ['Themes'=>$theme, 'Comments'=>$Comments]);
}
My Table(NewTheme_Comment):
id
parent_id
id_theme
user
text
upVotes
downVotes
My view(contains the recursive display of the tree of comments like the same in reddit), ......(data) contains the bootstrap media object, and the </div>'s things are used to round up (visually) the tree of comments as it should be:
<?php
tree($Comments, 0, 0);
$var = -1;
function tree($Comments, $parent_id = 0, $level=0, $c=0) {
global $var;
foreach($Comments as $Comment) {
if($Comment['parent_id'] == $parent_id) {
If ($level > $var) $var++; else {
for ($i = $var-$level+1; $i>0; $i--) { if ($c < 0) echo '</div> </div>'; else $c--; };
$var=$level;
};
echo '........(data)';
tree($Comments, $Comment['id'], $level+1,$c);
};
};
};
?>
The problem is that .........(data) should contain this stuff:
<div class="media">
<div class="media-left">
<img class="media-object" style="height:40px; width:40px;" src="{{ URL::asset("images/upVote.svg") }}" >
<div>{{$Comment->upVotes-$Comment->downVotes}}</div>
<img class="media-object" style="height:40px; width:40px;" src="{{ URL::asset("images/downVote.svg") }}" >
</div>
<div class="media-body">
<p class="media-heading">{{ $Comment->text }}</p>
<p class="media-heading">{{ $Comment->user }} / {{ $Comment->created_at }} </p>
And I am using the blade above this line | , which I can't integrate into that echo in view, replacing the ..........(data).
I have the intuition that the function I should integrate into the controller but I am broken(I spent to much time on recursive method of displaying comments) and I don't know how to take the data and print out it as whole unit recursively.
Any help is GREATLY appreciated to find a way out of this mess, thank you very much
Edit 1:
This is an example if i am filling with bootstrap media object in ........(data):
<div class="media">
<a class="media-left" href="#">
<img class="media-object" src="..." alt="...">
</a>
<div class="media-body">
<h4 class="media-heading">Media heading</h4>
Without 2 x </div>
You are approaching the views in a wrong way, as blade templates are not meant to use functions, it's better to follow the below recommendations.
The best way for that is to place the function code inside a blade file, for example recursive.blade.php:
recursive.blade.php
#foreach($comments as $comment)
//place your code here
#endforeach
Then in your main blade you can call it several times:
main.blade.php
<div>
#include('recursive', ['comments' => $comments])
</div>
The below example works for me and is the most widely used approach. remember the default value for parent_id is -1.
Model
public function children(){
return $this->hasMany(self::class,'parent_id','id')->with('children');
}
Controller
$comments = Comments::where('parent_id','=',-1)->get();
return view('comments',['comments'=> $comments]);
Blade (comments.blade.php)
<div class="tree">
#include('comment-list-widget',['comments' => $comment])
</div>
Blade (comment-list-widget.blade.php)
<ul>
#foreach($comments as $comment)
<li>
<a>{{$comment->text}}</a>
#if(!empty($comment->children) && $comment->children->count())
#include('comment-list-widget',['comments' => $comment->children])
#endif
</li>
#endforeach
</ul>

Laravel dynamic breadcrumbs with links

I am trying to implement dynamic breadcrumbs in laravel with links. I successfully render the breadcrumbs but without links by following code.
<ol class="breadcrumb">
<li><i class="fa fa-dashboard"></i>Marketplace</li>
#foreach(Request::segments() as $segment)
<li>
{{$segment}}
</li>
#endforeach
</ol>
But now i am facing issue with the urls. I am getting the current url of the route with all the decendents. Can someone please help me that how can I add links to the breadcrumbs ?
Thanks.
If I understand your issue correctly, you just need to fill in the URL of the link. This is untested but I think it should work.
<ol class="breadcrumb">
<li><i class="fa fa-dashboard"></i>Marketplace</li>
<?php $segments = ''; ?>
#foreach(Request::segments() as $segment)
<?php $segments .= '/'.$segment; ?>
<li>
{{$segment}}
</li>
#endforeach
</ol>
This worked for me, tried in Laravel 5.4.*
Requirement for this code to work flawlessly: All URL's should have hierarchy pattern in your routes file
Below code will create crumb for each path -
Home >
<?php $link = "" ?>
#for($i = 1; $i <= count(Request::segments()); $i++)
#if($i < count(Request::segments()) & $i > 0)
<?php $link .= "/" . Request::segment($i); ?>
{{ ucwords(str_replace('-',' ',Request::segment($i)))}} >
#else {{ucwords(str_replace('-',' ',Request::segment($i)))}}
#endif
#endfor
So Breadcrumb for URL your_site.com/abc/lmn/xyz will be - Home > abc > lmn > xyz
Hope this helps!
Im not sure if you already got a solution for this, but i figured out a way to go about it on my project. It might come in handy for your implementation.
I ended up with either adding the whole url to the link or only the segment, which ofc is not desirable, so using array slice i start slicing from the 0 index in the array and only slice untill the current iteration of the loop, then implode the array into a string and then use URL::to to create the link.
<ol class="breadcrumb">
<li>
<i class="fa fa-home"></i>
HOME
</li>
#for($i = 2; $i <= count(Request::segments()); $i++)
<li>
<a href="{{ URL::to( implode( '/', array_slice(Request::segments(), 0 ,$i, true)))}}">
{{strtoupper(Request::segment($i))}}
</a>
</li>
#endfor
</ol>
As you will notice, I only start my iteration from 2 ($i = 2) as my app base url starts at /admin and i manually put my home Url in the first breadcrumb.
Again you might already have a solution, but throught this could work for people who do not want to add the package to get breadcrumbs.
I wrote a this code that can handle laravel resource ( index | edit | create ) routes dynamically:
Custom Breadcrumb => custom.blade.php
#php
$segments=[];
$l=count(Request::segments())-1
#endphp
#switch(Request::segments()[$l])
#case('edit')
#php
$l--;
$segments=array_slice(Request::segments(),0,$l);
$segments[]=$model->slug // Model that passed to this included blade file
#endphp
#break
#default
#php $segments=Request::segments() #endphp
#endswitch
#php
$link=''
#endphp
#foreach($segments as $sg)
#php $link.='/'.$sg #endphp
#if($loop->index<$l)
<li class="breadcrumb-item">
{{ucfirst($sg=='admin'?'home':$sg)}}
</li>
#else
<li class="breadcrumb-item active">
{{ucfirst($sg)}}
</li>
#endif
#endforeach
Use Custom Breadcrumb => example.balde.php
#include('admin.vendor.breadcrumb.custom',['model'=> $articles])
Just add slash / before any link to add decendents to domain name
like that
<a href="/YourLink" ></a>
I liked the solution offered by #rohankhude but it was not showing "/" after the first segment (marketplace). So here is a clean code.
<div class="breadcrumb">
<ul>
<li>
Home
</li>
<?php $link = "" ?>
#for($i = 1; $i <= count(Request::segments()); $i++)
#if($i < count(Request::segments()) & $i > 0)
<?php $link .= "/" . Request::segment($i); ?>
#if ($i == 1)
/ {{ ucwords(str_replace('-',' ',Request::segment($i)))}}
#else
{{ ucwords(str_replace('-',' ',Request::segment($i)))}}
#endif
#else
<a class="active">/ {{ucwords(str_replace('-',' ',Request::segment($i)))}}</a>
#endif
#endfor
</ul>
</div>

Laravel 4 custom pagination: go to first/last page and show a fixed number of links

I'm using the default Bootstrap slider navigation in Laravel 4 and it works very nice: but now I'd like improve it with two customizations, and I have no clue how:
1: Add a "go to first page" at the beginning, disabled if we are in the first page; and an analogous "go to last page" at the end, disabled if we are in the last page (please see how the arrows are changed compared to default Laravel stuff! I'd like to use "double arrows" (« and ») for "go to first/last", and a single arrow (‹ and ›) for "go to prev/next:
<ul class="pagination">
<li class="disabled"><span>«</span></li>
<li class="disabled"><span>‹</span></li>
<li class="active"><span>1</span></li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>›</li>
<li>»</li>
</ul>
2: Show a custom number of links at a time (i.e. 5) instead of the default long list:
<ul class="pagination">
<li class="disabled"><span>«</span></li>
<li class="disabled"><span>‹</span></li>
<li class="active"><span>1</span></li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>›</li>
<li>»</li>
</ul>
or
<ul class="pagination">
<li>«</li>
<li>‹</li>
<li>2</li>
<li>3</li>
<li class="active"><span>4</span></li>
<li>5</li>
<li>6</li>
<li>›</li>
<li>»</li>
</ul>
Want to see a picture? This is how it should be for various pages (it's an old procedural PHP built on Bootstrap 2.3.2... I have the original code but don't know how to "translate" into Laravel OOP)
So far I made a custom.php view and changed line 'pagination' => 'pagination::slider-3' in laravel/app/config/view.php to 'pagination' => 'pagination::custom'
Then, in custom.php view, I am stuck on:
<?php
$presenter = new Illuminate\Pagination\BootstrapPresenter($paginator);
?>
<?php if ($paginator->getLastPage() > 1): ?>
<ul class="pagination">
</ul>
<?php endif; ?>
Please, any help?
Thanks in advance!
Here you go.
<?php
class MyPresenter extends Illuminate\Pagination\BootstrapPresenter {
public function render()
{
if ($this->currentPage == 1) {
$content = $this->getPageRange(1, $this->currentPage + 2);
}
else if ($this->currentPage >= $this->lastPage) {
$content = $this->getPageRange($this->currentPage - 2, $this->lastPage);
}
else {
$content = $this->getPageRange($this->currentPage - 1, $this->currentPage + 1);
}
return $this->getFirst().$this->getPrevious('‹').$content.$this->getNext('›').$this->getLast();
}
public function getFirst($text = '«')
{
if ($this->currentPage <= 1)
{
return $this->getDisabledTextWrapper($text);
}
else
{
$url = $this->paginator->getUrl(1);
return $this->getPageLinkWrapper($url, $text);
}
}
public function getLast($text = '»')
{
if ($this->currentPage >= $this->lastPage)
{
return $this->getDisabledTextWrapper($text);
}
else
{
$url = $this->paginator->getUrl($this->lastPage);
return $this->getPageLinkWrapper($url, $text);
}
}
}
Feel free to change MyPresenter class name, and in your custom view:
<ul class="pagination">
<?php echo with(new MyPresenter($paginator))->render(); ?>
</ul>
Of course this is not quite perfect (you'll probably run into problem if total pages is less than 3), but this will set you on the right track.

Resources