Select from list or create other structured data in form field I want to let users choose from a list of checkbox items, and I want users to be able to build their own options, if the options they want aren't in the list of checkboxes.
I'd like users to have the ability to build as many "custom" selections as they'd like.  

The value is compound, so http://drupal.org/project/select_or_other won't cut it.  

Is there a good module for this or a FAPI approach? It seems like this is close.

Here's a pseudo interface for illustration:

Select:

[] 1 liter(s)

[] 2 liter(s)

[] 1 gallon(s)

[] 2 gallon(s)

Or other(s):

[  (textbox that accepts number)  ]  [ (dropdown that lets you choose liter(s) or gallon(s)) ] [Add] &lt;--a button
You should check the examples module. Especially the ajax module. there is an example called Generate checkboxes This would lead you to the right direction.

The process would go as follows. You create the basic form then use create a button with Ajax call back. and return the required check box using the callback function. 

This is the relavent function that generated the form.

function ajax_example_autocheckboxes($form, &amp;$form_state) {
  // Since the form builder is called after every AJAX request, we rebuild
  // the form based on $form_state.
  $num_checkboxes = !empty($form_state['values']['howmany_select']) ? $form_state['values']['howmany_select'] : 1;

  $form['howmany_select'] = array(
    '#title' =&gt; t('How many checkboxes do you want?'),
    '#type' =&gt; 'select',
    '#options' =&gt; array(1 =&gt; 1, 2 =&gt; 2, 3 =&gt; 3, 4 =&gt; 4),
    '#default_value' =&gt; $num_checkboxes,
    '#ajax' =&gt; array(
      'callback' =&gt; 'ajax_example_autocheckboxes_callback',
      'wrapper' =&gt; 'checkboxes-div',
      //'method' defaults to replaceWith, but valid values also include
      // append, prepend, before and after.
      // 'method' =&gt; 'replaceWith',
      // 'effect' defaults to none. Other valid values are 'fade' and 'slide'.
      // See ajax_example_autotextfields for an example of 'fade'.
      'effect' =&gt; 'slide',
      // 'speed' defaults to 'slow'. You can also use 'fast'
      // or a number of milliseconds for the animation to last.
      // 'speed' =&gt; 'slow',
      // Don't show any throbber...
      'progress' =&gt; array('type' =&gt; 'none'),
    ),
  );


  $form['checkboxes_fieldset'] = array(
    '#title' =&gt; t("Generated Checkboxes"),
    // The prefix/suffix provide the div that we're replacing, named by
    // #ajax['wrapper'] above.
    '#prefix' =&gt; '&lt;div id="checkboxes-div"&gt;',
    '#suffix' =&gt; '&lt;/div&gt;',
    '#type' =&gt; 'fieldset',
    '#description' =&gt; t('This is where we get automatically generated checkboxes'),
  );

  for ($i = 1; $i &lt;= $num_checkboxes; $i++) {
    $form['checkboxes_fieldset']["checkbox$i"] = array(
      '#type' =&gt; 'checkbox',
      '#title' =&gt; "Checkbox $i",
    );
  }

  $form['submit'] = array(
    '#type' =&gt; 'submit',
    '#value' =&gt; t('Submit'),
  );

  return $form;
} 


There are couple of other examples related to the form api in the examples module that you can check out as well.