1.2.1 • Published 7 months ago

stimulus-decorators v1.2.1

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

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.

1.2.0

7 months ago

1.2.1

7 months ago

1.1.1

9 months ago

1.1.0

9 months ago