Form Inputs
Handling forms and user input is quite a common task in applications. Whether you are building a login form, data entry, or even a chat application, Aurelia allows you to work with forms intuitively.
In Aurelia, the binding system uses two-way
binding as a default for form elements. Text inputs, text areas and even contenteditable
elements all use a two-way
binding.
Many of the concepts discussed here assume knowledge of how Aurelia's template and binding syntax work. We recommend reading the Template syntax & features section before continuing with this section if you are new to Aurelia.
Data flow in forms
In Aurelia, form elements are reactive, and their changes are directly tied to the underlying view model. Updates flow from the view to the view model, and updates from the view model flow to the view (hence, two-way).
To illustrate how two-way
binding works in forms, let's break down the workflow:
The user types a value into the input element. The element is for a first name, so they enter John.
The native form input events are fired, and Aurelia also sees the value has changed.
The binding system sees the new value and notifies the view model to update the value.
Any reference to the bound value will be updated without needing any callback functions or additional notification steps (the value changes).
Creating a basic form
Creating forms in Aurelia requires no special configuration or treatment. Create a form element and add form input controls with bindings. Here is a basic form example for a login form to show you how little code you need.
Firstly, let's create the markup for our login form:
Before we write the view model code, let's break down what we did here:
We created a form with two text inputs
We used
value.bind
to bind the native value attribute of these fields to the corresponding view model propertiesWe are calling a function
handleLogin
when thesubmit
event on the form is triggered to handle the bindable properties inside
Now, the corresponding view model code:
There is not a whole lot of code here for what is happening. Whenever the email
or password
values change, they will be reflected inside of our view model. Inside the handleLogin
method, we would probably validate the data and call an API.
Using submit.trigger
on a form will prevent its default action by applying a event.preventDefault
behind-the-scenes. This means your form will not submit to the action or method attributes on the form, you will need to handle this manually.
Binding with text and textarea inputs
Binding to text inputs uses a syntax similar to binding to other elements in Aurelia. By default, input elements will use two-way
binding, which means the value will update in the view when changed inside the view model and updated in the view model when changed in the view.
Text Input
You can even bind to other attributes on form elements such as the placeholder
attribute.
Textarea
A textarea element is just like any other form element. It allows you to bind to its value and, by default, value.bind
will be two-way binding (meaning changes flow from out of the view into the view model and changes in the view-model flow back to the view).
Binding with checkbox inputs
Aurelia supports the two-way binding of various data types to checkbox input elements.
Booleans
Bind a boolean property to an input element's checked
attribute using checked.bind="myBooleanProperty"
.
Array of Numbers
A set of checkbox elements is a multiple-selection interface. If you have an array that serves as the "selected items" list, you can bind the array to each input's checked
attribute. The binding system will track the input's checked status, adding the input's value to the array when the input is checked and removing the input's value from the array when the input is unchecked.
To define the input's "value", bind the input's model
attribute: model.bind="product.id"
.
Array of Objects
Numbers aren't the only type of value you can store in a "selected items" array. The binding system supports all types, including objects. Here's an example that adds and removes "product" objects from a selectedProducts
array using the checkbox data-binding.
Array of Objects with Matcher
You may run into situations where the object your input element's model is bound to do not have reference equality to any objects in your checked array. The objects might match by id, but they may not be the same object instance. To support this scenario, you can override Aurelia's default "matcher", which is an equality comparison function that looks like this: (a, b) => a === b
.
You can substitute your chosen function with the right logic to compare your objects.
Array of Strings
Finally, here's an example that adds and removes strings from an selectedProducts
array using the checkbox data-binding. This is example is unique because it does not use model.bind
to assign each checkbox's value. Instead, the input's standard value
attribute is used.
Normally we cannot use the standard value
attribute in conjunction with checked binding because it coerces anything assigned to a string. This example uses an array of strings, so everything works just fine.
Binding with radio inputs
A radio input group is a "single select" interface. Aurelia supports two-way binding any type of property to a group of radio inputs. The examples below illustrate binding number, object, string and boolean properties to sets of radio inputs. In each of the examples, there's a common set of steps:
Group the radios via the
name
property. Radio buttons with the same value for the name attribute are in the same "radio button group"; only one radio button in a group can be selected at a time.Define each radio's value using the
model
property.Two-way bind each radio's
checked
attribute to a "selected item" property on the view model.
Numbers
Let's start with an example that uses a numeric "selected item" property. Each radio input will be assigned a number value via the model property in this example. Selecting a radio will cause its model value to be assigned to the selectedProductId
property.
Objects
The binding system supports binding all types of radios, including objects. Here's an example that binds a group of radios to a selectedProduct
object property.
Objects with Matcher
You may run into situations where the object your input element's model is bound to does not have reference equality to any of the objects in your checked attribute bound to. The objects might match by id, but they may not be the same object instance. To support this scenario, you can override Aurelia's default "matcher", which is an equality comparison function that looks like this: (a, b) => a === b
.
You can substitute your chosen function with the right logic to compare your objects.
Booleans
In this example, each radio input is assigned one of three literal values: null
, true
and false
. Selecting one of the radios will assign its value to the likesCake
property.
Strings
Finally, here's an example using strings. This is example is unique because it does not use model.bind
to assign each radio's value. Instead, the input's standard value
attribute is used. Normally we cannot use the standard value
attribute in conjunction with checked binding because it coerces anything assigned to a string.
Binding with select elements
A <select>
element can serve as a single-select or multiple-select "picker", depending on whether the multiple
attribute is present. The binding system supports both use cases. The samples below demonstrate a variety of scenarios.
All use a common series of steps to configure the selected element:
Add a
<select>
element to the template and decide whether themultiple
attribute should be applied.Bind the select element's
value
attribute to a property. In "multiple" mode, the property should be an array. In singular mode, it can be any type.Define the select element's
<option>
elements. You can userepeat
or add each option element manually.Specify each option's value via the
model
property:<option model.bind="product.id">${product.name}</option>
You can use the standard
value
attribute instead ofmodel
, remember- it will coerce anything it's assigned to a string.
Select Number
Select Object
Select Object with Matcher
You may run into situations where the object to your select element's value is bound and does not have reference equality with any of the objects your option element model properties are bound to. The select's value object might "match" one of the option objects by id, but they may not be the same object instance.
To support this scenario, you can override Aurelia's default "matcher", which is an equality comparison function that looks like this: (a, b) => a === b
. You can substitute your chosen function with the right logic to compare your objects.
Select Boolean
Select String
Multiple Select Numbers
Multiple Select Objects
Multiple Select Strings
Form Submission
Most of the time, a <form>
element should be used to group one or many controls in a form. It acts as a container for those controls and can also be used for layout purposes with CSS.
Normally, HTML forms can be submitted without involving any JavaScript via the action
and method
attributes on a <form>
. Though it's also common in applications that forms are driven by JavaScript.
In Aurelia, driving form via script can be achieved via submit
event on the form, with the basic usage looking like the following example:
Note that by default, for a <form/>
without a method
attribute, or method
attribute value being equal to GET/get
, using submit.trigger
will call preventDefault()
on the submit
event, which prevents the normally unwanted behavior of html of navigating the page to the URI
of the form. If this behavior is not desired, return true in the method being called, like the following example:
Form validation
Validation is an important part of creating good forms. Aurelia provides a robust validation plugin that allows you to validate forms, create custom validation rules and configure every facet of validation in your Aurelia applications.
To learn about form validation using the Aurelia Validation package, please consult the validation documentation below for details.
Last updated