AJAX data-request not finding handler

I’m struggling to create an AJAX request. Here is a test page I made.

##
title = "Test AJAX"
layout = "default"
url = "/testajax"

[session]
security = "user"
redirect = "index"
checkToken = 0
==
<?

function onTest() {
    $this->page['result'] = 'tested';
    return Redirect::to($url);
}

function onDoSomething() {
    return 'done';
}

==
{% component 'session' %}

 <a class="btn btn-outline-dark" data-request="onTest" data-request-error="console.log(data)">Test Request</a>



<button type="button" data-request="onDoSomething" class="btn btn-default">
    Do Something
</button>

But every time I click the button or link I get this response:

{"X_OCTOBER_REDIRECT":"https:\/\/neatquiz.test\/testajax"}

I have {% framework extras turbo %} in my header-links partial. I’ve tried removing turbo and extras, but I have no idea what is wrong. I can even change the data-request to a non-existent function, and nothing changes - no error.

Can anyone point me in the right direction?

The <a> tag won’t work since $url is not defined.

What are you trying to achieve exactly?

Thank @apinard for the reply. Are you sure the anchor tag won’t work without a url? It responds the same as the button.

I am trying to get my site dialed in for front end users with register, login, logout, and forgot password. I am using the rainlab user plugin. The example code on the plugin page for logout doesn’t work.

<a data-request="onLogout" data-request-data="redirect: '/good-bye'">Sign out</a>

Oddly enough, this example code doesn’t have a URL either.

I was able to create my own logout route which if fine, but I really want to figure out what is wrong with their example code, so I built this AJAX test.

This is all part of building my navigation.

  • If a user is signed in, they see a dashboard link and a sign out link in the navigation.
  • If a user is not signed in, the see the sign in link

To achieve this, I added the session component directly into my nav-links partial.

Here is the code nav-links.htm:

[backendLink]

[sitePicker]

[session]
security = "all"
checkToken = 0
==
{% set activeNavLink = activeNavLink|default(this.page.id) %}

<li class="nav-item">
    <a class="nav-link {{ activeNavLink == 'blog' ? 'active' }}" href="{{ 'blog/index'|page }}">Blog</a>
</li>
<li class="nav-item">
    <a class="nav-link {{ activeNavLink == 'wiki' ? 'active' }}" href="{{ 'wiki/index'|page }}">Wiki</a>
</li>
<li class="nav-item">
    <a class="nav-link {{ activeNavLink == 'about' ? 'active' }}" href="{{ 'about'|page }}">About</a>
</li>
<li class="nav-item">
    <a class="nav-link {{ activeNavLink == 'contact' ? 'active' }}" href="{{ 'contact'|page }}">Contact</a>
</li>
{% if user %}
<li class="nav-item dropdown">
  <a class="nav-link dropdown-toggle {{ activeNavLink == 'quizzes' or activeNavLink == 'games' or activeNavLink == 'profile' ? 'active' }}" href="#" role="button" data-bs-toggle="dropdown">Dashboard</a>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item {{ activeNavLink == 'quizzes' ? 'active' }}" href="{{ 'quiz/quizzes'|page }}">Quizzes</a></li>
    <li><a class="dropdown-item {{ activeNavLink == 'games' ? 'active' }}" href="{{ 'game/games'|page }}">Games</a></li>
    <li> <a class="dropdown-item {{ activeNavLink == 'profile' ? 'active' }}" href="{{ 'user/profile'|page }}">Profile</a></li>
  </ul>
</li>
{% endif %}
<li class="nav-item">
    {% if not user %}
    <a class="btn btn-outline-light {{ activeNavLink == 'login' ? 'active' }}" href="{{ 'user/login'|page }}">Sign In</a>
    {% else %}
    <a class="btn btn-outline-light" href="/signout">Sign Out</a>
    {% endif %}
</li>
{% if sitePicker.isEnabled %}
    <li class="nav-item dropdown">
        <a class="btn btn-outline-light dropdown-toggle" href="{{ ''|page }}" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            {{ this.site.name|default('Sites') }}
        </a>
        <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
            {% for site in sitePicker.sites %}
                <li><a class="dropdown-item {{ this.site.code == site.code ? 'active' }}" href="{{ site.url }}">{{ site.name }}</a></li>
            {% endfor %}
            {% if backendUrl %}
                <li><hr class="dropdown-divider"></li>
                <li><a class="dropdown-item" href="{{ backendUrl }}">Backend Area</a></li>
            {% endif %}
        </ul>
    </li>
{% elseif backendUrl %}
    <!--li class="nav-item">
        <a class="btn btn-outline-light" href="{{ backendUrl }}" target="backend">Backend Area</a>
    </li-->
{% endif %}

From the doc:

The Session component allows a user to sign out of their session

If you replace:

    <a class="btn btn-outline-light" href="/signout">Sign Out</a>

By:

<a data-request="onLogout" data-request-data="redirect: '/good-bye'">Sign out</a>

it doesn’t work ? Remove the [Session] from the partial and put it in the layout page to see if it helps

@apinard I removed the [Session] component and replaced my custom signout link with <a data-request="onLogout" data-request-data="redirect: '/good-bye'">Sign out</a>

It still doesn’t work.

[backendLink]

[sitePicker]
==
{% set activeNavLink = activeNavLink|default(this.page.id) %}

<li class="nav-item">
    <a class="nav-link {{ activeNavLink == 'blog' ? 'active' }}" href="{{ 'blog/index'|page }}">Blog</a>
</li>
<li class="nav-item">
    <a class="nav-link {{ activeNavLink == 'wiki' ? 'active' }}" href="{{ 'wiki/index'|page }}">Wiki</a>
</li>
<li class="nav-item">
    <a class="nav-link {{ activeNavLink == 'about' ? 'active' }}" href="{{ 'about'|page }}">About</a>
</li>
<li class="nav-item">
    <a class="nav-link {{ activeNavLink == 'contact' ? 'active' }}" href="{{ 'contact'|page }}">Contact</a>
</li>
{% if user %}
<li class="nav-item dropdown">
  <a class="nav-link dropdown-toggle {{ activeNavLink == 'quizzes' or activeNavLink == 'games' or activeNavLink == 'profile' ? 'active' }}" href="#" role="button" data-bs-toggle="dropdown">Dashboard</a>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item {{ activeNavLink == 'quizzes' ? 'active' }}" href="{{ 'quiz/quizzes'|page }}">Quizzes</a></li>
    <li><a class="dropdown-item {{ activeNavLink == 'games' ? 'active' }}" href="{{ 'game/games'|page }}">Games</a></li>
    <li> <a class="dropdown-item {{ activeNavLink == 'profile' ? 'active' }}" href="{{ 'user/profile'|page }}">Profile</a></li>
  </ul>
</li>
{% endif %}
<li class="nav-item">
    {% if not user %}
    <a class="btn btn-outline-light {{ activeNavLink == 'login' ? 'active' }}" href="{{ 'user/login'|page }}">Sign In</a>
    {% else %}
    <a class="btn btn-outline-light" href="/signout">Sign Out</a>
    <a class="btn btn-outline-light" data-request="onLogout" data-request-data="redirect: '/good-bye'">Sign out</a>
    {% endif %}
</li>
{% if sitePicker.isEnabled %}
    <li class="nav-item dropdown">
        <a class="btn btn-outline-light dropdown-toggle" href="{{ ''|page }}" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            {{ this.site.name|default('Sites') }}
        </a>
        <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
            {% for site in sitePicker.sites %}
                <li><a class="dropdown-item {{ this.site.code == site.code ? 'active' }}" href="{{ site.url }}">{{ site.name }}</a></li>
            {% endfor %}
            {% if backendUrl %}
                <li><hr class="dropdown-divider"></li>
                <li><a class="dropdown-item" href="{{ backendUrl }}">Backend Area</a></li>
            {% endif %}
        </ul>
    </li>
{% elseif backendUrl %}
    <!--li class="nav-item">
        <a class="btn btn-outline-light" href="{{ backendUrl }}" target="backend">Backend Area</a>
    </li-->
{% endif %}

but you put the [Session] in your layout page ?

Session is in the page, not the layout. Maybe I should put it in the layout? Wondering what the difference is between putting it in each individual page, the layout, or the nav-links partial in the layout.

The user is there because the signout link is displayed (actually both are displaying right now). My custom link works great, but again, trying to figure out what is going on with AJAX.

My signout link is in a route of a plugin I built.

Route::group(['middleware' => ['web']], function () {

    Route::get('signout', function (Request $request) {
        $user = Auth::getUser();
        Auth::logout();
        // I am not exactly sure what this does
        // $this->guard()->logout();
        // This doesn't seem neccessary - but what does it do beyond auth::logout?
        // $request->session()->invalidate();
        if ($user) {
            Event::fire('rainlab.user.logout', [$user]);
        }
        // $url = post('redirect', Request::fullUrl());
        Flash::success(Lang::get('rainlab.user::lang.session.logout'));
        return redirect('/');
        // return Redirect::to($url);
    })->name('signout');
});

@daft Because you’ve always found the solution in past, I am tagging you here. If you have a chance, can you take a look at this? Thanks.

@baberuth22

There is a lot going on here so its see exactly where your issue is. The best thing to do in these cases is to isolate the issue. Try this and it should work.

##
title = "Test AJAX"
layout = "default"
url = "/testajax"
==
<?
function onDoSomething() {
    return 'done';
}
?>
==
<button type="button" data-request="onDoSomething" class="btn btn-default">
    Do Something
</button>