stimulus-decorators
TypeScript icon, indicating that this package has built-in type declarations

1.2.1 • Public • Published

Stimulus Decorators

Stimulus Decorators is a TypeScript library that extends the Stimulus framework with TypeScript decorators to give you improved IntelliSense and type safety of automatically generated Stimulus controller properties.

Prerequisites

  • Stimulus 3
  • TypeScript

Installation

If you use Yarn package manager.

yarn add stimulus-decorators

If you use npm package manager.

npm install --save stimulus-decorators

Usage

There are several decorators:

@Target decorator

Explicitly define target properties with types using the @Target decorator, and it will automatically add them to the static targets array for your Stimulus controller.

// hello_controller.ts
import { Controller } from '@hotwired/stimulus';
import { Target, TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  @Target outputTarget!: HTMLElement;
  @Target nameTarget!: HTMLInputElement;

  greet() {
    this.outputTarget.textContent = `Hello, ${this.nameTarget.value}!`;
  }
}

Equivalent to:

// hello_controller.js
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  static targets = ['name', 'output'];

  greet() {
    this.outputTarget.textContent = `Hello, ${this.nameTarget.value}!`;
  }
}

@Targets decorator

To get an array of all matching targets in scope, use the @Targets decorator.

// slider_controller.ts
import { Controller } from '@hotwired/stimulus';
import { Targets, TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  @Targets slideTargets!: HTMLElement[];

  connect() {
    this.slideTargets.forEach((element, index) => {
      /* … */
    });
  }
}

Equivalent to:

// slider_controller.js
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  static targets = ['slide'];

  connect() {
    this.slideTargets.forEach((element, index) => {
      /* … */
    });
  }
}

@Value decorator

Explicitly define value properties with types and default values using the @Value decorator, and it will automatically add them to the static values object for your Stimulus controller.

// loader_controller.ts
import { Controller } from '@hotwired/stimulus';
import { Value, TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  @Value(String) urlValue!: string;
  @Value(String) methodValue: string = 'GET';

  connect() {
    fetch(this.urlValue, { method: this.methodValue }).then(/* … */);
  }
}

Equivalent to:

// loader_controller.js
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  static values = {
    url: String,
    method: { type: String, default: 'GET' },
  };

  connect() {
    fetch(this.urlValue, { method: this.methodValue }).then(/* … */);
  }
}

If you'd like to set the type of each value from its type definition, you must use reflect-metadata.

  1. Set "emitDecoratorMetadata": true in your tsconfig.json.
  2. Import reflect-metadata before importing stimulus-decorators (importing reflect-metadata is needed just once).
// loader_controller.ts
import 'reflect-metadata';
import { Controller } from '@hotwired/stimulus';
import { Value, TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  @Value urlValue!: string;
  @Value methodValue: string = 'GET';

  connect() {
    fetch(this.urlValue, { method: this.methodValue }).then(/* … */);
  }
}

@Class decorator

Explicitly define CSS class properties with types using the @Class decorator, and it will automatically add them to the static classes array for your Stimulus controller.

// search_controller.ts
import { Controller } from '@hotwired/stimulus';
import { Class, TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  @Class loadingClass!: string;

  loadResults() {
    this.element.classList.add(this.loadingClass);

    fetch(/* … */);
  }
}

Equivalent to:

// search_controller.js
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  static classes = ['loading'];

  loadResults() {
    this.element.classList.add(this.loadingClass);

    fetch(/* … */);
  }
}

@Classes decorator

To get an array of classes in the corresponding CSS class attribute, use the @Classes decorator.

// search_controller.ts
import { Controller } from '@hotwired/stimulus';
import { Classes, TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  @Classes loadingClasses!: string[];

  loadResults() {
    this.element.classList.add(...this.loadingClasses);

    fetch(/* … */);
  }
}

Equivalent to:

// search_controller.js
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  static classes = ['loading'];

  loadResults() {
    this.element.classList.add(...this.loadingClasses);

    fetch(/* … */);
  }
}

@Outlet decorator

Explicitly define CSS outlet properties with types using the @Outlet decorator, and it will automatically add them to the static outlets array for your Stimulus controller.

import { Controller } from '@hotwired/stimulus';
import { Outlet, TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  @Outlet exampleOutlet!: Controller;

  loadResults() {
    console.log(this.exampleOutlet.element);
  }
}

Equivalent to:

import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  static outlets = ['example'];

  loadResults() {
    console.log(this.exampleOutlet.element);
  }
}

@Outlets decorator

To get an array of outlets in the corresponding CSS class attribute, use the @Outlets decorator.

import { Controller } from '@hotwired/stimulus';
import { Outlets, TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  @Outlets exampleOutlets!: Controller[];

  loadResults() {
    for (const outlet of this.exampleOutlets) {
      console.log(outlet.element);
    }
  }
}

Equivalent to:

import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  static outlets = ['example'];

  loadResults() {
    for (const outlet of this.exampleOutlets) {
      console.log(outlet.element);
    }
  }
}

@TypedController decorator

It is required to use the @TypedController decorator on every Stimulus controller where you use @Target, @Targets, or @Value decorators.

// controller.ts
import { Controller } from '@hotwired/stimulus';
import { TypedController } from 'stimulus-decorators';

@TypedController
export default class extends Controller {
  /* … */
}

License

The project is MIT licensed.

Package Sidebar

Install

npm i stimulus-decorators

Weekly Downloads

0

Version

1.2.1

License

MIT

Unpacked Size

69 kB

Total Files

78

Last publish

Collaborators

  • loicnestler