-
Notifications
You must be signed in to change notification settings - Fork 435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error is logged in console when response has no matching <turbo-frame>
#432
Comments
It looks like you may be missing one piece. In order to remove the quote from the page you need a corresponding in a view - destroy.turbo_stream.erb
Or in your controller:
|
@alexandreruban - You might be interested in these discussions: see:
I'm curious if any of these solutions might solve what you are trying to accomplish (e.g. replace the entire page with the response if the response from the server does not include a matching turbo-frame#id), or are you trying to accomplish something different? |
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `url:` key, and the `response:` key containing: * `redirected: boolean` * `responseHTML: string` * `statusCode: number` Event listeners for `turbo:frame-missing` can forward the `detail` directly to a `Turbo.visit` call: ```js addEventListener("turbo:frame-missing", ({ target, detail: { url, response } }) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(target)) { const visitOptions = response Turbo.visit(url, visitOptions) } }) [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `url:` key, and the `response:` key containing: * `redirected: boolean` * `responseHTML: string` * `statusCode: number` Event listeners for `turbo:frame-missing` can forward the `detail` directly to a `Turbo.visit` call: ```js addEventListener("turbo:frame-missing", ({ target, detail: { url, response } }) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(target)) { const visitOptions = response Turbo.visit(url, visitOptions) } }) ``` [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `url:` key, and the `response:` key containing: * `redirected: boolean` * `responseHTML: string` * `statusCode: number` Event listeners for `turbo:frame-missing` can forward the `detail` directly to a `Turbo.visit` call: ```js addEventListener("turbo:frame-missing", ({ target, detail: { url, response } }) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(target)) { const visitOptions = response Turbo.visit(url, visitOptions) } }) ``` [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `url:` key, and the `response:` key containing: * `redirected: boolean` * `responseHTML: string` * `statusCode: number` Event listeners for `turbo:frame-missing` can forward the `detail` directly to a `Turbo.visit` call: ```js addEventListener("turbo:frame-missing", ({ target, detail: { url, response } }) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(target)) { Turbo.visit(url, { response }) } }) ``` [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. To transform the `FetchResponse` into a `Visit`, clients can extract: * `redirected: boolean` * `statusCode: number` * `responseHTML: Promise<string>` Event listeners for `turbo:frame-missing` can forward the `detail` directly to a `Turbo.visit` call: ```js addEventListener("turbo:frame-missing", async ({ target, detail: { fetchResponse } }) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(target)) { const { location, redirected, statusCode, responseHTML } = fetchResponse const response = { redirected, statusCode, responseHTML: await responseHTML } Turbo.visit(location, { response }) } }) ``` [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. To transform the `FetchResponse` into a `Visit`, clients can extract: * `redirected: boolean` * `statusCode: number` * `responseHTML: Promise<string>` Event listeners for `turbo:frame-missing` can forward the `detail` directly to a `Turbo.visit` call: ```js addEventListener("turbo:frame-missing", async ({ target, detail: { fetchResponse } }) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(target)) { const { location, redirected, statusCode, responseHTML } = fetchResponse const response = { redirected, statusCode, responseHTML: await responseHTML } Turbo.visit(location, { response }) } }) ``` [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. The `event.detail.visit` key provides handlers with a way to transform the `fetchResponse` into a `Turbo.visit()` call without any knowledge of the internal structure or logic necessary to do so. Event listeners for `turbo:frame-missing` can invoke the `event.detail.visit` directly to invoke `Turbo.visit()` behind the scenes. The yielded `visit()` function accepts `Partial<VisitOptions>` as an optional argument: ```js addEventListener("turbo:frame-missing", async ({ target, detail: { fetchResponse, visit } }) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(target)) { visit({ action: "replace" }) } }) ``` [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. The `event.detail.visit` key provides handlers with a way to transform the `fetchResponse` into a `Turbo.visit()` call without any knowledge of the internal structure or logic necessary to do so. Event listeners for `turbo:frame-missing` can invoke the `event.detail.visit` directly to invoke `Turbo.visit()` behind the scenes. The yielded `visit()` function accepts `Partial<VisitOptions>` as an optional argument: ```js addEventListener("turbo:frame-missing", (event) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(event.target)) { const { detail: { fetchResponse, visit } } = event event.preventDefault() visit() } }) ``` The event listener is also a good opportunity to change the `<turbo-frame>` element itself to prevent future missing responses. For example, if the reason the frame is missing is access (an expired session, for example), the call to `visit()` can be made with `{ action: "replace" }` to remove the current page from Turbo's page history. Similarly, if the reason for the missing frame is particular to the page referenced by the element's `[src]` attribute, this is an opportunity to change that attribute (calling `event.target.removeAttribute("src")`, for example) before navigating away so that re-visiting the page by navigating backward in the Browser's history doesn't automatically load the frame and re-trigger another `turbo:frame-missing` event. [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31 cancelable event
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. The `event.detail.visit` key provides handlers with a way to transform the `fetchResponse` into a `Turbo.visit()` call without any knowledge of the internal structure or logic necessary to do so. Event listeners for `turbo:frame-missing` can invoke the `event.detail.visit` directly to invoke `Turbo.visit()` behind the scenes. The yielded `visit()` function accepts `Partial<VisitOptions>` as an optional argument: ```js addEventListener("turbo:frame-missing", (event) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(event.target)) { const { detail: { fetchResponse, visit } } = event event.preventDefault() visit() } }) ``` The event listener is also a good opportunity to change the `<turbo-frame>` element itself to prevent future missing responses. For example, if the reason the frame is missing is access (an expired session, for example), the call to `visit()` can be made with `{ action: "replace" }` to remove the current page from Turbo's page history. Similarly, if the reason for the missing frame is particular to the page referenced by the element's `[src]` attribute, this is an opportunity to change that attribute (calling `event.target.removeAttribute("src")`, for example) before navigating away so that re-visiting the page by navigating backward in the Browser's history doesn't automatically load the frame and re-trigger another `turbo:frame-missing` event. [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. The `event.detail.visit` key provides handlers with a way to transform the `fetchResponse` into a `Turbo.visit()` call without any knowledge of the internal structure or logic necessary to do so. Event listeners for `turbo:frame-missing` can invoke the `event.detail.visit` directly to invoke `Turbo.visit()` behind the scenes. The yielded `visit()` function accepts `Partial<VisitOptions>` as an optional argument: ```js addEventListener("turbo:frame-missing", (event) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(event.target)) { const { detail: { fetchResponse, visit } } = event event.preventDefault() visit() } }) ``` The event listener is also a good opportunity to change the `<turbo-frame>` element itself to prevent future missing responses. For example, if the reason the frame is missing is access (an expired session, for example), the call to `visit()` can be made with `{ action: "replace" }` to remove the current page from Turbo's page history. Similarly, if the reason for the missing frame is particular to the page referenced by the element's `[src]` attribute, this is an opportunity to change that attribute (calling `event.target.removeAttribute("src")`, for example) before navigating away so that re-visiting the page by navigating backward in the Browser's history doesn't automatically load the frame and re-trigger another `turbo:frame-missing` event. [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. The `event.detail.visit` key provides handlers with a way to transform the `fetchResponse` into a `Turbo.visit()` call without any knowledge of the internal structure or logic necessary to do so. Event listeners for `turbo:frame-missing` can invoke the `event.detail.visit` directly to invoke `Turbo.visit()` behind the scenes. The yielded `visit()` function accepts `Partial<VisitOptions>` as an optional argument: ```js addEventListener("turbo:frame-missing", (event) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(event.target)) { const { detail: { fetchResponse, visit } } = event event.preventDefault() visit() } }) ``` The event listener is also a good opportunity to change the `<turbo-frame>` element itself to prevent future missing responses. For example, if the reason the frame is missing is access (an expired session, for example), the call to `visit()` can be made with `{ action: "replace" }` to remove the current page from Turbo's page history. Similarly, if the reason for the missing frame is particular to the page referenced by the element's `[src]` attribute, this is an opportunity to change that attribute (calling `event.target.removeAttribute("src")`, for example) before navigating away so that re-visiting the page by navigating backward in the Browser's history doesn't automatically load the frame and re-trigger another `turbo:frame-missing` event. [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. The `event.detail.visit` key provides handlers with a way to transform the `fetchResponse` into a `Turbo.visit()` call without any knowledge of the internal structure or logic necessary to do so. Event listeners for `turbo:frame-missing` can invoke the `event.detail.visit` directly to invoke `Turbo.visit()` behind the scenes. The yielded `visit()` function accepts `Partial<VisitOptions>` as an optional argument: ```js addEventListener("turbo:frame-missing", (event) => { // the details of `shouldRedirectOnMissingFrame(element: FrameElement)` // are up to the application to decide if (shouldRedirectOnMissingFrame(event.target)) { const { detail: { fetchResponse, visit } } = event event.preventDefault() visit() } }) ``` The event listener is also a good opportunity to change the `<turbo-frame>` element itself to prevent future missing responses. For example, if the reason the frame is missing is access (an expired session, for example), the call to `visit()` can be made with `{ action: "replace" }` to remove the current page from Turbo's page history. Similarly, if the reason for the missing frame is particular to the page referenced by the element's `[src]` attribute, this is an opportunity to change that attribute (calling `event.target.removeAttribute("src")`, for example) before navigating away so that re-visiting the page by navigating backward in the Browser's history doesn't automatically load the frame and re-trigger another `turbo:frame-missing` event. [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. Unless it's canceled (by calling `event.preventDefault()`), Turbo Drive will visit the frame's URL as a full-page navigation. The event listener is also a good opportunity to change the `<turbo-frame>` element itself to prevent future missing responses. For example, if the reason the frame is missing is access (an expired session, for example), the call to `visit()` can be made with `{ action: "replace" }` to remove the current page from Turbo's page history. [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
Closes [hotwired#432][] Follow-up to [hotwired#94][] Follow-up to [hotwired#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. Unless it's canceled (by calling `event.preventDefault()`), Turbo Drive will visit the frame's URL as a full-page navigation. The event listener is also a good opportunity to change the `<turbo-frame>` element itself to prevent future missing responses. For example, if the reason the frame is missing is access (an expired session, for example), the call to `visit()` can be made with `{ action: "replace" }` to remove the current page from Turbo's page history. [contract]: hotwired#94 (comment) [hotwired#432]: hotwired#432 [hotwired#94]: hotwired#94 [hotwired#31]: hotwired#31
* Introduce `turbo:frame-missing` event Closes [#432][] Follow-up to [#94][] Follow-up to [#31][] When a response from _within_ a frame is missing a matching frame, fire the `turbo:frame-missing` event. There is an existing [contract][] that dictates a request from within a frame stays within a frame. However, if an application is interested in reacting to a response without a frame, dispatch a `turbo:frame-missing` event. The event's `target` is the `FrameElement`, and the `detail` contains the `fetchResponse:` key. Unless it's canceled (by calling `event.preventDefault()`), Turbo Drive will visit the frame's URL as a full-page navigation. The event listener is also a good opportunity to change the `<turbo-frame>` element itself to prevent future missing responses. For example, if the reason the frame is missing is access (an expired session, for example), the call to `visit()` can be made with `{ action: "replace" }` to remove the current page from Turbo's page history. [contract]: #94 (comment) [#432]: #432 [#94]: #94 [#31]: #31 * re-run CI * issue a new request for the full page of content * Add console warning if a full-page visit is triggered as a result of missing matching frame Co-authored-by: David Heinemeier Hansson <david@hey.com>
When loading a frame and the response does not have a matching
<turbo-frame>
with the sameid
, an error is logged in the console inFrameController#extractForeignFrameElement
. It was discussed in this issue #31.However, I think this causes an issue in most Rails apps.
Steps to reproduce
Let's imagine a simple CRUD controller on a
quote
resource. The destroy action in the controller would look like this:In the
QuotesController#index
page, I render the collection of quotes:The markup for a quote is in the
app/views/quotes/_quote.html.erb
partial:Actual behavior
When clicking on the "Destroy" button for a quote, the quote is removed, but I get an error in console:
Response has no matching <turbo-frame id="quote_1"> element
. The empty frame remains in the DOM.Expected behavior
The
<turbo-frame id="quote_1">
is removed from the DOM completely. No error is logged in the console.What do you think?
If you agree with the expected behavior, I would love to make a PR.
If what is expected when destroying a resource is to always distinguish the
html
andturbo_stream
formats, then I would love to document it somewhere:The text was updated successfully, but these errors were encountered: