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 component.
import { Input } from '@ember/component';
<template>
  <label for="user-question">Ask a question about Ember:</label>
  <Input
    id="user-question"
    @type="text"
    @value="How do text fields work?"
  />
</template>When Ember renders this component, 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,
- You can nest the input inside the label.
import Component from "@glimmer/component";
import { Input } from '@ember/component';
import { tracked } from '@glimmer/tracking';
export default class Example extends Component {
  @tracked userQuestion = '';
  <template>
    <label>
      Ask a question about Ember:
      <Input
        @type="text"
        @value={{this.userQuestion}}
      />
    </label>
  </template>
}- You can create an ID (globally unique within the webpage), then associate the label to the input with forattribute andidattribute.
import Component from "@glimmer/component";
import { Input } from '@ember/component';
import { tracked } from '@glimmer/tracking';
export default class Example extends Component {
  @tracked userQuestion = '';
  myUniqueId = "this-is-a-unique-id";
  <template>
    <label for={{this.myUniqueId}}>
      Ask a question about Ember:
    </label>
    <Input
      id={{this.myUniqueId}}
      @type="text"
      @value={{this.userQuestion}}
    />
  </template>
}- You can use the aria-labelattribute to label the input with a string that is visually hidden but still available to assistive technology.
import Component from "@glimmer/component";
import { Input } from '@ember/component';
import { tracked } from '@glimmer/tracking';
export default class Example extends Component {
  @tracked userQuestion = '';
  <template>
    <Input
      aria-label="Ask a question about Ember"
      @type="text"
      @value={{this.userQuestion}}
    />
  </template>
}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:
import { Input } from '@ember/component';
<template>
  <Input aria-labelledby="button-search" />
  <button id="button-search" type="button">Search</button>
</template>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.
import Component from "@glimmer/component";
import { Input } from '@ember/component';
import { tracked } from '@glimmer/tracking';
export default class Example extends Component {
  @tracked isReadOnly = true;
  @tracked name = 'Tomster';
  <template>
    <label for="input-name">Name:</label>
    <Input
      id="input-name"
      @value={{this.name}}
      disabled={{this.isReadOnly}}
      maxlength="50"
    />
  </template>
}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
- @type
- @value
Actions
We recommend using the {{on}} modifier to call an action on specific events such as the input event.
import Component from "@glimmer/component";
import { Input } from '@ember/component';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';
export default class Example extends Component {
  @tracked name = '';
  validateName = (inputValue) => {
    // Name validation here
  };
  <template>
    <label for="input-name">Name:</label>
    <Input
      id="input-name"
      @value={{this.name}}
      {{on "input" this.validateName}}
    />
  </template>
}Learn more about the {{on}} modifier.
Lastly, Ember also provides custom input events @enter, @insert-newline 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,
import Component from "@glimmer/component";
import { Input } from '@ember/component';
import onKey from 'ember-keyboard/modifiers/on-key';
export default class Example extends Component {
  doSomething = () => {
    alert('something');
  };
  doSomethingElse = () => {
    alert('something else');
  };
  <template>
    {{!-- Before --}}
    <Input
      @enter={{this.doSomething}}
      @escape-press={{this.doSomethingElse}}
    />
    {{!-- After --}}
    <Input
      {{onKey "Enter" this.doSomething}}
      {{onKey "Escape" this.doSomethingElse event="keydown"}}
    />
  </template>
}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.
import Component from "@glimmer/component";
import { Input } from '@ember/component';
import { tracked } from '@glimmer/tracking';
export default class Example extends Component {
  @tracked isAdmin = false;
  <template>
    <label for="admin-checkbox">Is Admin?</label>
    <Input
      id="admin-checkbox"
      @type="checkbox"
      @checked={{this.isAdmin}}
    />
  </template>
}To call an action on specific events, use the {{on}} modifier:
import Component from "@glimmer/component";
import { Input } from '@ember/component';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';
export default class Example extends Component {
  @tracked isAdmin = false;
  validateRole = () => {
    // validate logic
  };
  <template>
    <label for="admin-checkbox">Is Admin?</label>
    <Input
      id="admin-checkbox"
      @type="checkbox"
      @checked={{this.isAdmin}}
      {{on "input" this.validateRole}}
    />
  </template>
  }<Textarea>  
The following example shows how to bind this.userComment to a text area's value.
import Component from "@glimmer/component";
import { Textarea } from '@ember/component';
import { tracked } from '@glimmer/tracking';
export default class Example extends Component {
  @tracked userComment = '';
  <template>
    <label for="user-comment">Comment:</label>
    <Textarea
      id="user-comment"
      @value={{this.userComment}}
      rows="6"
      cols="80"
    />
  </template>
}Setting attributes on <Textarea>  
With the exception of @value argument, you can use any attribute that <textarea> natively supports.