hotwired / turbo

The speed of a single-page web application without having to write any JavaScript
https://turbo.hotwired.dev
MIT License
6.54k stars 415 forks source link

Indefinite Progress Bar on Turbo.visit with turbo-stream content #1271

Open userLegacy opened 1 month ago

userLegacy commented 1 month ago

The Progress bar does go indefinitely unless it is hidden manually, will there be a -fix- or am i missing something?

Edit 1: even the hide() function isnt working! There is no problem with the progress bar on 7.x(no morph!?) with the same code and without using the turbo:morph event

import { Application, Controller } from 'https://cdn.jsdelivr.net/npm/@hotwired/stimulus@3.2.2/+esm'
import 'https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.0/+esm'

window.Stimulus = Application.start()

Stimulus.register("list", class extends Controller {
    connect() {
        Turbo.visit("/dev/app/public/api/get/list")
        document.addEventListener("turbo:morph", (e) =>{
            Turbo.navigator.delegate.adapter.progressBar.hide()
        })
    }

})
$app->get('/api/get/list', function (Request $request, Response $response, $args) {
    $list = R::findAll('mock_data', "LIMIT 25");
    ob_start();
    include_once "resources/table-list.php";
    $content = ob_get_clean();
    $response->getBody()->write($content);    
    return $response->withHeader('Content-Type', 'text/vnd.turbo-stream.html');
});
tpaulshippy commented 1 month ago

I could be wrong because your code samples are incomplete, but it appears that you are attempting to mix Turbo Drive with Turbo Streams.

Turbo.visit is meant for Turbo Drive. It is intended for navigating to new pages smoothly.

Returning a text/vnd.turbo-stream.html response is meant to be used as part of Turbo Streams. It allows you to have your back end tell your front end to append, prepend, replace, update, remove, insert before, insert after, morph, or refresh a DOM element by ID. These streams can be sent via websockets, or (as it appears you intend) via javascript AJAX calls. If you want to initiate a turbo stream via javascript, you want to do something like this:

const response = await fetch('/api/get/list', {
            method: 'get', 
            headers: {
                'Accept': 'text/vnd.turbo-stream.html',
            }
        })
        const html = await response.text();
        Turbo.renderStreamMessage(html)

As discussed here, this is made easier by using the @rails/request.js library.

Generally, this should only be necessary if you are wiring up client-side DOM events other than link clicks and form submits to something on your server. For example, loading dependent selects as discussed here.

It might help if you can share more about your use case. I suspect that the progress bar is not going away because your server isn't responding with what is expected from the Turbo.visit call.

tpaulshippy commented 1 month ago

Indeed, if you look at https://github.com/hotwired/turbo/blob/c339144924e5632d4ef5e3a7b941b3db17d9efa3/src/observers/stream_observer.js#L47 you will see that the system is designed to intercept turbo stream responses and prevent the default behavior in that case. The default behavior is to succeed or fail the request, resulting in the progress bar being removed. But https://github.com/hotwired/turbo/blob/c339144924e5632d4ef5e3a7b941b3db17d9efa3/src/http/fetch_request.js#L155 means that the code never gets to that success/failure point.

userLegacy commented 4 weeks ago

Thanks for your response, yes I know using the fetch api would be useful, but i was experimenting with some infinite scroll and came accross using the Turbo.visit with turbo-stream header and it was very useful in simple cases where the response would just be a turbo-stream.

<turbo-stream action="append" target="list">
    <template>
        <?php $sno = $offset + 1;
        foreach ($list as $record) : ?>
            <tr>
                <td><?= $sno ?></td>
                <td><?= "{$record->first_name} {$record->last_name}" ?></td>
                <td><?= $record->member_id ?></td>
                <td><?= $record->email ?></td>
                <td><?= $record->gender ?></td>
                <td><img src="<?= $record->photo ?>" alt=""></td>
            </tr>
        <?php $sno++;
        endforeach; ?>
    </template>
</turbo-stream>

The thing is there is no issue such like this in the v7.3 and i checked the code you referred to the in the v7.3 and its just the same. Also checked it with some delay <?php sleep(3) ?> in the backend, and the progress bar works in v7.3 and not like its completely off.

Unless I am sending some other data that i would need to work --(like disabling any more request if a particular total is reached)-- with in js, i would happily just add the single line Turbo.visit and forget about anything else.

tpaulshippy commented 4 weeks ago

Ah so you were trying to use Turbo.visit as an easy way to initiate a GET that returns a turbo stream? Interesting. Looks like that may only work by coincidence in some versions - probably not designed to work that way. Right?

userLegacy commented 4 weeks ago

Okay i was following the trail and in the v8 there is some missing code that is present in the v7.x.

8.x https://github.com/hotwired/turbo/blob/c339144924e5632d4ef5e3a7b941b3db17d9efa3/src/http/fetch_request.js#L144 https://github.com/hotwired/turbo/blob/c339144924e5632d4ef5e3a7b941b3db17d9efa3/src/core/drive/visit.js#L340 https://github.com/hotwired/turbo/blob/c339144924e5632d4ef5e3a7b941b3db17d9efa3/src/core/drive/visit.js#L202 https://github.com/hotwired/turbo/blob/c339144924e5632d4ef5e3a7b941b3db17d9efa3/src/core/native/browser_adapter.js#L57

7.x https://github.com/hotwired/turbo/blob/4593d06ce58d17af5b17495ad8524eaa9bc2f5d2/src/http/fetch_request.ts#L120 ... https://github.com/hotwired/turbo/blob/4593d06ce58d17af5b17495ad8524eaa9bc2f5d2/src/core/drive/visit.ts#L251 https://github.com/hotwired/turbo/blob/4593d06ce58d17af5b17495ad8524eaa9bc2f5d2/src/core/native/browser_adapter.ts#L68

In v8 there is some logic in visitCompleted and not in visitRequestFinished and its the opposite in 7.x. https://github.com/hotwired/turbo/blob/4593d06ce58d17af5b17495ad8524eaa9bc2f5d2/src/core/native/browser_adapter.ts#L71 https://github.com/hotwired/turbo/blob/c339144924e5632d4ef5e3a7b941b3db17d9efa3/src/core/native/browser_adapter.js#L59

This intended?!?

-- And the progress bar is hidden if i place the code in the function, but unsure how it will affect others!