Module: ViewComponentReducible::Helpers
- Defined in:
- lib/view_component_reducible/helpers.rb
Overview
View helpers for dispatching messages to the VCR endpoint.
Instance Method Summary collapse
-
#vcr_boundary(path:) { ... } ⇒ String
Wrap component markup with a boundary for partial updates.
-
#vcr_dispatch_form(state:, msg_type:, msg_payload: {}, target_path: nil, url: '/vcr/dispatch') { ... } ⇒ String
Build a dispatch form with hidden fields for the VCR endpoint.
-
#vcr_dispatch_script_tag ⇒ String
Insert the minimal JS dispatcher for partial updates.
- #vcr_envelope_path ⇒ Object
Instance Method Details
#vcr_boundary(path:) { ... } ⇒ String
Wrap component markup with a boundary for partial updates.
12 13 14 |
# File 'lib/view_component_reducible/helpers.rb', line 12 def vcr_boundary(path:, &block) content_tag(:div, capture(&block), data: { vcr_path: path }) end |
#vcr_dispatch_form(state:, msg_type:, msg_payload: {}, target_path: nil, url: '/vcr/dispatch') { ... } ⇒ String
Build a dispatch form with hidden fields for the VCR endpoint.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/view_component_reducible/helpers.rb', line 24 def vcr_dispatch_form(state:, msg_type:, msg_payload: {}, target_path: nil, url: '/vcr/dispatch', &block) payload = msg_payload.is_a?(String) ? msg_payload : JSON.generate(msg_payload) resolved_target = target_path || vcr_envelope_path || instance_variable_get(:@vcr_current_path) || 'root' state_param = ViewComponentReducible.config.adapter.state_param_name form_tag(url, method: :post, data: { vcr_form: true, vcr_state_param: state_param }) do body = [ hidden_field_tag(state_param, state), hidden_field_tag('vcr_msg_type', msg_type), hidden_field_tag('vcr_msg_payload', payload), hidden_field_tag('vcr_target_path', resolved_target), (block_given? ? capture(&block) : '') ] safe_join(body) end end |
#vcr_dispatch_script_tag ⇒ String
Insert the minimal JS dispatcher for partial updates.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/view_component_reducible/helpers.rb', line 43 def vcr_dispatch_script_tag js = <<~JS (function() { if (window.__vcrDispatchInstalled) return; window.__vcrDispatchInstalled = true; document.addEventListener("submit", function(event) { var form = event.target; if (!(form instanceof HTMLFormElement)) return; if (!form.matches("[data-vcr-form]")) return; event.preventDefault(); var formData = new FormData(form); formData.append("vcr_partial", "1"); fetch(form.action, { method: (form.method || "POST").toUpperCase(), body: formData, headers: { "X-Requested-With": "XMLHttpRequest" } }) .then(function(response) { var state = response.headers.get("X-VCR-State"); return response.text().then(function(html) { return { html: html, state: state }; }); }) .then(function(payload) { var targetPath = formData.get("vcr_target_path"); var parser = new DOMParser(); var doc = parser.parseFromString(payload.html, "text/html"); var newNode = doc.querySelector('[data-vcr-path="' + targetPath + '"]') || doc.body.firstElementChild; var current = document.querySelector('[data-vcr-path="' + targetPath + '"]'); if (newNode && current) { current.replaceWith(newNode); } if (payload.state) { var boundary = document.querySelector('[data-vcr-path="' + targetPath + '"]'); if (boundary) { var stateParam = form.dataset.vcrStateParam || "vcr_state"; boundary.querySelectorAll('input[name="' + stateParam + '"]').forEach(function(input) { input.value = payload.state; }); } } }); }); })(); JS content_tag(:script, js.html_safe) end |
#vcr_envelope_path ⇒ Object
91 92 93 94 95 |
# File 'lib/view_component_reducible/helpers.rb', line 91 def vcr_envelope_path return unless respond_to?(:vcr_envelope) && vcr_envelope vcr_envelope['path'] end |