Dynamically Adding Fields to FormIt

I think I finally have a solution to add fields to a FormIt form!!!

It works for me, I hope that someone can take it and refine it for general release. (Sidenote: I wish there was an official location to find add-ons for extras. Like FormIt hooks ,and Output Filters.)

resource

[[!FormIt?
   &preHooks=`FormItLoopFields`
   &hooks=`FormItUpdateLoopInt,FormItJSON`
   &iterations=`5`
]]

<h1>Form</h1>
<form action="[[~[[*id]]]]" method="post" id="form" class="form">
<input type="hidden" id="fieldCount" name="fieldCount" value="[[+int]]" />
    <div class="form-row">
        <label for="name">Name</label>
        <input type="text" name="name" size="50" class="form-field" value="[[!+fi.name]]" placeholder="Your Name"/>
    </div>
<div class="loopFields">
[[+loopFields]]
</div>

    <button class="add_form_fields">Add New Fields &nbsp; 
      <span style="font-size:16px; font-weight:bold;">+ </span>
    </button>
    <button type="submit" class="submit-button">Submit</button>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script>
$(document).ready(function() {
    var max_fields = 10;
    var wrapper = $(".loopFields");
    var add_button = $(".add_form_fields");
    var x = [[+int]];
    $(add_button).click(function(e) {
        e.preventDefault();
        if (x < max_fields) {
            x++;
            $(wrapper).append('[[$formRow:strip?idx=`' + x + '`]]'); //add input box
            $('#fieldCount').val(x);
        } else {
            alert('You Reached the limits')
        }
    });
});
</script>

snippet: FormItUpdateLoopInt

<?php
$int = $hook->getValue('fieldCount');
$output = $modx->runSnippet('FormItLoopFields',array(
   'iterations' => $int
));
return true;

snippet: FormItLoopFields

<?php
$iterations = $modx->getOption('iterations',$formit->config, 3);
$iterations = $modx->getOption('iterations', $scriptProperties, 3);
$tpl = $modx->getOption('tpl', $formit->config, 'formRow');
$tpl = $modx->getOption('tpl', $scriptProperties, 'formRow');

for ($idx = 1; $idx <= $iterations; $idx++) {
$output .= $modx->getChunk($tpl,array('idx'=>$idx));
}
$modx->setPlaceholder('int',$idx-1);
$modx->setPlaceholder('loopFields',$output);
return true;

chunk: formRow

<fieldset id="Address-[[+idx]]">
  <legend>Address [[+idx]]</legend>
  <div class="form-group col-xs-12">
    <label for="address[[+idx]]">Street Address</label>
    <div class="input-group" style="width:100%">
      <input type="text" class="form-control"
        name="address[[+idx]]"
        id="address[[+idx]]"
        value="[[!+fi.address[[+idx]]]]"
		placeholder="Street Address"
      />
	</div>
  </div>
  <div class="form-group col-xs-4">
    <label for="city[[+idx]]"><br class="visible-xs-block">City</label>
    <div class="input-group">
      <div class="input-group-addon hidden-xs">$</div>
      <input type="text" class="form-control"
        name="city[[+idx]]"
        id="city[[+idx]]"
        value="[[!+fi.city[[+idx]]]]"
		placeholder="city"
		/>
    </div>
  </div>
  <div class="form-group col-xs-4">
    <label for="state[[+idx]]">State</label>
    <div class="input-group">
      <div class="input-group-addon hidden-xs">$</div>
      <input type="text" class="form-control"
        name="state[[+idx]]"
        id="state[[+idx]]"
        value="[[!+fi.state[[+idx]]]]"
		placeholder="state"
      />
    </div>
  </div>
  <div class="form-group col-xs-4">
    <label for="zip[[+idx]]"><br class="visible-xs-block">ZIP</label>
    <div class="input-group">
      <input type="text" class="form-control"
        name="zip[[+idx]]"
        id="zip[[+idx]]"
        value="[[!+fi.zip[[+idx]]]]"
		placeholder="zip code"
      />
    </div>
  </div>
</fieldset>

I am using a hidden field to track the count, I could not get the data passed to the hook any other way.

1 Like