-1

I am currently creating a feature on a webpage that aims to create an HTTP request to a server with js when a certain dropdown menu value is changed and the change the webpage based on the request response. To accomplish this, I am using a Laravel @include to include the view that will build the page based on the json response.

The problem lies on this line allNews.innerHTML+=(`@include('partials.news.post',['news'=>`+news.data[i]+`])`)

The problem here is that an error (in the view caused by the argument news.data[i] being null) is immediately thrown by js when the page is loaded, it doesn't even wait for the EventListener to be triggered or for the request to be answered. If I delete this line of code it does not throw any error and works as expected, but if I comment it, the same error happens, which seems odd to say the least. What seems to be the problem here?

I used this stackoverflow question to base my development on.

I know the view is well built and does not throw errors because I use it in other instances.

<script defer>

    let select = document.getElementById("sort-select");
    let allNews = document.getElementById("posts-result");
    
    let xhttp = new XMLHttpRequest();

    console.log(js_query)
    select.addEventListener("change",function(){

        xhttp.open("GET", "/api/load-posts-search?sortBy="+ select.value +"&search=" + js_query, false);
        xhttp.send();
        let news = JSON.parse(xhttp.responseText);
        console.log(news);
        allNews.innerHTML=""
        for(i=0;i<news.total;i++)
        {
            console.log(news.data[i]);
            allNews.innerHTML+=(`@include('partials.news.post',['news'=>`+news.data[i]`])`)
        }  
    })
</script>
fuscati
  • 101
  • 7
  • 1
    You can't mix JS and PHP. `@include('partials.news.post')` is PHP and will be executed on the server while `+ news.data[i]` is JavaScript and will be executed on the client. So this will never work as expected. – shaedrich Jun 03 '21 at 11:07

1 Answers1

0

The XMLHttpRequest will be asynchronous, so I think you need to change this:

select.addEventListener("change",function(){

        xhttp.open("GET", "/api/load-posts-search?sortBy="+ select.value +"&search=" + js_query, false);
        xhttp.send();
        let news = JSON.parse(xhttp.responseText);
        console.log(news);
        allNews.innerHTML=""
        for(i=0;i<news.total;i++)
        {
            console.log(news.data[i]);
            allNews.innerHTML+=(`@include('partials.news.post',['news'=>`+news.data[i]`])`)
        }  
    })

to:

select.addEventListener("change",function(){

        xhttp.open("GET", "/api/load-posts-search?sortBy="+ select.value +"&search=" + js_query, false);
        xhttp.send();

        // wait on the response from the request
        xhttp.onload = function() {
            let news = JSON.parse(xhttp.responseText);
            console.log(news);
            allNews.innerHTML=""
            for(i=0;i<news.total;i++)
            {
                console.log(news.data[i]);
                allNews.innerHTML+=(`@include('partials.news.post',['news'=>`+news.data[i]`])`)
            }
        }
    })

I'm not sure about using the @include within the JavaScript, it's not something I've done to know how well it would work. If the included blade file was static I think it would be fine, I'm just not sure how it would work passing it a dynamic news property that comes from an ajax request, i.e. one part of the @include is server side and one is client side, but I could be wrong and it will work completely fine.

You might need to refactor and return the html of the generated partial from the controller instead of trying to do it within the success stage of the ajax request.

martincarlin87
  • 10,848
  • 24
  • 98
  • 145
  • First of all, thank for your answer. I tried this and it still behaves the same way. By my (not much) understanding, xhttp.responseText already waits for the response to arrive before continuing the program. Anyways, I think you might be right about the use of @include in js, it looks kind of sketchy, I will probably try to go another way to solve this problem. Again, thank for the help. – fuscati Jun 03 '21 at 11:13
  • No problem, sorry I couldn't be more helpful. I didn't know that about xhttp.responseText, I will need to try it. Another way might be to somehow have the partial as an es6 template that you can populate with the news item in the JS, then your response would be the same as it is now, i.e. JSON. – martincarlin87 Jun 03 '21 at 11:19