phlex-reactive 0.11.6 → 0.11.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -840,14 +840,58 @@ module Phlex
840
840
  # The add-a-row trigger — CLIENT-ONLY (no dispatch descriptor, no
841
841
  # POST). Forced type="button": a bare button inside the surrounding
842
842
  # real <form> would submit it.
843
- def reactive_nested_add(association)
844
- {
845
- type: "button",
846
- data: {
847
- action: "click->reactive#nestedAdd",
848
- reactive_association_param: nested_identifier!(:reactive_nested_add, :association, association)
849
- }
843
+ #
844
+ # FILL-THEN-ADD (issue #208 Scenario A). By default add clones the
845
+ # template and focuses the new row's first field — INLINE-EDIT (you
846
+ # type INTO the row). But a common form shape puts the add controls
847
+ # OUTSIDE the row (a preset <select>, a typeahead, plain inputs) and
848
+ # "Add" SNAPSHOTS those values into a new row, then clears them for the
849
+ # next entry. `from:` expresses that: a map of ROW FIELD name => SOURCE
850
+ # CONTROL selector. On click the client fills each cloned-row field
851
+ # from its source's current value (matching the field by the trailing
852
+ # bracket segment of its name — the SAME key inference JSON mode uses,
853
+ # so the two agree), keeps focus on the sources, and (with `clear:
854
+ # true`) resets the sources. It composes with BOTH wire modes: the
855
+ # seeded values ride the renumbered `…_attributes[i][field]` names on
856
+ # submit (:attributes), and the end-of-add JSON sync serializes them
857
+ # (as: :json) with no extra wiring.
858
+ #
859
+ # a(**reactive_nested_add(:items,
860
+ # from: { name: "#item-name", quantity: "#item-qty" }, clear: true))
861
+ #
862
+ # `from:` values are RAW CSS selectors (the escape-hatch posture of
863
+ # reactive_filter/reactive_tags) — the sources are author-owned markup,
864
+ # not reactive_field bindings — resolved root-scoped (#15 ownership).
865
+ def reactive_nested_add(association, from: nil, clear: false)
866
+ data = {
867
+ action: "click->reactive#nestedAdd",
868
+ reactive_association_param: nested_identifier!(:reactive_nested_add, :association, association)
850
869
  }
870
+ unless from.nil?
871
+ data[:reactive_nested_from_param] = nested_from_param!(from)
872
+ # STRING "true", not boolean: a valueless boolean attr reads "" (falsy)
873
+ # client-side — the on()/tags precedent.
874
+ data[:reactive_nested_clear_param] = "true" if clear
875
+ end
876
+ { type: "button", data: }
877
+ end
878
+
879
+ # Validate + compile a fill-then-add `from:` map into its JSON wire
880
+ # (issue #208). Each key is a ROW FIELD name (plain identifier, like the
881
+ # association); each value is a SOURCE CONTROL selector (non-blank). An
882
+ # empty map is a dead binding — fail at render (the reactive_show_targets
883
+ # posture), never a silent no-op.
884
+ def nested_from_param!(from)
885
+ unless from.is_a?(Hash) && from.any?
886
+ raise ArgumentError,
887
+ "reactive_nested_add from: needs at least one row-field => source-selector pair " \
888
+ "(e.g. from: { quantity: \"#item-qty\" }), got #{from.inspect}"
889
+ end
890
+
891
+ from.to_h do |field, selector|
892
+ [nested_identifier!(:reactive_nested_add, :field, field),
893
+ filter_selector!(:reactive_nested_add_from, selector)]
894
+ end.to_json
851
895
  end
852
896
 
853
897
  # A row's remove trigger — client-only. Draft rows leave the DOM;
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Phlex
4
4
  module Reactive
5
- VERSION = "0.11.6"
5
+ VERSION = "0.11.7"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlex-reactive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.6
4
+ version: 0.11.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson