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

Instance Method Details

#vcr_boundary(path:) { ... } ⇒ String

Wrap component markup with a boundary for partial updates.

Parameters:

  • path (String)

Yields:

  • block for component content

Returns:

  • (String)


12
13
14
# File 'lib/view_component_reducible/helpers.rb', line 12

def vcr_boundary(path:, &block)
  (: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.

Parameters:

  • state (String)

    signed state token

  • msg_type (String)
  • msg_payload (Hash, String) (defaults to: {})
  • target_path (String, nil) (defaults to: nil)
  • url (String) (defaults to: '/vcr/dispatch')

Yields:

  • block for the form body (e.g., submit button)

Returns:

  • (String)


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_tagString

Insert the minimal JS dispatcher for partial updates.

Returns:

  • (String)


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
  (:script, js.html_safe)
end

#vcr_envelope_pathObject



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