Laravel-adminlte: Menu item (sidebar) is not active.

Created on 31 May 2020  路  19Comments  路  Source: jeroennoten/Laravel-AdminLTE

Menu item (sidebar) is not active, on localhost it is active, but on the web server (heroku for testing) no, the active class is not added.
Laravel 7.x, AdminLTE 3.2

scheduled

All 19 comments

@multiarts Which Laravel version and which project version do you use?

Laravel 7.x, AdminLTE 3.2

@multiarts is the issue actual?

@multiarts is the issue actual?

Yes.

Can you provide more information:
1) Do you see any error in the Browser's Console or Network tabs (using the web developers tools)
2) When you click a menu link (for example Todos in your image), what is the URL you see in the browser on local development and what is the one you see in the Heroku web server?
3) Are you using the same adminlte.php config file on local development and Heroku web server?
4) What version of this package you are using now?

I think it鈥榮 an issue on your local env, for example, the htaccess rules are not correct. I don鈥榯 can find any error on any browsers and webservers.

I think it鈥榮 an issue on your local env, for example, the htaccess rules are not correct. I don鈥榯 can find any error on any browsers and webservers.

he told that on localhost it is active on server it is not.

The same for me, I had laravel 6.x now upgraded to 7.x (v7.14.1) and jeroennoten/laravel-adminlte v3.3.1 (the same problem existed in older version, for example v3.2.0).

I have 3 setups - local, stage and prod. Active menu works as expected on local and stage, but active class is never added on prod. Only prod is https, local and stage is http - my guess is it is related but I am not sure.

Hi @ivarsju , can you give a try to dev-master version of the package?

1) Edit the composer.json file of your Laravel project and use "jeroennoten/laravel-adminlte": "dev-master" on the require section instead of the current one.

2) Run the composer update command.

Also, can you give an example of how are you defining the menu item configuration that is not active on production when you click on it.

I was not able to just update the composer, I had to update views and config too. But still not working, active class is never added.
I have one small project, good for testing. Menu config is just:
return [
[
'text' => 'Video',
'url' => 'video',
'icon' => 'nav-icon fas fa-video'
],
];

And in AppServiceProvider:
public function boot(Dispatcher $events, Repository $config)
{
if ($config->get('app.env') === 'prod') {
\URL::forceScheme('https');
}

    $events->listen(BuildingMenu::class, function (BuildingMenu $event) use ($config) {
        call_user_func_array([$event->menu, 'add'], $config->get('menu', []));
    });
}

In http://stage.my.site.com/video the menu item is active, in https://my.site.com/video it is not.
The same issue in another project with similar setup (but more menu items).

Thanks for your feedback @ivarsju , I manage to reproduce the issue, comes mainly for the usage of URL::forceScheme('https');. I'm preparing a fix for this issue, but I will like that you test it before uploading. So can you make the next change on the dev-master version of this package:

On your local project, edit the file vendor/jeroennoten/laravel-adminlte/src/Menu/ActiveChecker.php and replace the method checkPattern() by the new version:

Old Version

/**
 * Checks if an url pattern matches the requested url.
 *
 * @param string $pattern
 * @return bool
 */
 protected function checkPattern($pattern)
{
    // First, check if the pattern is a regular expression.

    if (Str::startsWith($pattern, 'regex:')) {
        $regex = Str::substr($pattern, 6);

        return (bool) preg_match($regex, $this->request->path());
    }

    // If pattern is not a regex, check if the requested url matches the
    // absolute path to the given pattern.

    return Str::is($this->url->to($pattern), $this->request->url());
}

New Version

/**
 * Checks if an url pattern matches the requested url.
 *
 * @param string $pattern
 * @return bool
 */
protected function checkPattern($pattern)
{
    // First, check if the pattern is a regular expression.

    if (Str::startsWith($pattern, 'regex:')) {
        $regex = Str::substr($pattern, 6);

        return (bool) preg_match($regex, $this->request->path());
    }

    // If pattern is not a regex, check if the requested url matches the
    // absolute path to the given pattern.

    $pattern = preg_replace('(^https?://)', "", $this->url->to($pattern));
    $request = preg_replace('(^https?://)', "", $this->request->url());
    return Str::is($pattern, $request);
}

@Shidersz What do you think about this shorter version? :)
https://laravel.com/api/7.x/Illuminate/Http/Request.html#method_is

/**
 * Checks if an url pattern matches the requested url.
 *
 * @param string $pattern
 * @return bool
 */
protected function checkPattern($pattern)
{
    // First, check if the pattern is a regular expression.

    if (Str::startsWith($pattern, 'regex:')) {
        $regex = Str::substr($pattern, 6);

        return (bool) preg_match($regex, $this->request->path());
    }

    // If pattern is not a regex, check if the requested url matches the
    // absolute path to the given pattern.

    return $this->request->is($pattern);
}

@lacodimizer That fails on some of the test we have. However, we can try to get a short version once they can confirm the issue is solved this way. The main problem I have observed (on my local environment) is that when you use URL::forceScheme('https') the method $this->url->to($pattern) always use the https scheme to generate the url, while $this->request->url() sometimes uses the http scheme and that causes the issue.

@Shidersz You are right with the tests...

@lacodimizer In case you need a test to reproduce the issue with the current implementation, you can use next changes:

1) Change next methods of tests/TestCase.php like this:

protected function makeActiveChecker($uri = 'http://example.com', $scheme = null)
{
    return new ActiveChecker(
        $this->makeRequest($uri),
        $this->makeUrlGenerator($uri, $scheme)
    );
}

protected function makeUrlGenerator($uri = 'http://example.com', $scheme = null)
{
    $UrlGenerator = new UrlGenerator(
        $this->getRouteCollection(),
        $this->makeRequest($uri)
    );

    if ($scheme) {
        $UrlGenerator->forceScheme($scheme);
    }

    return $UrlGenerator;
}

2) Add the next new test to tests/Menu/ActiveCheckerTest.php file:

public function testWithForcedScheme()
{
    $checker = $this->makeActiveChecker('http://example.com/about', 'https');

    $isActive = $checker->isActive(['url' => 'about']);
    $this->assertTrue($isActive);

    $isActive = $checker->isActive(['url' => 'http://example.com/about']);
    $this->assertTrue($isActive);

    $isActive = $checker->isActive(['url' => 'https://example.com/about']);
    $this->assertTrue($isActive);
}

Also, we don't even need to inject Request into the ActiveChecker constructor, we can access the request using the UrlGenerator instance as:

$this->url->getRequest()

Thanks for your feedback @ivarsju , I manage to reproduce the issue, comes mainly for the usage of URL::forceScheme('https');. I'm preparing a fix for this issue, but I will like that you test it before uploading. So can you make the next change on the dev-master version of this package:

On your local project, edit the file vendor/jeroennoten/laravel-adminlte/src/Menu/ActiveChecker.php and replace the method checkPattern() by the new version:

Old Version

/**
 * Checks if an url pattern matches the requested url.
 *
 * @param string $pattern
 * @return bool
 */
 protected function checkPattern($pattern)
{
    // First, check if the pattern is a regular expression.

    if (Str::startsWith($pattern, 'regex:')) {
        $regex = Str::substr($pattern, 6);

        return (bool) preg_match($regex, $this->request->path());
    }

    // If pattern is not a regex, check if the requested url matches the
    // absolute path to the given pattern.

    return Str::is($this->url->to($pattern), $this->request->url());
}

New Version

/**
 * Checks if an url pattern matches the requested url.
 *
 * @param string $pattern
 * @return bool
 */
protected function checkPattern($pattern)
{
    // First, check if the pattern is a regular expression.

    if (Str::startsWith($pattern, 'regex:')) {
        $regex = Str::substr($pattern, 6);

        return (bool) preg_match($regex, $this->request->path());
    }

    // If pattern is not a regex, check if the requested url matches the
    // absolute path to the given pattern.

    $pattern = preg_replace('(^https?://)', "", $this->url->to($pattern));
    $request = preg_replace('(^https?://)', "", $this->request->url());
    return Str::is($pattern, $request);
}

Yes, it has fixed active menu issue

Nice, thanks for your help @ivarsju , this issue should be solved on the next releases.

Than you!

@ivarsju @Shidersz the release v3.4.0 is out now.

I'm sorry I didn't answer, I was sick.
Now with the update from 3.3 to 3.4 the failure has been resolved.
Thank you very much.

Was this page helpful?
0 / 5 - 0 ratings