Skip to content

AmpersandJS/ampersand-select-view

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ampersand-select-view

Lead Maintainer: Christopher Dieringer (@cdaringe)

overview

A view module for intelligently rendering and validating selectbox input. Works well with ampersand-form-view.

install

npm install ampersand-select-view

Part of the Ampersand.js toolkit for building clientside applications.

API Reference

clear() - [Function] - returns this

Alias to calling setValue(null, true). Sets the selected option to either the unselectedText option or a user defined option whose value is null. Be mindful that if no unselectedText or null option exists, the view will error.

reset() - [Function] - returns this

Sets the selected option and view value to the original option value provided during construction.

setValue([value, skipValidationMessage]) - [Function] - returns this

Sets the selected option to that which matches the provided value. Updates the view's .value accordingly. SelectView will error if no matching option exists. null, undefined, and '' values will preferentially select unselectedText if defined.

constructor - [Function] new SelectView([options])

options

general options
  • name: the <select>'s name attribute's value. Used when reporting to parent form
  • parent: parent form reference
  • options: array/collection of options to render into the select box
  • [groupOptions]: use instead of options to generate <optgroup> elements within your <select>. If this is set, any values passed in options will be ignored and replaced with values coming from groupOptions.
  • [el]: element if you want to render the view into
  • [template]: a custom template to use (see 'template' section, below, for more)
  • [required]: [default: false] field required
  • [eagerValidate]: [default: false] validate and show messages immediately. Note: field will be validated immediately to provide a true .valid value, but messages by default are hidden.
  • [unselectedText]: text to display if unselected
  • [value]: initial value for the <select>. value must be a member of the options set
  • [tabindex]: [default: 0] Specify the tab index number for your field (integer).
label & validation options
  • [label]: [default: name value] text to annotate your select control
  • [invalidClass]: [default: 'select-invalid'] class to apply to root element if invalid
  • [validClass]: [default: 'select-valid'] class to apply to root element if valid
  • [requiredMessage]: [default: 'Selection required'] message to display if invalid and required
collection option set

If using a collection to produce <select> <option>s, the following may also be specified:

  • [disabledAttribute]: boolean model attribute to flag disabling of the option node
  • [idAttribute]: model attribute to use as the id for the option node. This will be returned by SelectView.prototype.value
  • [textAttribute]: model attribute to use as the text of the option node in the select box
  • [yieldModel]: [default: true] if options is a collection, yields the full model rather than just its idAttribute to .value

When the collection changes, the view will try and maintain its currently .value. If the corresponding model is removed, the <select> control will default to the 0th index <option> and update its value accordingly.

custom template

You may override the default template by providing your own template string to the constructor options hash. Technically, all you must provided is a <select> element. However, your template may include the following under a single root element:

  1. An element with a data-hook="label" to annotate your select control
  2. An <select> element to hold your options
  3. An element with a data-hook="message-container" to contain validation messages
  4. An element with a data-hook="message-text" nested beneath the data-hook="message-container" element to show validation messages

Here's the default template for reference:

<label class="select">
    <span data-hook="label"></span>
    <select></select>
    <span data-hook="message-container" class="message message-below message-error">
        <p data-hook="message-text"></p>
    </span>
</label>

You may SelectView.extend({ template: ...}) to create a View definition with a more permanent default template of your liking as well.

example

var FormView = require('ampersand-form-view');
var SelectView = require('ampersand-select-view');

module.exports = FormView.extend({
    fields: function () {
        return [
            new SelectView({
                label: 'Pick a color!',
                // actual field name
                name: 'color',
                parent: this,
                // you can pass simple string options
                options: ['blue', 'orange', 'red'],
                // if included this will add option for an unselected state
                unselectedText: 'please choose one',
                // you can specify that they have to pick one
                required: true,
                // specify tab index for usability
                tabindex: 1,
            }),
            new SelectView({
                name: 'option',
                parent: this,
                // you can also pass array, first is the value, second is used for the label
                // and an optional third value can used to disable the option
                options: [ ['a', 'Option A'], ['b', 'Option B'], ['c', 'Option C', true] ],
                tabindex: 2,
            }),
            new SelectView({
                name: 'option',
                parent: this,
                // define groupOptions to generate <optgroup> elements. Pass it an array of
                // Objects, each object will become an <optgroup> with groupName being the
                // <optgroup>'s name and options being an array (either of strings or array, see
                // previous two examples) that will become the <option>s under that <optgroup>
                groupOptions: [
                  {
                    groupName: "Options 1",
                    options: [ ['1', 'Option 1'], ['2', 'Option 2'], ['3', 'Option 3', true] ]
                  },
                  {
                    groupName: "Options 2",
                    options: [ ['a', 'Option A'], ['b', 'Option B'], ['c', 'Option C', true] ]
                  }
                ],
                tabindex: 3,
            }),
            new SelectView({
                name: 'model',
                parent: this,
                // you can pass in a collection here too
                options: collection,
                // and pick an item from the collection as the selected one
                value: collection1.at(2),
                // here you specify which attribute on the objects in the collection
                // to use for the value returned.
                idAttribute: 'id',
                // you can also specify which model attribute to use as the title
                textAttribute: 'title',
                // you can also specify a boolean model attribute to render items as disabled
                disabledAttribute: 'disabled',
                // here you can specify if it should return the selected model from the
                // collection, or just the id attribute.  defaults `true`
                yieldModel: false,
                tabindex: 4,
            })
        ];
    }
});

gotchas

  • Numeric option values are generally stringified by the browser. Be mindful doing comparisons. You'll generally desire to inspect selectView.value (the value of your selected options' input) over selectView.select.value (the value returned from the browser).

    • Additionally, do not use option sets containing values that == one another. E.g., do not use options whose values are "2" (string) and 2 (number). Browsers cannot distinguish between them in the select control context, thus nor can ampersand-select-view.
  • null, undefined, or '' option values are not considered valid when the field is required. This does not apply when options are from a collection and yieldModel is enabled.

    • The unselectedText option will always be preferred in updating the control to an empty-ish value.

browser support

testling badge

changelog

  • 7.0.0

    • Upgrade to &-view 9.x
  • 6.2.1

    • Added the tabindex option to allow custom tab-ordering of fields for usability
  • 6.2.0

    • Support extending template
  • 6.1.0

    • Generate <optgroup> elements by passing the new options.groupOptions parameter
  • 6.0.0

    • Match field label rendering behavior to ampersand-input-view. removes label fallback to name attr
    • Improve x-browser testing CI
  • 5.0.0

    • Change events now always get triggered on the select element instead of blindly calling on the root element.
  • 4.0.0

    • Extend ampersand-view and support autoRender, where previously this view would autoRender unconditionally
  • 3.0.0

    • Improve general option edge cases, and add supporting test cases. Primarily targets falsy option value handling.
    • Validate immediately to assist when parent FormView tests onload for field validity. Update skipValidation to skipValidationMessage, permit immediate validation, but conditionally display messages.
    • Throw an Error when trying to setValue(value) and an option matching the requested value does not exist. The exception to this is when the provided value is null, undefined, or '', and a null option value exists. Because the DOM can only recognize a single empty value for any <option>, which is the empty string '', only a single empty-ish option can only be supported by the view.
    • Support 0 value options, both in Model id's and array values.
    • Add eagerValidate.
    • Denote a plan for 4.x release
    • Bulk update README, and some cody tidying

credits

Originally designed & written by @philip_roberts.

license

MIT