CableReady provides a simple interface for triggering client-side DOM operations from the server via ActionCable.
Please read the official ActionCable docs to learn more about ActionCable before proceeding.
yarn install cable_ready
gem "cable_ready"
import CableReady from 'cable_ready';
App.cable.subscriptions.create({ channel: "UserChannel" }, {
received: function (data) {
if (data.cableReady) {
CableReady.perform(data.operations);
}
}
});
class User < ApplicationRecord
include CableReady::Broadcaster
def broadcast_name_change
cable_ready["UserChannel"].text_content selector: "#user-name", text: name
cable_ready.broadcast
end
end
- dispatchEvent
- morph
- innerHTML
- outerHTML
- insertAdjacentHTML
- insertAdjacentText
- remove
- setValue
- setAttribute
- removeAttribute
- addCssClass
- removeCssClass
- setDatasetProperty
The
selector
options use document.querySelector() to find an element by default. XPath expressions can also be used if thexpath
option is set totrue
. As with CSS selectors, the XPath expression must resolve to a single element and not a collection.
It's possible to invoke multiple DOM operations with a single ActionCable broadcast.
All DOM mutations have corresponding
before/after
events triggered ondocument
. These events exposeevent.detail
set to the arguments from the server.
class User < ApplicationRecord
include CableReady::Broadcaster
def broadcast_name_change
cable_ready["UserChannel"].text_content selector: "/html/body/div[1]/form/input[1]", text: name, xpath: true
cable_ready.broadcast
end
end
Dispatches a DOM event in the browser.
cable_ready["MyChannel"].dispatch_event(
name: "string", # required - the name of the DOM event to dispatch (can be custom)
detail: "object", # [null] - assigned to event.detail
selector: "string" # [window] - string containing a CSS selector or XPath expression
)
Fast lightweight DOM diffing/patching without a virtual DOM.
cable_ready["MyChannel"].morph(
selector: "string", # required - string containing a CSS selector or XPath expression
html: "string", # [null] - the HTML to assign
children_only: true|false, # [null] - indicates if only child nodes should be morphed... skipping the parent element
permanent_attribute_name: "string", # [null] - an attribute name that prevents elements from being updated i.e. "data-permanent"
focus_selector: "string", # [null] - string containing a CSS selector
)
cable-ready:before-morph
cable-ready:after-morph
For some reason Stimulus controllers don't reconnect after DOM mutations triggered by Morphdom. You can force your controllers to reconnect with the following code.
import { Controller } from "stimulus"
export default class extends Controller {
connect() {
this.name = this.element.dataset.controller;
document.addEventListener('cable-ready:after-morph', this.reconnect.bind(this));
);
}
reconnect() {
setTimeout(() => this.element.setAttribute('data-controller', this.name), 1);
this.element.setAttribute('data-controller', '');
}
}
Sets the innerHTML of a DOM element.
cable_ready["MyChannel"].inner_html(
selector: "string", # required - string containing a CSS selector or XPath expression
focus_selector: "string", # [null] - string containing a CSS selector
html: "string" # [null] - the HTML to assign
)
cable-ready:before-inner-html
cable-ready:after-inner-html
Replaces a DOM element with new HTML.
cable_ready["MyChannel"].outerHTML(
selector: "string", # required - string containing a CSS selector or XPath expression
focus_selector: "string", # [null] - string containing a CSS selector
html: "string" # [null] - the HTML to use as replacement
)
cable-ready:before-outer-html
cable-ready:after-outer-html
Sets the text content of a DOM element.
cable_ready["MyChannel"].text_content(
selector: "string", # required - string containing a CSS selector or XPath expression
text: "string" # [null] - the text to assign
)
cable-ready:before-text-content
cable-ready:after-text-content
Inserts HTML into the DOM relative to an element. Supports behavior akin to prepend & append.
cable_ready["MyChannel"].insert_adjacent_html(
selector: "string", # required - string containing a CSS selector or XPath expression
focus_selector: "string", # [null] - string containing a CSS selector
position: "string", # [beforeend] - the relative position to the DOM element (beforebegin, afterbegin, beforeend, afterend)
html: "string" # [null] - the HTML to insert
)
cable-ready:before-insert-adjacent-html
cable-ready:after-insert-adjacent-html
Inserts text into the DOM relative to an element. Supports behavior akin to prepend & append.
cable_ready["MyChannel"].insert_adjacent_text(
selector: "string", # required - string containing a CSS selector or XPath expression
position: "string", # [beforeend] - the relative position to the DOM element (beforebegin, afterbegin, beforeend, afterend)
text: "string" # [null] - the text to insert
)
cable-ready:before-insert-adjacent-text
cable-ready:after-insert-adjacent-text
Removes an element from the DOM.
cable_ready["MyChannel"].remove(
selector: "string", # required - string containing a CSS selector or XPath expression
focus_selector: "string" # [null] - string containing a CSS selector
)
cable-ready:before-remove
cable-ready:after-remove
Sets the value of an element.
cable_ready["MyChannel"].set_value(
selector: "string", # required - string containing a CSS selector or XPath expression
value: "string" # [null] - the value to assign to the attribute
)
cable-ready:before-set-value
cable-ready:after-set-value
Sets an attribute on an element.
cable_ready["MyChannel"].set_attribute(
selector: "string", # required - string containing a CSS selector or XPath expression
name: "string", # required - the attribute to set
value: "string" # [null] - the value to assign to the attribute
)
cable-ready:before-set-attribute
cable-ready:after-set-attribute
Removes an attribute from an element.
cable_ready["MyChannel"].remove_attribute(
selector: "string", # required - string containing a CSS selector or XPath expression
name: "string" # required - the attribute to remove
)
cable-ready:before-remove-attribute
cable-ready:after-remove-attribute
Adds a css class to an element.
This is a noop
if the css class is already assigned.
cable_ready["MyChannel"].add_css_class(
selector: "string", # required - string containing a CSS selector or XPath expression
name: "string" # [null] - the CSS class to add
)
cable-ready:before-add-css-class
cable-ready:after-add-css-class
Removes a css class from an element.
cable_ready["MyChannel"].add_css_class(
selector: "string", # required - string containing a CSS selector or XPath expression
name: "string" # [null] - the CSS class to remove
)
cable-ready:before-remove-css-class
cable-ready:after-remove-css-class
Sets an dataset property (data-* attribute) on an element.
cable_ready["MyChannel"].set_dataset_property(
selector: "string", # required - string containing a CSS selector or XPath expression
name: "string", # required - the property to set
value: "string" # [null] - the value to assign to the dataset
)
cable-ready:before-set-dataset-property
cable-ready:after-set-dataset-property
Please run bin/standardize
on your codebase before submitting commits.
This project uses Standard
and Prettier to minimize bike shedding related to code formatting.
Please run ./bin/standardize
prior submitting pull requests.
- Bump version number at
lib/cable_ready/version.rb
- Run
rake build
- Run
rake release
- Change directories
cd ./javascript
- Run
yarn publish
- NOTE: this will throw a fatal error because the tag already exists but the package will still publish
CableReady is released under the MIT License.