Skip to content

Commit

Permalink
feat: BaseController - An extendable controller that provides common …
Browse files Browse the repository at this point in the history
…useful behaviours and properties for all controllers that use it as a base
  • Loading branch information
Sub-Xaero committed Apr 24, 2021
1 parent 5c62e02 commit a12b101
Show file tree
Hide file tree
Showing 16 changed files with 101 additions and 10 deletions.
1 change: 1 addition & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { BaseController } from "./utilities/base_controller";
export { AnchorSpyController } from "./controllers/anchor_spy_controller";
export { AppearanceController } from "./controllers/utility/appearance_controller";
export { AsyncBlockController } from "./controllers/async_block_controller";
Expand Down
2 changes: 1 addition & 1 deletion dist/index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/stimulus-library.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/stimulus-library.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/stimulus-library.modern.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/stimulus-library.modern.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/stimulus-library.module.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/stimulus-library.module.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/stimulus-library.umd.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/stimulus-library.umd.js.map

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions dist/utilities/base_controller.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { Context, Controller } from "stimulus";
export declare class BaseController extends Controller {
constructor(context: Context);
get el(): HTMLElement;
get isTurboPreview(): boolean;
get isTurbolinksPreview(): boolean;
get csrfToken(): string | null;
metaValue(name: string): string | null;
dispatch(element: HTMLElement, eventName: string, options?: CustomEventInit): void;
log(functionName: string, args?: {}): void;
logEvent(eventName: string, event: CustomEvent, element: HTMLElement): void;
Expand Down
2 changes: 1 addition & 1 deletion dist/utilities/base_controller.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 60 additions & 0 deletions docs/docs/controllers/base_controller.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
id: BaseController
title: BaseController
---


## Purpose

Provide common utilities and base functionality for all Stimulus controllers that extend this controller.


## Properties

This controller provides the following properties to sub-classes.

| Name | Purpose | Return Value |
| --- | --- | --- |
| `el` | For Typescript projects, provides a wrapper around `this.element` typecast to `HTMLElement` so that type-hinting correctly works for all DOM APIs | The controller root element, as an `HTMLElement` |
| `isTurboPreview` | Whether or not the document is currently displaying a preview from the Hotwire/Turbo cache https://turbo.hotwire.dev/handbook/building#detecting-when-a-preview-is-visible. Also works with legacy Turbolinks | `boolean` |
| `isTurbolinksPreview` | Alias for `isTurboPreview`, both methods work for both Turbolinks and Hotwire | `boolean` |
| `csrfToken` | The current Rails CSRF token, taken from the `<meta>` tag Rails inserts into the document head, if present. | `string` or `null` |

## Methods

This controller provides the following methods to sub-classes.

| Name | Parameters | Purpose | Default |
| --- | --- | --- | --- |
| `dispatch` | | Dispatch a custom event | |
| | `element` | The element to dispatch the event on | |
| | `eventName` | The fully qualified name of the event. Usually follows the format `controller-identifier:event` | |
| | `options` (Optional) | The options to initialize the event with. See the options `eventInit` accepts: https://developer.mozilla.org/en-US/docs/Web/API/Event/Event | `{ bubbles: true, cancellable: true, details: { element: this.element } }` |

| Name | Parameters | Purpose | Return value |
| --- | --- | --- | --- |
| `metaValue` | | Fetch a value from a `<meta>` tag in the `<head>` of the document. | `string` or `null` |
| | `name` | The `name` attribute of the `meta` tag to fetch the value of | |


## Side Effects / Inherited Behaviour

If [debug mode](/docs/debugging) is enabled, any controller that extends BaseController controller will automatically log calls to any actions or methods, and events dispatched with `this.dispatch`.

If there are any getters, setters, methods or properties that should not be logged, you should name them with an underscore prefix i.e. `_foo() {}`, or `_bar = "baz"` to indicate that they are private methods.


## How to Use

```typescript
import {BaseController} from "stimulus-library";

export default class extends BaseController {
// ...

foo() {
this.dispatch( this.el, "my-controller:something-happened", { bubbles: true, cancellable: true, detail: { element: this.el, data: 'thing' } } )
}

}
```
5 changes: 5 additions & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ module.exports = {
"controllers/LazyBlockController",
"controllers/TeleportController",
"controllers/ToggleClassController",
],
},
{
"Extendable Controllers": [
"controllers/BaseController",
]
},
{
Expand Down
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Utilities
export {BaseController} from "./utilities/base_controller";

// Controllers
export {AnchorSpyController} from "./controllers/anchor_spy_controller";
export {AppearanceController} from "./controllers/utility/appearance_controller";
export {AsyncBlockController} from "./controllers/async_block_controller";
Expand Down
17 changes: 17 additions & 0 deletions src/utilities/base_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ export class BaseController extends Controller {
return this.element as HTMLElement;
}

get isTurboPreview(): boolean {
return document.documentElement.hasAttribute('data-turbo-preview') || document.documentElement.hasAttribute('data-turbolinks-preview');
}

get isTurbolinksPreview(): boolean {
return this.isTurboPreview;
}

get csrfToken(): string | null {
return this.metaValue('csrf-token');
}

metaValue(name: string): string | null {
const element = document.head.querySelector(`meta[name="${name}"]`);
return element?.getAttribute('content') || null;
}

dispatch(element: HTMLElement, eventName: string, options: CustomEventInit = {}) {
let mergedOptions = Object.assign({}, {bubbles: true, cancelable: true, detail: {target: element}}, options);
if (!!mergedOptions.detail.target) {
Expand Down

0 comments on commit a12b101

Please sign in to comment.