@@ -1513,6 +1513,125 @@ def form_config
1513
1513
1514
1514
end
1515
1515
1516
+ describe "supports custom form input components on dynamically added child forms" do
1517
+
1518
+ before do
1519
+ @dummy_model = DummyModel . create ( title : "existing-dummy-model-title" )
1520
+
1521
+ class Components ::CustomFormInputTest < Matestack ::Ui ::VueJs ::Components ::Form ::Input
1522
+ vue_name "custom-form-input-test" # defined in app/spec/dummy/javascript/components.js
1523
+
1524
+ def response
1525
+ div class : "custom-input-markup" do
1526
+ label "my form input"
1527
+ span ":id" : "'input_uid'+vc.$parent.nestedFormRuntimeId" do
1528
+ plain "UID: {{ vc.props['component_uid'] }}"
1529
+ end
1530
+ input input_attributes
1531
+ button "change value" , "@click" : "vc.changeValueViaJs(42)" , type : :button
1532
+ render_errors
1533
+ end
1534
+ end
1535
+
1536
+ register_self_as ( :custom_form_input_test )
1537
+ end
1538
+
1539
+ class ExamplePage < Matestack ::Ui ::Page
1540
+
1541
+ def prepare
1542
+ @dummy_model = DummyModel . last
1543
+ end
1544
+
1545
+ def response
1546
+ matestack_form form_config do
1547
+ form_input key : :title , type : :text , label : "dummy_model_title_input" , id : "dummy_model_title_input"
1548
+
1549
+ @dummy_model . dummy_child_models . each do |dummy_child_model |
1550
+ dummy_child_model_form dummy_child_model
1551
+ end
1552
+
1553
+ form_fields_for_add_item key : :dummy_child_models_attributes , prototype : method ( :dummy_child_model_form ) do
1554
+ button "add" , type : :button # type: :button is important! otherwise remove on first item is triggered on enter
1555
+ end
1556
+
1557
+ br
1558
+ plain "data: {{vc.data}}"
1559
+ br
1560
+
1561
+ button "Submit me!"
1562
+
1563
+ toggle show_on : "success" , hide_after : 1000 do
1564
+ plain "success!"
1565
+ end
1566
+ toggle show_on : "failure" , hide_after : 1000 do
1567
+ plain "failure!"
1568
+ end
1569
+ end
1570
+ end
1571
+
1572
+ def dummy_child_model_form dummy_child_model = DummyChildModel . new ( title : "init-value" )
1573
+ form_fields_for dummy_child_model , key : :dummy_child_models_attributes do
1574
+ span ":id" : "'uid'+vc.nestedFormRuntimeId" do
1575
+ plain "UID: {{ vc.props['component_uid'] }}"
1576
+ end
1577
+ form_input key : :title , type : :text , label : "dummy-child-model-title-input"
1578
+ custom_form_input_test key : :bar , type : :text , id : "bar"
1579
+ form_fields_for_remove_item do
1580
+ button "remove" , ":id" : "'remove'+vc.nestedFormRuntimeId" , type : :button # id is just required in this spec, but type: :button is important! otherwise remove on first item is triggered on enter
1581
+ end
1582
+ end
1583
+ end
1584
+
1585
+ def form_config
1586
+ {
1587
+ for : @dummy_model ,
1588
+ method : :put ,
1589
+ path : nested_forms_spec_submit_update_path ( id : @dummy_model . id ) ,
1590
+ success : { emit : "success" } ,
1591
+ failure : { emit : "failure" }
1592
+ }
1593
+ end
1594
+ end
1595
+ end
1596
+
1597
+ it "dynamically adds unlimited new nested forms with different UIDs enabling proper getElement() usage when working with child form DOM" do
1598
+ # relevant form form input components accessing their child form DOM via UID
1599
+
1600
+ dummy_model = DummyModel . last
1601
+ child_model_0 = dummy_model . dummy_child_models . create ( title : "existing-child-model-title" )
1602
+
1603
+ visit "/example"
1604
+ # sleep
1605
+ uids = [ ]
1606
+ expect ( page ) . to have_selector ( '#dummy_model_title_input' )
1607
+ expect ( page ) . to have_selector ( '#title_dummy_child_models_attributes_child_0' )
1608
+ within "#dummy_child_models_attributes_child_0" do
1609
+ uids << page . find_by_id ( "uid_dummy_child_models_attributes_child_0" )
1610
+ uids << page . find_by_id ( "input_uid_dummy_child_models_attributes_child_0" )
1611
+ end
1612
+ expect ( page ) . to have_xpath ( '//matestack-component-template[@id="dummy_child_models_attributes_child_0"]//div[@class="custom-input-markup"]/input[@id="bar" and @class="js-added-class"]' )
1613
+ click_on "add"
1614
+ within "#dummy_child_models_attributes_child_1" do
1615
+ uids << page . find_by_id ( "uid_dummy_child_models_attributes_child_1" )
1616
+ uids << page . find_by_id ( "input_uid_dummy_child_models_attributes_child_1" )
1617
+ click_on "change value"
1618
+ end
1619
+ expect ( page ) . to have_xpath ( '//div[@class="matestack-form-fields-for" and @id="dummy_child_models_attributes_child_1"]//div[@class="custom-input-markup"]/input[@id="bar" and @class="js-added-class"]' )
1620
+ click_on "add"
1621
+ within "#dummy_child_models_attributes_child_2" do
1622
+ uids << page . find_by_id ( "uid_dummy_child_models_attributes_child_2" )
1623
+ uids << page . find_by_id ( "input_uid_dummy_child_models_attributes_child_2" )
1624
+ end
1625
+ expect ( page ) . to have_xpath ( '//div[@class="matestack-form-fields-for" and @id="dummy_child_models_attributes_child_2"]//div[@class="custom-input-markup"]/input[@id="bar" and @class="js-added-class"]' )
1626
+
1627
+ expect ( uids . count ) . to eq ( uids . uniq . count )
1628
+
1629
+ expect ( page ) . to have_content ( "data: { \" dummy_child_models_attributes\" : [ { \" _destroy\" : false, \" id\" : \" #{ child_model_0 . id } \" , \" title\" : \" existing-child-model-title\" , \" bar\" : null }, { \" _destroy\" : false, \" id\" : null, \" title\" : \" init-value\" , \" bar\" : 42 }, { \" _destroy\" : false, \" id\" : null, \" title\" : \" init-value\" , \" bar\" : null } ], \" title\" : \" existing-dummy-model-title\" }" )
1630
+
1631
+ end
1632
+
1633
+ end
1634
+
1516
1635
end
1517
1636
1518
1637
end
0 commit comments