Skip to content
dartajax edited this page Apr 8, 2015 · 16 revisions

#Form structuring in Ilios 3

In order to accommodate forms without using html tables, but still ensure the proper alignment of labels and fields, Ilios 3 forms are created using Bourbon Neat column spans, and the spans are set up in containing divs based on how many form fields will reside in each row.

A form can have any number of fields, but is limited to having one 1 to 3 form fields per row. In order to enforce proper alignment, each form 'label' is contained in its own respective 'column-span' and is paired with its form 'data' counter part, which also resides in its own respective column-span. Any given set of label/data 'column-span' pairs is contained in its own 'Form Column' div container. Each 'form column' is defined by a CSS class name representing the width the of the column in a percentage-column format as follows (eg, 'class="form-column-{numeric width-percentage without %}-[column-ordinal]"'):

##All forms For the grid alignment to work properly on any form, there must be a class of 'form-container' added to the container that will be holding the form, typically a '<section>' tag.

<section class='newsession form-container'>
  <div class="newsession-title">{{t 'sessions.new'}}</div>
  <div class="detail-content"> ...

3-column Form Rows

3-column rows should be used for rows the have small data (checkboxes and small text like dates or small numbers)

For form rows that will contain 3 form items (3 field/label pairs), use a 33%-based 3-column class:

<!-- the class of the container should be 'form-column-33-1' for '33% wide, first column'; the column's place in the order is denoted by by the column number (1) in the class, following the width percentage -->
<!-- for a 3 column row, the first/leftmost column -->
<label class="form-column form-column-33-1">
   <div class="form-label">{{t field.label}}:</div>
   <div class="form-data">{{input for data}}</div>
</label>
<!-- the middle/second column of a 3 column row -->
<label class="form-column form-column-33-2">
   <div class="form-label">{{t field.label}}:</div>
   <div class="form-data">{{input for data}}</div>
</label>
<!-- and, finally, the last/third column of a 3 column row -->
<label class="form-column form-column-33-3">
   <div class="form-label">{{t field.label}}:</div>
   <div class="form-data">{{input for data}}</div>
</label>

2-column Form Rows

2-column rows should be used for rows the have text data which does not require a lot of length (20-30 characters)

For form rows that will contain 2 form items (2 field/label pairs), use a 50%-based 2-column class:

<!-- the class of the container should be 'form-column-50-1' for '50% wide, first column'; the column's place in the order is denoted by by the column number (1) in the class, following the width percentage -->
<!-- for a 2 column row, the first/leftmost column -->
<label class="form-column form-column-50-1">
   <div class="form-label">{{t field.label}}:</div>
   <div class="form-data">{{input for data}}</div>
</label>
<!-- the final/second column of a 2 column row -->
<label class="form-column form-column-50-2">
   <div class="form-label">{{t field.label}}:</div>
   <div class="form-data">{{input for data}}</div>
</label>

1-column Form Rows

1-column rows should be used for fields that have a lengthy data-value requirement (long text fields/dropdown select lists, text areas, etc)

For form rows that will only contain one form item (1 field/label pair):

<!-- the class of the container should be 'form-column-100' for '100% wide'; there is only one column, so it is column order is implied and the column-order delimiter is not necessary in the class name --> 
<label class="form-column form-column-100">
   <div class="form-label">{{t field.label}}:</div>
   <div class="form-data">{{input for data}}</div>
</label>

##Special Form Elements There are a few special form elements which require some additional handling than those above. They are listed here:

###Submit Buttons The form submission buttons (cancel/submit) are automatically right-aligned and only need to be placed in the correctly-sized container in for proper placement.

For far-right alignment, place the buttons in a 100% wide container with the additional 'form-submit-data' data class:

<label class="form-column-100 form-data-submit">
  <button class='cancel' {{action 'cancel'}}>{{t 'general.cancel'}}</button>
  <button class='done' {{action 'save'}}>{{t 'general.done'}}</button>
</label>

For alignment in the "middle" of a form, do the same steps as above, but place the buttons in the first 50%-wide container:

<label class="form-column-50-1 form-data-submit">
  <button class='cancel' {{action 'cancel'}}>{{t 'general.cancel'}}</button>
  <button class='done' {{action 'save'}}>{{t 'general.done'}}</button>
</label>

In order to be able to properly size form elements within the 1, 2, or 3-column layout, it is sometimes helpful to explicitly set the data field's input type with a clarifying classname within its corresponding 'form-data' div. For example, checkboxes in Ilios 3 are typically styled as a 'toggle switch' and a 'form-data' div that will contain a toggle-switch styled checkbox input field should have the additional 'form-data-checkbox' class or you may see some stretching of the checkbox (see below)

###Checkbox Example: This checkbox is styled as an 'no/yes' white/green toggle switch and requires an explicit width; otherwise it will inherit the width of the whole column and render incorrectly. Adding the 'form-data-checkbox' class to the 'form-data' div, along with the other classes required by the particular toggle-type ('switch yes-no switch-green'), should take care of this:

<label class="form-column form-column-50-1">
   <div class="form-label">{{t field.label}}:</div>
   <div class="form-data form-data-checkbox switch yes-no switch-green">{{input for data}}</div>
</label>

##Full Form Example:

The following image displays an example 'Add New Session' form with all varieties of row layout (1, 2, and 3-column) which uses all varieties of input: text, select, checkbox, submit.

Ilios 3 Form Example

The code that created this form is here:

<section class='newsession form-container'>
  <div class="newsession-title">{{t 'sessions.new'}}</div>
  <div class="detail-content">
      <label class="form-column form-column-100">
        <div class="form-label">{{t 'general.title'}}:</div> 
        <div class="form-data form-data-text form-input-row">{{input value=session.title placeholder=placeholder}}</div>
      </label>
    
      <label class="form-column form-column-100">
        <div class="form-label">{{t "sessions.type"}}:</div>
        <div class="form-data form-data-select form-input-row">
          {{#if sortedSessionTypes}}
          {{view "select"
            content=sortedSessionTypes
            value=selectedSessionTypeId
            optionValuePath='content.id'
            optionLabelPath='content.title'
          }}
        {{else}}
          <select>
            <option selected>{{t 'sessions.loadingSessionTypes'}}</option>
          </select>
        {{/if}}
        </div>
      </label>
      <label class="form-column-50 form-column-50-1">
        <div class="form-label">{{t 'sessions.specialAttireRequired'}}:</div>
        <div class="form-data switch yes-no switch-green">
          <input class='switch-input' {{bind-attr checked=isPropertyChecked }} type='checkbox' />
          <span class="switch-label" data-on='{{t 'general.yes'}}' data-off='{{t 'general.no'}}'></span>
          <span class="switch-handle"></span>
        </div>
      </label>
      <label class="form-column-50 form-column-50-2">
        <div class="form-label">{{t 'sessions.specialEquipmentRequired'}}:</div>
        <div class="form-data switch yes-no switch-green">
          <input class='switch-input' {{bind-attr checked=isPropertyChecked }} type='checkbox' />
          <span class="switch-label" data-on='{{t 'general.yes'}}' data-off='{{t 'general.no'}}'></span>
          <span class="switch-handle"></span>
        </div>
      </label>
      <label class="form-column-33-1 form-column-33">
        <div class="form-label">{{t 'sessions.independentLearning'}}:</div>
        <div class="form-data switch yes-no switch-green">
          <input class='switch-input' {{bind-attr checked=isPropertyChecked }} type='checkbox' />
          <span class="switch-label" data-on='{{t 'general.yes'}}' data-off='{{t 'general.no'}}'></span>
          <span class="switch-handle"></span>
        </div>
      </label>
      <label class="form-column-33-2 form-column-33">
        <div class="form-label">{{t 'sessions.hours'}}:</div>
        <div class="form-data"><span class="slug">1</span></div>
      </label>
      <label class="form-column-33-3 form-column-33">
        <div class="form-label">{{t 'sessions.dueBy'}}:</div>
        <div class="form-data">
          <span class="slug">mm/dd/yyyy</span>
        </div>
      </label>

        <label class="form-column form-column-100">
          <div class="form-label">{{t 'general.description'}}:</div> 
          <div class="form-data">
            <span class="slug">Begin typing to enter description...</span></div>
        </label>

        <label class="form-column-100 form-data-submit">
            <button class='cancel' {{action 'cancel'}}>{{t 'general.cancel'}}</button>
            <button class='done' {{action 'save'}}>{{t 'general.done'}}</button>
        </label>
  </div> <!-- //detail-content -->
</section>