Skip to content

Latest commit

 

History

History
92 lines (65 loc) · 2.61 KB

File metadata and controls

92 lines (65 loc) · 2.61 KB

ember/template-no-builtin-form-components

💼 This rule is enabled in the 📋 template-lint-migration config.

Disallow usage of Ember's built-in <Input> and <Textarea> components. These components use two-way binding to mutate values, which is considered an anti-pattern. Use native HTML <input> and <textarea> elements instead.

Examples

This rule forbids the following:

<template><Input @type="text" @value={{this.name}} /></template>
<template><Textarea @value={{this.body}}></Textarea></template>

This rule allows the following:

<template><input type="text" value={{this.name}} {{on "input" this.handleInput}} /></template>
<template><textarea {{on "input" this.handleInput}}>{{this.body}}</textarea></template>

Migration

Many forms may be simplified by switching to a light one-way data approach.

For example – vanilla JavaScript has everything we need to handle form data, de-sync it from our source data and collect all user input in a single object.

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';

export default class MyComponent extends Component {
  @tracked userInput = {};

  @action
  handleInput(event) {
    const formData = new FormData(event.currentTarget);
    this.userInput = Object.fromEntries(formData.entries());
  }
}
<form {{on 'input' this.handleInput}}>
  <label>
    Name
    <input name='name' />
  </label>
</form>

Another option would is to "control" the field's value by replacing the built-in form component with a native HTML element and binding an event listener to handle user input.

In the following example the initial value of a field is controlled by a local tracked property, which is updated by an event listener.

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';

export default class MyComponent extends Component {
  @tracked name;

  @action
  updateName(event) {
    this.name = event.target.value;
  }
}
<input type='text' value={{this.name}} {{on 'input' this.updateName}} />

Related Rules

References