Skip to content

Instantly share code, notes, and snippets.

@antonkomarev
Last active April 8, 2017 01:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antonkomarev/cc65425c83c60633302d4c3579f48718 to your computer and use it in GitHub Desktop.
Save antonkomarev/cc65425c83c60633302d4c3579f48718 to your computer and use it in GitHub Desktop.
Laravel CSS Active Class View Composer
<?php
namespace App\ViewComposers;
use Illuminate\View\View;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
class CssActiveClassComposer
{
/**
* @var \Illuminate\Http\Request
*/
private $request;
/**
* @var string
*/
private $activeClass = 'active';
/**
* @var string
*/
private $template = ' class="{classes}"';
/**
* Create a new profile composer.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function compose(View $view)
{
$view->with('link', $this);
}
/**
* Determine if a link should be marked as active based on the provided route(s)
* and return the class attribute. Optionally, you can override the template
* to only return the class list or individual active state for the link.
*
* @param $routes string|array A single or list of routes to match against.
* @param string $classes string A string of classes to be returned with the state.
* @param null $activeClass string A string to override the $this->activeClass.
* @param null $template string A string to override $this->template
* @return string
*/
public function activeRoute($routes, $classes = '', $activeClass = null, $template = null)
{
return $this->buildClassList(
$routes, $this->request->route()->getName(), $classes, $activeClass, $template
);
}
/**
* Determine if a link should be marked as active based on the provided path(s)
* and return the class attribute. Optionally, you can override the template
* to only return the class list or individual active state for the link.
*
* @param $paths string|array A single or list of paths to match against.
* @param string $classes string A string of classes to be returned with the state.
* @param null $activeClass string A string to override the $this->activeClass.
* @param null $template string A string to override $this->template
* @return string
*/
public function activePath($paths, $classes = '', $activeClass = null, $template = null)
{
return $this->buildClassList(
$paths, $this->request->decodedPath(), $classes, $activeClass, $template
);
}
/**
* Determine if a link should be marked as active based on provided patterns(s)
* and return the class attribute. Optionally, you can override the template
* to only return the class list or individual active state for the link.
*
* @param $patterns string|array A single or list of patterns to match against.
* @param $value string The string to match the patterns against.
* @param string $classes string A string of classes to be returned with the state.
* @param null $activeClass string A string to override the $this->activeClass.
* @param null $template string A string to override $this->template
* @return string
*/
private function buildClassList($patterns, $value, $classes, $activeClass, $template)
{
if ($this->matches($patterns, $value)) {
$classes = trim(implode(' ', [$classes, $activeClass ?: $this->activeClass]));
}
return str_replace('{classes}', $classes, $template ?: $this->template);
}
/**
* Determine if any of the provided patterns match the given value.
*
* @param $patterns string|array A single or list of patterns to match against.
* @param $value string The string to match the patterns against.
* @return bool
*/
private function matches($patterns, $value)
{
foreach ((array) $patterns as $pattern) {
if (Str::is($pattern, $value)) {
return true;
}
}
return false;
}
/**
* Set the active class to be used on future calls.
*
* @param $activeClass
* @return $this
*/
public function class($activeClass)
{
$this->activeClass = $activeClass;
return $this;
}
/**
* Set the template to be used on future calls.
*
* @param $activeTemplate
* @return $this
*/
public function template($activeTemplate)
{
$this->template = $activeTemplate;
return $this;
}
}
{{-- Single path wildcard, matches. Returns: class="active" --}}
{{ $link->activePath('setup/*') }}<br>
{{-- Single path, matches. Includes other classes. Returns: class="link-item active" --}}
{{ $link->activePath('setup/requirements', 'link-item') }}<br>
{{-- Multiple paths, matches. Overrides active class. Returns: class="link-item active-item" --}}
{{ $link->activePath(['setup/*', 'mismatch/path'], 'link-item', 'active-item') }}<br>
{{--Single route wildcard, matches. Overrides template. Returns: link-item active--}}
{{ $link->activeRoute('*.requirements', 'mismatch.route', 'link-item', null, '{classes}') }}<br>
{{-- Single route, matches. Sets new default active class and template. Returns: data-class="link-item activated" --}}
{{ $link->class('activated')->template(' data-class="{classes}"')->activeRoute('setup.*', 'link-item') }}<br>
{{-- Multiple routes, matches. Uses above template and class. Returns: data-class="link-item active-item" --}}
{{ $link->activeRoute(['setup.requirements', 'mismatch.route'], 'link-item', 'active-item') }}<br>
{{-- Multiple routes, matches. Uses above template and class. Returns: data-class="link-item active-item" --}}
{{ $link->activeRoute(['setup.requirements', 'mismatch.route'], 'link-item', 'active-item') }}<br>
{{-- Multiple routes, doesn't match. Returns: ng-class="link-item" --}}
{{ $link->activePath(['requirements', 'mismatch.route'], 'link-item', 'active-item', ' ng-class="{classes}"') }}<br>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment