Skip to content
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

Closed
alexandreruban opened this issue Nov 1, 2021 · 2 comments · Fixed by #445
Closed

Error is logged in console when response has no matching <turbo-frame> #432

alexandreruban opened this issue Nov 1, 2021 · 2 comments · Fixed by #445

Comments

@alexandreruban
Copy link

When loading a frame and the response does not have a matching <turbo-frame> with the same id, an error is logged in the console in FrameController#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:

# app/controllers/quotes_controller.rb

def destroy
  @quote.destroy # Destroy the quote
  redirect_to quotes_path # Redirect to index page
end

In the QuotesController#index page, I render the collection of quotes:

<%# app/views/quotes/index.html.erb %>

<%= render @quotes %>

The markup for a quote is in the app/views/quotes/_quote.html.erb partial:

<%# app/views/quotes/_quote.html.erb %>

<%= turbo_frame_tag quote do %>
  <div class="quote">
    <span>Irrelevant markup</span>
    <%= button_to "Destroy", quote, method: :delete %> 
  </div>
<% end %>

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 and turbo_stream formats, then I would love to document it somewhere:

# app/controllers/quotes_controller.rb

def destroy
  @quote.destroy
  respond_to do |format|
    format.html { redirect_to quotes_path }
    format.turbo_stream
  end
end
@kylekeesling
Copy link

kylekeesling commented Nov 1, 2021

It looks like you may be missing one piece.

In order to remove the quote from the page you need a corresponding destroy.turbo_stream.erb view or you’d need to explicitly write the code to remove the quote from the page in your controller response. Would look something like:

in a view - destroy.turbo_stream.erb

turbo_stream.remove @quote

Or in your controller:

respond_to do |format|
  format.html { redirect_to quotes_path } 
  format.turbo_stream { turbo_stream.remove @quote } 
end

@tleish
Copy link
Contributor

tleish commented Nov 12, 2021

@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?

seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 14, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 14, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 14, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 14, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 15, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 15, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 18, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 18, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 18, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 18, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 18, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Nov 21, 2021
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Aug 1, 2022
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
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Aug 1, 2022
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
dhh added a commit that referenced this issue Aug 3, 2022
* 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>
@dhh dhh closed this as completed in #445 Aug 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants