There is a problem while making the project as SPA with pure js

I have set up the SPA structure like this. It passes between pages without any problems and without reloading the page. But now there is a problem and I can’t understand it. I was writing the url that will go by running the function in javascript in the a tag or buttons on the pages and since this url display function in the backend returns render(‘xxx.html’) as a return, it takes this page as text and loads the new page.

However, the page is reloaded with buttons such as the login form, registration form, profile editing form. When I do this with Response, only the response value appears on the page.

I am leaving my project link. Please help. My graduation project and this is the only problem left. and I have very few days to deliver it.

I hope you can help me? I left the part I had trouble with in the comment below. Thanks in advance.

Welcome @erenakbas57 !

If you’re looking for assistance with an issue here, there are two suggestions I would make regarding your post:

  • The most important one is to identify what parts of the code where you think the problem may lie, and copy/paste those sections of the code into this thread. Don’t expect the people here to go searching through your project trying to find the error.

  • Provide a more clear and detailed description of what the issue is. Identify the urls, models, views, and forms involved.

1 Like

My navigate.js file is like this. I provide the SPA structure with the buttons in the navbar.

As an example:

 <li class="nav-item">
<a class="nav-link {% if request.resolver_match.view_name == 'home' %}active{% endif %}"
onclick="swapApp('/home')">Home</a>
</li>

The swapApp function is running and the page is loading.

// frontend/static/js/app.js


import { isLogin } from './pages/login.js';


export function getCookie(name) {
    const cookieValue = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)');
    return cookieValue ? cookieValue.pop() : '';
}
  
document.addEventListener('DOMContentLoaded', function () {
    updateApp(window.location.pathname);
});

let previousUrl = '';

function updateApp(path) {
    fetch(path)
        .then(response => response.text())
        .then(html => {
            document.body.innerHTML = html;
            if (!html.includes('<div class="big-text">404 ERROR</div>')) {
                pageHandler(path);
            }
        })
        .catch(error => console.log(error));
}

function updateTitle(path) {
    var parts = path.split('/');

    if (parts.length > 0) {
        parts.shift();

        var titleParts = parts.map(function (part) {
            return part.charAt(0).toUpperCase() + part.slice(1);
        });

        var title = titleParts.join(' ');
    }
    else {
        var title = 'TransCat';
    }

    if (!title)
        title = 'TransCat';
    document.title = title;
}

function swapApp(path) {
    //currentPath = window.location.pathname;
    window.history.pushState({}, '', path);
    updateApp(path);
    updateTitle(path);
}



window.updateApp = updateApp;
window.isLogin = isLogin;
window.swapApp = swapApp;
window.onpopstate = function (event) {
    if (window.location.hash == '') {
        updateApp(window.location.pathname);
    }
};

function pageHandler(path) {
    console.log('Sayfa işleyici çalıştırılıyor:', path);
    // Sayfa içeriği yüklenip, özel işlemler yapılacak
    getCookie();
    console.log('Cookie:', getCookie('csrftoken'));
    switch (true) {
        case path.includes('/'):
            isLogin();
            break;
        case path.includes('/login'):
            isLogin();
            break;
        case path.includes('/register'):
            console.log('Anasayfa');
            break;
        case path.includes('/search'):
            console.log('Anasayfa');
            break;
        case path.includes('/profile'):
            console.log('Anasayfa');
            break;
        case path.includes('/home'):
            console.log('Anasayfa');
            break;
        case path.includes('/pong-home'):
            console.log('Anasayfa');
            break;
        case path.includes('/pong-ai'):
            console.log('Anasayfa');
            break;
        case path.includes('/pong-local'):
            console.log('Anasayfa');
            break;
        case path.includes('/pong-local-tournament'):
            console.log('Anasayfa');
            break;
        case path.includes('/rps-home'):
            console.log('Anasayfa');
            break;
        case path.includes('/rps-ai'):
            console.log('Anasayfa');
            break;
        case path.includes('/logout'):
            console.log('Anasayfa');
            break;
        default:
            console.log('Bilinmeyen sayfa');
    }
}

@login_required
@never_cache
def home_view(request):
 print("home func")
 if (request.user.is_authenticated):
 return HttpResponse("home")
 print("is auth not done")
 return HttpResponse(render_to_string("auth/login.html", {"form": form}, request=request))

The view is like this.

My button on my login page is like this
<button onclick="isLogin('login')" type="submit" class="btn btn-login btn-success mt-3">Login</button>

export function isLogin(check) {
 if (!check)
 return;
 var form = document.getElementById('loginForm');
 var formData = new FormData(form);
 var csrftoken = document.cookie.split('; ').find(row => row.startsWith('csrftoken')).split('=')[1];
 fetch('/login', {
 method: 'POST',
 headers: {
 'X-CSRFToken': csrftoken
 },
 body:formData
 })
 .then(response => response.text())
 .then(data => {
 console.log(data);
 if (data == "home")
 swapApp('/home');
 else {
 console.log("error");
 showToast(`${data}`, `text-bg-danger`, `bi-bug-fill`);
 }
 })
 .catch(error => {
 console.error(error);
 });
 }

This function works but the data comes as “home” but it does not go to the swapApp function. Shouldn’t it be sent to swapApp and rendered by adding a request to that url address? I took it from another code and wrote the same but it only gives the “home” text or the error text on a white page.

I edited it and added it as a comment below. Thank you.

1 Like