forked from hotwired/turbo-rails
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add hooks to integrate with Action Text
One major challenge that applications face when integrating with morphing-powered Page Refreshes involves `<trix-editor>` elements rendered by Action Text. The emergent guidance instructs applications to skip morphing by marking the `<trix-editor>` as permanent. This guidance, while correct, does not encapsulate the entire story. In the case of Action Text-rendered `<trix-editor>` elements, applications might invoke `form.rich_text_area` with `data: {turbo_permanent: true}`, expecting for the presence of `trix-editor[data-turbo-permanent]` to be sufficient. However, to achieve the intended behavior, applications must *nest* their `<trix-editor>` elements *within* an element with `[data-turbo-permanent]` (a `<div>`, a `<fieldset>`, etc.). This provides a container for the `trix-editor` to inject its associated `<input>` and `<trix-toolbar>` elements. A `<trix-editor>` element will insert an `<input type="hidden">` element and a `<trix-toolbar>` element when they are absent on connect. Applications can skip a Trix-manage injection by rendering those either (or both) elements ahead of time, then associating them to the `trix-editor` through `[input]` and `[toolbar]` attributes (respectively). Action Text skips the `<input>` injection step by rendering and associating an Action View-rendered `<input type="hidden">` attribute with the appropriate attributes. No matter how the `<input>` connects to the document, it's important for it to keep its `[data-turbo-permanent]` synchronized with the `trix-editor`'s attribute in order to tolerate a morph. Since Page Refreshes, Morphing, and permanence are all Turbo concepts, and Action Text is a Rails framework, `turbo-rails` feels like the most appropriate codebase (out of `rails`, `trix`, `turbo`, and `turbo-rails`) to house the integration.
- Loading branch information
1 parent
1aa7ba9
commit 389a30f
Showing
12 changed files
with
106 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { observeAttributes } from "./util" | ||
|
||
export function observeTurboAttributes({ target }) { | ||
observeAttributes(target, ["data-turbo-permanent"], (value) => { | ||
if (target.inputElement) { | ||
target.inputElement.toggleAttribute("data-turbo-permanent", value ?? false) | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export function observeAttributes(element, attributeFilter, callback) { | ||
const observer = new MutationObserver((mutations) => { | ||
mutations.forEach(({ attributeName, target }) => { | ||
callback(target.getAttribute(attributeName), attributeName) | ||
}) | ||
}) | ||
observer.observe(element, { attributeFilter }) | ||
|
||
attributeFilter.forEach((attributeName) => { | ||
callback(element.getAttribute(attributeName), attributeName) | ||
}) | ||
|
||
return observer | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails | ||
import "@hotwired/turbo-rails" | ||
import "trix" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<% if params[:method] == "morph" %> | ||
<% turbo_refreshes_with method: :morph %> | ||
<% end %> | ||
<%= form_with model: @message do |form| %> | ||
<%= form.rich_text_area :content, data: {turbo_permanent: true} %> | ||
<% end %> | ||
<%= link_to "Page Refresh", {}, data: {turbo_action: "replace"} %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
require "application_system_test_case" | ||
|
||
class ActionTextTest < ApplicationSystemTestCase | ||
test "forwards [data-turbo-permanent] from trix-editor to its input and trix-toolbar" do | ||
visit new_message_path | ||
|
||
assert_trix_editor name: "message[content]", "data-turbo-permanent": true | ||
|
||
find(:rich_text_area).execute_script <<~JS | ||
this.removeAttribute("data-turbo-permanent") | ||
JS | ||
|
||
assert_trix_editor name: "message[content]", "data-turbo-permanent": false | ||
end | ||
|
||
test "keeps a trix-editor[data-turbo-permanent] interactive through a Page Refresh" do | ||
visit new_message_path(method: "morph") | ||
fill_in_rich_text_area with: "Hello" | ||
click_link "Page Refresh" | ||
|
||
assert_trix_editor name: "message[content]", with: /Hello/ | ||
|
||
fill_in_rich_text_area with: "Hello world" | ||
|
||
assert_trix_editor name: "message[content]", with: /Hello world/ | ||
end | ||
|
||
def assert_trix_editor(name: nil, with: nil, **options, &block) | ||
trix_editor = find(:element, "trix-editor", **options, &block) | ||
|
||
assert_field name, type: "hidden", with: with do |input| | ||
assert_equal trix_editor.evaluate_script("this.inputElement"), input | ||
assert_matches_selector input, :element, **options | ||
end | ||
end | ||
end |