Components

Character Counter

A Stimulus controller that counts the number of characters in any input fields.


Installation

  1. Install the package

    Terminal
    $ yarn add @stimulus-components/character-counter
    
  2. Register the controller in your application

    app/javascript/controllers/index.js
    import { Application } from '@hotwired/stimulus'
    import CharacterCounter from '@stimulus-components/character-counter'
    
    const application = Application.start()
    application.register('character-counter', CharacterCounter)
    

Example

Character Counter

There are characters in this textarea.

Usage

app/views/index.html
<div data-controller="character-counter">
  <textarea data-character-counter-target="input"></textarea>

  <p>
    There are
    <strong data-character-counter-target="counter"></strong> characters in this textarea.
  </p>
</div>

You can use it in countdown mode, add the correct value and a maxlength attribute on the input/textarea field:

app/views/index.html
<div data-controller="character-counter" data-character-counter-countdown-value="true">
  <textarea data-character-counter-target="input" maxlength="280"></textarea>

  <p>
    There are
    <strong data-character-counter-target="counter"></strong> characters remaining.
  </p>
</div>

By default, characters are counted as UTF-16 code units, the same unit the browser uses to enforce maxlength. Emojis and other multibyte characters then count as more than one character. Use the count unit value to count Unicode code points, or graphemes so that a composed emoji such as ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ counts as a single character:

app/views/index.html
<div data-controller="character-counter" data-character-counter-count-unit-value="graphemes">
  <textarea data-character-counter-target="input"></textarea>

  <p>
    There are
    <strong data-character-counter-target="counter"></strong> characters in this textarea.
  </p>
</div>

Grapheme counting relies on Intl.Segmenter; on browsers without it, the controller falls back to counting code points. Note that maxlength is still enforced by the browser in code units, so in countdown mode a counter using another unit will not reach zero at the same time as the browser stops accepting input.

Configuration

AttributeDefaultDescriptionOptional
data-character-counter-countdown-valueundefinedActivate the countdown mode.โœ…
data-character-counter-count-unit-valuecode-unitsHow characters are counted: code-units, code-points, graphemes.โœ…

Extending Controller

You can use inheritance to extend the functionality of any Stimulus component:

app/javascript/controllers/character_counter_controller.js
import CharacterCounter from "@stimulus-components/character-counter"

export default class extends CharacterCounter {
  connect() {
    super.connect()
    console.log("Do what you want here.")

    this.count // Will return the number of characters in the input/texterea.
  }
}

This controller will automatically have access to targets defined in the parent class.

If you override the connect, disconnect or any other methods from the parent, you'll want to call super.method() to make sure the parent functionality is executed.