Using laravel-menu, how do I get sub-items to nest? - php

I am using Lavary's laravel-menu package, and I am trying to build a simple 2 level menu system based on the contents of a db table. I have the middleware created to create the menu on each request:
public function handle($request, Closure $next)
{
Menu::make('NavBar', function($menu){
$menuitems = MenuItem::all();
foreach($menuitems as $menuitem)
{
if(!is_null($menuitem->parent)){
// For example, 'Conferences', a top level menu item with a null parent field
$menu->add($menuitem->title, url($menuitem->url));
}
else{
// Parent is a field in database, for example 'Traverse City 2015' would have the parent 'conferences'
$parent = $menuitem->parent;
$menu->item($parent)->add($menuitem->title, url($menuitem->url));
}
}
});
return $next($request);
}
In my view, I call:
{!! $NavBar->asUl() !!}
I would expect this to render as such:
<ul>
<li>Conferences</li>
<ul>
<li><a href="/conferences/traverse-city-2015">Traverse City 2015</li>
</ul>
</ul>
Instead, it is rendering:
<ul>
<li>Conferences</li>
<li>Traverse City 2015</li>
</ul>
Any ideas why the sub-items aren't showing up correctly?

What you are after is nested groups: https://github.com/lavary/laravel-menu#nested-groups
Menu::make('MyNavBar', function($menu){
$menu->group(array('prefix' => 'pages', 'data-info' => 'test'), function($m){
$m->add('About', 'about');
$m->group(array('prefix' => 'about', 'data-role' => 'navigation'), function($a){
$a->add('Who we are', 'who-we-are?');
$a->add('What we do?', 'what-we-do');
$a->add('Our Goals', 'our-goals');
});
});
});
This will then render as:
<ul>
<li data-info="test">
About
<ul>
<li data-info="test" data-role="navigation"></li>
<li data-info="test" data-role="navigation"></li>
<li data-info="test" data-role="navigation"></li>
</ul>
</li>
</ul>

Related

How can I change the language of errors in laravel 5.1 dynamically

I have been using the helper
app()->setLocale(session('lang'));
However, I can get to change the languages of views but the languages of errors still continues reading of
\config\app.php locale => ‘es’
That means that always show the same language.
How can i change it also dynamically?
The problems is that the partial view that prints the errors always print in the same language.
Here is the code that i have.
\resources\views\layout.blade.php
#lang('messages.project')
<ul class="nav navbar-nav navbar-right">
<li>En</li>
<li>Es</li>
</ul>
\app\Http\routes.php
Route::get('lang/{lang}', 'NotesController#changeLang')->where([ 'lang' => 'en|es']);
Route::group(['middleware' => ['web']], function () {
Route::get('notes', 'NotesController#index');
Route::get('notes/create', 'NotesController#create');
});
\app\Http\Controllers\NotesController.php
public function changeLang($lang)
{
session(['lang' => $lang]);
return Redirect::back();
}
\app\Http\Middleware\LangMiddleware.php
public function handle($request, Closure $next)
{
if (!empty(session('lang'))) {
app()->setLocale(session('lang'));
}
return $next($request);
}
\resources\views\partials\errors.blade.php
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
The solution was put the middleware in the file App\Http\Kernel.php in the section of protected $middleware = [] because i just only put in the section "protected $routeMiddleware"
\App\Http\Middleware\VerifyCsrfToken::class,
\App\Http\Middleware\myNewMiddleware::class,
];

simplify this #foreach/if in blade and laravel

I am fairly new to laravel (L5 specifically) and I am making my own version of a todo app rather than following one of the tutorials out there. I've learned quite a bit so far but the way I have this piece of code currently laid out in my blade template makes me think their might be a simpler way of doing this.
My TodosController#index fn is
public function index()
{
$todos = Todo::get();
return view('todos', compact('todos'));
}
App\Todo extends an Eloquent model which makes data handling very easy!
My route is:
Route::bind('todos', function($slug)
{
return App\Todo::whereSlug($slug)->first();
});
So my page simply displays an unorded list of "todos". I want to have two separate lists. One that is for completed todos and one for incomplete. My blade template looks like this so far and looks a bit messy. Also I am looping over the results twice which is where I think I can improve on.
<h3>Incomplete</h3>
<ul>
#foreach ($todos as $todo)
#if ($todo->completed == 'No')
<li>
{{ $todo->title }}
</li>
#endif
#endforeach
</ul>
<h3>Complete</h3>
<ul>
#foreach ($todos as $todo)
#if ($todo->completed == 'Yes')
<li>
{{ $todo->title }}
</li>
#endif
#endforeach
</ul>
Any suggestions to simplify that blade template?
DRY your code out. You could streamline it by moving the actual item mark-up to a partial template since it’s repeated in both the complete and incomplete lists:
<h3>Incomplete</h3>
<ul>
#foreach ($todos as $todo)
#if ($todo->completed == 'No')
#include('partials.items.todo')
#endif
#endforeach
</ul>
<h3>Complete</h3>
<ul>
#foreach ($todos as $todo)
#if ($todo->completed == 'Yes')
#include('partials.items.todo')
#endif
#endforeach
</ul>
And partials.items.todo would look like this:
<li>
{{ $todo->title }}
</li>
I would also re-factor your loops. Instead of looping over the same list twice, you could split them in your controller:
public function index()
{
$todos = Todo::where('user_id', '=', Auth::id())->get();
$complete = $todos->filter(function ($item) {
return $item->completed = 'Yes';
});
$incomplete = $todos->filter(function ($item) {
return $item->completed = 'No';
});
return view('todos', compact('complete', 'incomplete'));
}
Looking at your Todo model, I’d also make your completed column in the database a boolean field instead of a column containing “Yes” or “No” strings. You could then cast that column value to a proper boolean (since MySQL doesn’t have a native boolean field type):
class Todo extends Model
{
protected $casts = [
'completed' => 'boolean',
];
public function isComplete()
{
return $this->completed;
}
}
And then re-factor your controller action to use this instead:
public function index()
{
$todos = Todo::where('user_id', '=', Auth::id())->get();
$complete = $todos->filter(function ($item) {
return $item->isComplete() === true;
});
$incomplete = $todos->filter(function ($item) {
return $item->isComplete() === false;
});
return view('todos', compact('complete', 'incomplete'));
}
You could even move those collection filters to a custom TodoCollection class:
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
class TodoCollection extends EloquentCollection
{
public function complete()
{
return $this->filter(function ($item) {
return $item->isComplete() === true;
});
}
public function incomplete()
{
return $this->filter(function ($item) {
return $item->isComplete() === false;
});
}
}
Sorry for the lengthy reply, but should give you food for though on how to re-factor your code.
Only a bit simplified but...
You can try in your controller:
public function index()
{
$completed = Todo::where('completed','Yes')->get();
$incompleted = Todo::where('completed','No')->get();
return view('todos', compact('completed', 'incompleted'));
}
in Your template:
<h3>Incomplete</h3>
<ul>
#foreach ($incompleted as $todo)
<li>
{{ $todo->title }}
</li>
#endforeach
</ul>
<h3>Complete</h3>
<ul>
#foreach ($completed as $todo)
<li>
{{ $todo->title }}
</li>
#endforeach
</ul>
Another approach using a subtemplate like this:
//_list_todos.blade.php
#foreach ($todos as $todo)
<li>
{{ $todo->title }}
</li>
#endforeach
And your main template like this:
<h3>Incomplete</h3>
<ul>
#include('_list_todos',['todos'=>$incompleted] )
</ul>
<h3>Complete</h3>
<ul>
#include('_list_todos',['todos'=>$completed] )
</ul>
The advantege to use a subtemplate like the last one is you can reuse the code, and simplify your main templates.

Add Class to html Macros Laravel Blade

I am new to laravel blade and I want to have an automatic active navigation bar,
so I have this code
<li>{{ HTML::clever_link("index", 'Home' ) }}</li>
<li><a class="glow" href='breeder'>Breeder's Profile</a></li>
<li><a class="glow" href='gallery'>Gallery</a></li>
<li><a class="glow" href='contact'>Contact Us</a></li>
I used the clever link as I research to do what i want, but it remove the link class "glow" now I want to add the glow class to the li with the clever link, I tried this
<li>{{ HTML::clever_link("index", 'Home', class="glow" ) }}</li>
but it just gives me error. Thanks
You can simply add an argument to your HTML Macro: (Obviously I don't know how your macro looks like so this is just an example)
HTML::macro('clever_link', function($link, $label, $class = ''){
return ''.$label.'';
});
Usage:
{{ HTML::clever_link("index", 'Home', 'glow') }}
Or something a bit more flexible:
HTML::macro('clever_link', function($link, $label, $attributes = array()){
return '<a href="'.$link.'" '.HTML::attributes($attributes).'>'.$label.'</a>';
});
Usage:
{{ HTML::clever_link("index", 'Home', array('class' => 'glow')) }}
(The HTML::attributes() method allows you to convert an array into an HTML attributes string)
// for navigation menu highlight
HTML::macro('clever_link', function($route, $text, $icon) {
if( Request::path() == $route ) {
$active = "class = 'active'";
}
else {
$active = '';
}
return "<a href = '{url($route)}' $active> <i class = '{$icon}'></i>{$text}</a>";
});
</pre>
Usage:
Make your menu as:
{{ HTML::clever_link("/", 'Home', 'icon-home-2') }}
{{ HTML::clever_link("/aboutus", 'About Us', 'icon-dollor') }}
in your menu's link
OR use
https://github.com/pyaesone17/active-state

CodeIgniter: Passing database array data to a template file

In my application I am trying to populate a sidebar menu list with rows from a database table. More specifically, I try to retrieve team name where the coach has the same user_id as the user that is logged in. I want to list the logged in coach's teams listed in a menu.
In my Model, I am using Active Record to get the desired query results:
public function get_team()
{
$this->db->select('teamname')->from('teams')->where('coaches', $this->session->userdata('user_id'));
$this->db->order_by('teamname', 'asc');
$query = $this->db->get();
if($query->num_rows() > 0)
{
foreach($query->result_array() as $row)
{
$data[] = $row;
}
return $data;
}
}
In the Controller, I am not sure how to go about in order to pass the array data to my view. In my index function, I do this:
public function index()
{
if (!$this->tank_auth->is_logged_in()) {
redirect('/auth/login/');
} else
{
$data['title'] = 'Team';
$data['main_content'] = 'team_v';
$data['username'] = $this->tank_auth->get_username();
$data['coach'] = $this->tank_auth->is_admin();
$this->load->vars($data);
$this->load->view('includes/template');
}
}
And in the relevant controller function, I try to send the data directly to the sidebar view, (which is included in the previously loaded template file):
public function get_team()
{
$data = array(
'result' => $this->team_m->get_team());
$this->load->view('includes/sidebar', $data);
}
The view code performs a standard foreach and looks like this:
<li>Teams</li>
<ul>
<?php /* if (empty($result)): */ ?>
<li>Create a team</li>
<?php /* else: */ ?>
<?php foreach ($result as $row): ?>
<li><?php echo $row['teamname'];?></li>
<?php endforeach; ?>
<?php /* endif; */ ?>
</ul>
<li>Messages</li>
<li>My profile</li>
<li>Logout</li>
Sending the $data array to the sidebar this way doesn't work. I have also tried to load all the views in the template manually and passing the data to the views, but to no avail. No matter how I pass it, it gives me the "Invalid argument supplied for foreach()" error, which AFAIK means that no data gets returned in the array.
However, if I do this in the controller function:
public function get_team()
{
$data = array(
'result' => $this->team_m->get_team());
$this->load->view('get_team_v', $data);
}
and make a get_team_v view with the exact same code in the sidebar view above, then the desired result is listed perfectly. I have also performed an affected_rows test and confirmed that the query part is good. What should I do to get the array data to be listed also in the templated sidebar view?
Solved, for anyone browsing.
Passing the arrays in the index method of the controller like below did it for me.
$data['result'] = $this->team_m->get_team_by_coach();
$this->load->vars($data);
And in the sidebar view like so:
<ul id="menu" class="nav nav-pills nav-stacked">
<li><span class="glyphicon glyphicon-list"></span>My Teams</li>
<ul id="submenu" class="nav">
<?php foreach ($result as $row): ?>
<?php echo '<li>' . $row['teamname'] . '</li>';?>
<?php endforeach;
if(count($result) <= 2)
{
echo '<li><a data-toggle="modal" id="create_team" data-backdrop="true" href="#create_team_modal" href="base_url(index.php/team/create_team)"><span class="glyphicon glyphicon-plus"></span>Create a team</a></li>';
}
?>
</ul>
<li><span class="glyphicon glyphicon-envelope"></span>Messages</li>
<li><span class="glyphicon glyphicon-user"></span></i>My Profile</li>
<li><span class="glyphicon glyphicon-log-out"></span>Logout</li>

knpMenuBundle issue

I just tried knpLabs MenuBundle
I am not receiving the flag for the current item, I follower the turorial from https://github.com/KnpLabs/KnpMenuBundle/blob/master/Resources/doc/index.md
Here is my code
use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAware;
class Builder extends ContainerAware
{
public function mainMenu(FactoryInterface $factory, array $options)
{
$menu = $factory->createItem('root');
$menu->addChild('Innehåll', array('route' => 'Content'));
$menu->addChild('Skärmlayouter', array('route' => 'Layout'));
$menu->addChild('Media', array('route' => 'Media'));
$menu->addChild('Områden & fastigheter', array('route' => 'Container'));
$menu->addChild('Användare & behörigheter', array('route' => 'UserManagement'));
return $menu;
}
}
And here is what it produces:
<ul>
<li class="first">
Innehåll
</li>
<li>
Skärmlayouter
</li>
<li>
Media
</li>
<li>
Områden & fastigheter
</li>
<li class="last">
Användare & behörigheter
</li>
</ul>
It claims to include the active link flag (by class "current") automatically, that's why I wanted to try this bundle, so I wouldn't have to meddle around coding that part.
Either I am missing a key point, or this documentation that I am following is missing a key part?
You should use setCurrentUri method. Such as:
$menu = $factory->createItem('root');
$menu->setCurrentUri($this->container->get('request')->getRequestUri());

Categories