From 68968b2c6c5f277f9933908437e6503d6cb33178 Mon Sep 17 00:00:00 2001 From: Keith Cirkel Date: Wed, 24 Jun 2020 15:31:44 +0100 Subject: [PATCH 1/3] docs: add convention/anti-pattern around shadowing HTMLElement names --- docs/_guide/anti-patterns.md | 40 +++++++++++++++++++++++++++++++++--- docs/_guide/conventions.md | 2 +- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/docs/_guide/anti-patterns.md b/docs/_guide/anti-patterns.md index 198b6d8f..14340975 100644 --- a/docs/_guide/anti-patterns.md +++ b/docs/_guide/anti-patterns.md @@ -3,9 +3,10 @@ chapter: 9 subtitle: Anti Patterns --- -{% capture discouraged %}

Discouraged

{% endcapture %} - -{% capture encouraged %}

Encouraged

{% endcapture %} +{% capture octx %}{% endcapture %} +{% capture octick %}{% endcapture %} +{% capture discouraged %}

{{ octx }} Discouraged

{% endcapture %} +{% capture encouraged %}

{{ octick }} Encouraged

{% endcapture %} Here are a few common anti-patterns which we've discovered as developers have used Catalyst. We consider these anti-patterns as they're best avoided, because of surprising edge-cases, or simply because there are easier ways to achieve the same goals. @@ -111,6 +112,39 @@ class UserSettingsElement extends HTMLElement { +### Avoid shadowing method names + +When naming a method, you should avoid naming it something that already exists on the `HTMLElement` prototype; as doing so can lead to surprising behaviors. Test out the form below to see what method names are allowed or not: + +
+

I want my method to be called...

+ + + + + +
+ ### Avoid naming methods after events, e.g. `onClick` When you have a method which is only called as an event, it is tempting to name that method based off of the event, e.g. `onClick`, `onInputFocus`, and so on. This name implies a coupling between the event and method, which later refactorings may break. Also names like `onClick` are very close to `onclick` which is already [part of the Element's API](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick). Instead we recommend naming the method after what it does, not how it is called, for example `resetForm`: diff --git a/docs/_guide/conventions.md b/docs/_guide/conventions.md index afa7eb35..e7800127 100644 --- a/docs/_guide/conventions.md +++ b/docs/_guide/conventions.md @@ -34,4 +34,4 @@ Be careful not to go too short! We'd recommend avoiding contracting words such a ### Method names should describe what they do -A good method name, much like a good class name, describes what it does, not how it was invoked. While methods can be given any name, names like `onClick` are best avoided, overly generic names like `toggle` should also be avoided. Just like class names it is a good idea to ask "how" and "what", so for example `showAdmins`, `filterUsers`, `updateURL`. +A good method name, much like a good class name, describes what it does, not how it was invoked. While methods can be given most names, you should avoid names that conflict with existing methods on the `HTMLElement` prototype (more on that in [anti-patterns](/guide/anti-patterns#avoid-shadowing-method-names)). Names like `onClick` are best avoided, overly generic names like `toggle` should also be avoided. Just like class names it is a good idea to ask "how" and "what", so for example `showAdmins`, `filterUsers`, `updateURL`. From fa18fe99fe31d8e23e41314d103c40c826380527 Mon Sep 17 00:00:00 2001 From: Keith Cirkel Date: Wed, 24 Jun 2020 16:54:43 +0100 Subject: [PATCH 2/3] docs: rewrite Your-First-Component Based on user feedback this section has been re-written for a few reasons: - It focusses more on the `@controller` decorator and less on Custom Elements - It repeats (multiple times, including a call-out box) that the class name must consist of two words, as this is something users miss. --- docs/_guide/conventions.md | 2 +- docs/_guide/your-first-component.md | 57 ++++++++++++++++++----------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/docs/_guide/conventions.md b/docs/_guide/conventions.md index e7800127..7e68dd7a 100644 --- a/docs/_guide/conventions.md +++ b/docs/_guide/conventions.md @@ -16,7 +16,7 @@ class UserListElement extends HTMLElement {} ### The best class-names are two word descriptions -Custom elements are required to have a `-` inside the tag name. Catalyst's `@controller` will derive the tag name from the class name - and so as such the class name needs to have at least two capital letters, or to put it another way, it needs to consist of two words. The element name should describe what it does succinctly in two words. Some examples: +Custom elements are required to have a `-` inside the tag name. Catalyst's `@controller` will derive the tag name from the class name - and so as such the class name needs to have at least two capital letters, or to put it another way, it needs to consist of at least two CamelCased words. The element name should describe what it does succinctly in two words. Some examples: - `theme-picker` (`class ThemePickerElement`) - `markdown-toolbar` (`class MarkdownToolbarElement`) diff --git a/docs/_guide/your-first-component.md b/docs/_guide/your-first-component.md index e9ed382a..11862c59 100644 --- a/docs/_guide/your-first-component.md +++ b/docs/_guide/your-first-component.md @@ -3,51 +3,64 @@ subtitle: Building an HTMLElement chapter: 2 --- -Custom Elements allow you to create reusable components that you can declare in HTML, and [progressively enhance](https://en.wikipedia.org/wiki/Progressive_enhancement) within JavaScript. Custom Elements must named with a `-` in the HTML name, and the JS class must `extend HTMLElement`. When the browser connects each element class instance to the DOM node, `connectedCallback` is fired - this is where you can change parts of the element. Here's a basic example: +### Catalyst's `@controller` decorator -```html - - +// This happens automatically within `@controller` +// window.customElements.register('hello-world', HelloWorldElement) ```
+Catalyst will automatically convert the classes name; removing the trailing `Element` suffix and lowercasing all capital letters, separating them with a dash. -Here are the three key elements to remember: +By convention, Catalyst controllers end in `Element`, and Catalyst will strip this for the tag name, but the `Element` suffix is not required - just convention. All examples in this guide use `Element` suffixed names. - - Custom Elements must have a dash in the name. - - The JS class must `extend HTMLElement` - - `connectedCallback` can be used as a life-cycle hook for when the element and class are connected. +
+ + + +
+ +Remember! A class name _must_ include at least two CamelCased words (not including the `Element` suffix). One-word elements will raise exceptions. Example of good names: `UserListElement`, `SubTaskElement`, `PagerContainerElement` -### Catalyst +
+
-Catalyst saves you writing some of this boilerplate, by automatically calling the `customElements.register` code, and by adding ["Actions"](/guide/actions) and ["Targets"](/guide/targets) features described later. If you're using TypeScript with `decorators` support, simply add `@controller` to the top of your class: -```js -@controller +### What does `@controller` do? + +Catalyst components are really just "Custom Elements", they're doing all the heavy lifting. Custom Elements allow you to create reusable components that you can declare in HTML, and [progressively enhance](https://en.wikipedia.org/wiki/Progressive_enhancement) within JavaScript. Custom Elements must named with a `-` in the HTML name, and the JS class must `extend HTMLElement`. When the browser connects each element class instance to the DOM node, `connectedCallback` is fired - this is where you can change parts of the element. Here's a basic example: + +```html + + ``` -
- -Catalyst will automatically convert the classes name; removing the trailing `Element` suffix and lowercasing all capital letters, separating them with a dash. -By convention, Catalyst controllers end in `Element`, and Catalyst will strip this for the tag name, but suffixing `Element` is not required. All examples in this guide use `Element` suffixed names. +The Catalyst version isn't all that different, it's just that we have the `@controller` decorator to save on some of the boilerplate. -#### What about without Decorators? +### What about without TypeScript Decorators? -If you don't want to use decorators, you can simply wrap the class in a call to `controller`: +If you don't want to use TypeScript decorators, you can use `controller` as a regular function, and just pass it your class: ```js controller( From 53fe1f541078cb87ef784fffff1a129529271161 Mon Sep 17 00:00:00 2001 From: Keith Cirkel Date: Wed, 24 Jun 2020 17:15:42 +0100 Subject: [PATCH 3/3] docs: further refine method name form with warnings --- docs/_guide/anti-patterns.md | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/_guide/anti-patterns.md b/docs/_guide/anti-patterns.md index 14340975..a548e708 100644 --- a/docs/_guide/anti-patterns.md +++ b/docs/_guide/anti-patterns.md @@ -117,23 +117,43 @@ class UserSettingsElement extends HTMLElement { When naming a method, you should avoid naming it something that already exists on the `HTMLElement` prototype; as doing so can lead to surprising behaviors. Test out the form below to see what method names are allowed or not:
-

I want my method to be called...

- - + +