Old Guides - You are viewing the guides for Ember v3.18.0. VIEW v3.24.0
Edit Page

Built-in Components


Out of the box, Ember provides 2 components for building a form:

These components are similar in HTML markup to the native <input> or <textarea> elements. In contrast to the native elements, <Input> and <Textarea> automatically update the state of their bound values.

<Input>

We mentioned that the built-in components are similar in HTML markup to their native counterparts. What does this mean?

Consider the following example in a template file.

<label for="user-question">Ask a question about Ember:</label>
<Input
  @id="user-question"
  @type="text"
  @value="How do text fields work?"
/>

When Ember renders this template, you will see the following HTML code:

<label for="user-question">Ask a question about Ember:</label>
<input id="user-question" type="text" value="How do text fields work?" />

Ways to associate labels and inputs

Every input should be associated with a label. In HTML, there are a few ways to do this. With the built-in <Input> component,

  1. You can nest the input inside the label.

    <label>
     Ask a question about Ember:
    
     <Input
       @type="text"
       @value={{this.userQuestion}}
     />
    </label>
    
  2. You can create an ID (globally unique within the webpage), then associate the label to the input with for attribute and @id argument.

    <label for={{this.myUniqueId}}>
     Ask a question about Ember:
    </label>
    
    <Input
     @id={{this.myUniqueId}}
     @type="text"
     @value={{this.userQuestion}}
    />
    
  3. You can use the aria-label attribute to label the input with a string that is visually hidden but still available to assistive technology.

    <Input
     aria-label="Ask a question about Ember"
     @type="text"
     @value={{this.userQuestion}}
    />
    

While it is more appropriate to use the <label> element, the aria-label attribute can be used in instances where visible text content is not possible.

Setting attributes on <Input>

With a few exceptions, you can pass input attributes as attributes (i.e. do not prepend @) to the <Input> component.

For example, the aria-labelledby attribute may be useful if you have a search input. The search button can serve as the label for the input element:

<Input aria-labelledby="button-search" />
<button id="button-search" type="button">Search</button>

If an attribute is set to a quoted string ("button-search" in the prior example), its value will be set directly on the element.

You can also bind the attribute value to a property that you own. In the next example, the disabled attribute is bound to the value of isReadOnly in the current context.

<label for="input-name">Name:</label>
<Input
  @id="input-name"
  @value={{this.name}}
  disabled={{this.isReadOnly}}
  maxlength="50"
/>

Recall that there were a few exceptions. The following input attributes must be passed as arguments (i.e. do prepend @) to the <Input> component:

  • @checked
  • @id
  • @type
  • @value

Actions

Starting with Ember Octane, we recommend using the {{on}} modifier to call an action on specific events such as the input event.

<label for="input-name">Name:</label>
<Input
  @id="input-name"
  @value={{this.name}}
  {{on "input" this.validateName}}
/>

The event name (e.g. "focusout", "input", "keydown") always follows the casing that the HTML standard uses.

Tomster says...

We mention event arguments below to help with Octane upgrade. Due to a bug, event arguments do not work in versions 3.15 and 3.17-3.19. Please consider using the {{on}} modifier or upgrading to the next LTS (3.16 or 3.20).

For backwards compatibility with earlier versions of Ember, it is possible to call an action by passing an event argument.

<label for="input-name">Name:</label>
<Input
  @id="input-name"
  @value={{this.name}}
  @input={{this.validateName}}
/>

The argument name is always dasherized (e.g. @focus-out, @input, @key-down). To minimize confusion, we recommend that you use the {{on}} modifier. (Learn more about the {{on}} modifier.)

Lastly, Ember also provides custom input events @enter and @escape-press. These events do not exist on native input elements, but you may find them to be useful for handling keyboard interactions.

The modern, Octane-style way to handle keyboard events is to write a modifier to separate concerns: The component manages the state, while the modifier manages interactions with the DOM. Your action will receive an actual event object.

There are community-made addons to help manage keyboard events. For example, with ember-keyboard, you can write,

{{!-- Before --}}
<Input
  @enter={{this.doSomething}}
  @escape-press={{this.doSomethingElse}}
/>

{{!-- After --}}
<Input
  {{on-key "Enter" this.doSomething}}
  {{on-key "Escape" this.doSomethingElse event="keydown"}}
/>

Note, the keydown event was used for Escape because keypress is deprecated.

Checkboxes

You can use the <Input> component to create a checkbox. Set @type to the string "checkbox", and use @checked instead of @value.

<label for="admin-checkbox">Is Admin?</label>
<Input
  @id="admin-checkbox"
  @type="checkbox"
  @checked={{this.isAdmin}}
/>

To call an action on specific events, use the {{on}} modifier:

<label for="admin-checkbox">Is Admin?</label>
<Input
  @id="admin-checkbox"
  @type="checkbox"
  @checked={{this.isAdmin}}
  {{on "input" this.validateRole}}
/>

<Textarea>

The following example shows how to bind this.userComment to a text area's value.

<label for="user-comment">Comment:</label>
<Textarea
  @id="user-comment"
  @value={{this.userComment}}
  rows="6"
  cols="80"
/>

Setting attributes on <Textarea>

With the exception of @value argument, you can use any attribute that <textarea> natively supports.

Binding dynamic attribute

You might need to bind a property dynamically to an input if you're building a flexible form, for example. To achieve this you need to use the {{get}} and {{mut}} in conjunction like shown in the following example:

<label for="input-name">Name:</label>
<Input
  @id="input-name"
  @value={{mut (get this.person this.field)}}
/>

The {{get}} helper allows you to dynamically specify which property to bind, while the {{mut}} helper allows the binding to be updated from the input. See the respective helper documentation for more detail: {{get}} and {{mut}}.