ember-form-master-2000
v3.4.1
Published
A simple and flexible Ember-CLI based form builder.
Downloads
2,290
Maintainers
Readme
NOTE
This project is in the process of moving towards Ember 2.1. There is still some work to be done, so please have patience.
Installation
This is an ember-cli addon and can be installed using npm:
npm install --save-dev ember-form-master-2000
Demo
You can see the basic dummy app here:
Overview
Ember Form Master 2000 is an extensible library for creating forms in Ember. The library comes out of the box with the standard form components you would expect and it is easy to add more custom components as needed.
FM2000's primary entry point is the fm-field
component. This is
used to render a form field to the page. Even when you are making custom
components you will still use fm-field
to render them.
Every time a field is rendered, it renders a display
and a widget
.
displays
are responible for the layout and css formatting of your form
field. For example, using different display
s you could opt to
render a field using horizontal form style or a stacked form style.
widgets
are responsible for encapulsating the actual component
that is manipulated. There are built in widgets for things like
input
and textarea
but you could add a custom date picker widget or
a fancy autocomplete widget. To learn more about creating custom displays
and widgets
see the Extending Form Master below.
Validation
Currently FM2000 is all about rendering interactive forms in a standardized way with a concise and extensible syntax. FM2000 is not about doing form validation or managing CRUD logic. We may consider adding this functionality in the future but it will be as a separate layer from the existing components which are purely responsible for form display.
Built-In Components
The following is the basic API for Ember 2.3+. The hash
helper that
is used below is not present in Ember 2.0-2.2. We are currently still supporting
setting the widgetAttrs values for the default widgets directly on the
fm-field
component. For those versions just
specifiy widgetAttrs
directly on the the component. The supported
attributes for this are listed in the WIDGET_ATTR_ALIASES
constant in
addon/components/fm-field.js
.
{{#fm-form action='submit'}}
{{fm-field label='First Name'
value=model.exampleModel.first_name
errors=model.exampleModel.errors.first_name
placeholder='Foo'
}}
{{fm-field label='Last Name'
value=model.exampleModel.last_name
errors=model.exampleModel.errors.last_name
placeholder='Bar'
}}
{{fm-field
label='Write an Essay'
type='textarea'
value=model.exampleModel.essay
errors=model.exampleModel.errors.essay
rows='6'
helptext='Make sure its good!'
data-test='master-2000'
}}
{{fm-field
label='Choose Something'
type='select'
content=model.selectOptions
optionValuePath='value'
optionLabelPath='label'
prompt='Select Something'
value=model.exampleModel.language
action=(action (mut model.exampleModel.language))
errors=model.exampleModel.errors.language
}}
{{fm-field
widget='checkbox'
label='Are you awesome?'
value=model.exampleModel.isAwesome
errors=model.exampleModel.errors.isAwesome
}}
{{fm-field
widget='radio-group'
label='Choose the best language'
name='bestLanguage'
content=model.radioOptions
optionValuePath='value'
optionLabelPath='label'
value=model.exampleModel.bestLanguage
errors=model.exampleModel.errors.bestLanguage
}}
{{fm-submit value='Submit the Form' disabled=model.disableSubmit}}
{{/fm-form}}
Extending Form Master
There are two ways to extend form-master's built in functionality.
Widgets
Widgets are responsible for creating a UI object to manipulate some
data. Form-master provides some builtin widgets such as select
, textarea
and
radio-group
. Note that some widgets are interchangeable for the same
type of data. Both a textarea
and input
work well for manipulating
a string attribute. Similarly, a selection from a predefined list could
be done with either a select
or a radio-group
widget.
You can easily override any of the existing widgets to augment or modify their functionality.
Widgets should do as little as possible to affect their appearance.
They should not specify css classes and should contain as little dom in
their templates as is necessary for them to function. For an example of
this, look at how fm-widgets/checkbox
contains only the checkbox
element itself and the label
and surrounding divs are in the
fm-displays/checkbox
component.
You can also create your own custom widgets. For instance, you may want to
create an autocompleting text input. This would be easily done by creating
a new component called fm-widgets/autocomplete
.
You would then be able to create a field
with an autocomplete widget as follows:
{{fm-field
widget='autocomplete'
value=value
widgetAttrs=(hash
choices=autocompleteChoices
placeholder=placeholder
)
}}
The fm-field
component will take care of adding labels, errors and
formatting classes around your autocomplete widget. Meanwhile your
autocomplete widget can focus solely on adding the extra autocomplete
functionality you want.
You can create custom form widgets easily. Simply create a new
component named as fm-widgets/<your widget name>
. A widget will
receive the following attrs:
value
: the current value of the input.action
(optional): action to call with a new value chosen through user interaction with the widget. If you do not want to support actions-up/data-down design you can modifyvalue
directly and ignoreaction
.widgetAttrs
: an Ember.Object which is used as a vessel to pass any custom values for your widget. For instance a select, widget would look for the choices, labelField and valueField properties in thewidgetAttrs
property.onUserInteraction
: your custom widget needs to call this action whenever it is manipulated. This letsfm-field
know when it should show errors on the form field.classNames
: allows thefm-field's
display component to add certain standard css classes.
Displays
Displays let you customize the aesthetics of a form field. For
instance, you may want to create a display where the fields label and
inputs appear in rows. You could do this by creating a component
called fm-displays/horizontal
. Your
templates/components/fm-displays/horizontal.hbs
might look like this:
<div class="{{styles.wrapperClass}}">
<label for="{{forAttribute}}" class="col-sm-2 {{styles.labelClass}}">
{{label}}
</label>
<div class="col-sm-10">
{{yield inputClasses}}
</div>
{{#if visibleErrors.length}}
<span class="{{styles.errortextClass}}">
{{visibleErrors.firstObject}}
</span>
{{/if}}
{{#if helptext}}
<span class="{{styles.helptextClass}}">
{{helptext}}
</span>
{{/if}}
</div>
This widget will be included wherever you place the yield
statement.
The inputClasses
attribute is passed to the yield
statement to
specify classes that should be applied to the widget itself.
You can now use this display anywhere in your application by simply specifying
the layout when creating an fm-field
:
{{fm-field
display='horizontal'
widget='input'
value=myValue
errors=errors
placholder=placehodler
}}
Note how we defer to styles
property for class names where possible.
This ties in the fm-config
service which provides easy configuration of
form classes on a global basis.
The best place to start for creating a display is to look at
fm-displays/default.hbs
.
Errors
Displaying validation errors is a core requirement for any form library.
To keep things simple, you must explicitly tell fm-fields what errors
should be displayed. When provided an array of errors,
fm-field
will display the first error.
var model = Ember.Object.create();
model.set('errors', Ember.Object.create({first_name: ['Required', 'Too short']}));
{{fm-field type='text' value=model.first_name errors=model.errors.first_name}}
By default, fm-field
displays any error that is included in the
errors
property. If you do not want errors to be displayed until a
fm-field
has been manipulated for the first time, set the
showErrorsByDefault
property in the fm-config
service to false
.
With this change, fm-field
will only display errors when it has been
notified by its widget that the widget has received user interaction.
If you are using the fm-form
wrapper component and fm-submit
then
clicking the fm-submit
button will also cause errors to display.
Minor Customizations
If you need to make minor adjustments to classnames of the elements, you can easily override the default initializer with your own. The default initializer can be found here, which imports the default configuration from the addon directory.
Demo App
You can see a more holistic example by looking at the Dummy app that we use to test against. The index.hbs template and the application route are of particular interest.