Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: added custom components #1910

Merged
merged 11 commits into from
Dec 2, 2024
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
---
title: 'quickstart'
sidebar_label: 'Quick Start'
title: "quickstart"
sidebar_label: "Quick Start"
id: quick-start

keywords:
[
quickstart,
Custom Element Basics,
GenesisElement Introduction,
Creating Components,
Component Templates,
First Custom Element,
Getting Started,
Component Initialization,
]
tags:
- quickstart
- GenesisElement
- customElement
- template
- shadowRoot
- Hello World
- My Button
sidebar_position: 3
---

# Quick Start

Let's create a simple web component using Genesis. There are three parts that make up a component: the HTML template, the CSS styles and the component logic. Web components can vary in complexity, from a simple button to a very detailed interactive experience.
Let's create a simple web component using Genesis. There are three parts that make up a component: the _HTML template_, the _CSS styles_ and the _component logic_. Web components can vary in complexity, from a simple button to a very detailed interactive experience.

## Create Custom Element

Start by importing all necessary parts:

```typescript
import { css, customElement, GenesisElement, html } from '@genesislcap/web-core';
import {
css,
customElement,
GenesisElement,
html,
} from "@genesislcap/web-core";
```

```typescript
Expand Down Expand Up @@ -45,17 +69,42 @@ We’ve created a custom component called `<my-button>`, which currently display

:::important

Like web Components, Genesis Elements are required to include a hyphen (-) in their name in order to avoid conflicts with native HTML elements and to provide a way to namespace components from various libraries.
Like web Components, Genesis Elements are required to include a hyphen (-) in their name in order to avoid conflicts with native HTML elements.

:::

## Add it to your project

:::note
After defining your custom component, you need to import it somewhere in your application's code to ensure it gets registered. If you are using a project built generated from Genesis Create or `genx` then a good place for it to go is the same file that contains `rapidDesignSystem.provideDesignSystem()`.
:::

Let's say we import `MyButton` into a `hello-world.js` file. This ensures `MyButton` will be registered with the browser, allowing you to use the `<my-button>` element in your HTML.

```typescript
import "./MyButton";

...

MyButton;
```

Now it can be added in your HTML this way:

```typescript
<script type="module" src="path/to/hello-world.js"></script>
<my-button label="Cancel"></my-button>
```

> In this example, we created a custom web component using `GenesisElement`. We defined a button template and added a `label` attribute using the `@attr` decorator, allowing the button text to be customized via HTML. We implemented the `labelChanged` method, which is automatically called whenever the `label` value changes. The template dynamically updates with the new value, ensuring the button remains responsive to changes in its attributes.

## Add an Attribute

We can add an `attr` decorator which allows us to link a class property to an HTML attribute, ensuring that changes in the attribute are automatically reflected in the JavaScript property, and vice versa, allowing for clean and declarative state management of custom elements.

You can define a default value for an attribute directly within the class definition. This ensures that if no value is provided, the attribute will fall back to the specified default.

Let's declare an attribute called **_name_** and then change that value to see it reflected:
Let's declare an attribute called **_label_** and then change that value to see it reflected:

```typescript
import { attr, css, customElement, GenesisElement, html } from '@genesislcap/web-core';
Expand All @@ -75,28 +124,18 @@ export class MyButton extends GenesisElement {
Now let's update the template to display the value:

```typescript

const template = html`<button>${x => x.label}</button>`
const template = html`<button>${(x) => x.label}</button>`;
```

## Add it to your project

:::note
After defining your custom component, you need to import it somewhere in your application's code to ensure it gets registered.
:::

By importing the file, `MyButton` will be registered with the browser, allowing you to use the `<my-button>` element in your HTML.

```typescript
import './MyButton';
```
## Typed Templates

Templates can be strongly typed to ensure they align with the data model they are rendering. In TypeScript, you specify the type directly within the template declaration using the syntax `html<Type>`. This approach provides better type safety and ensures that the data passed into the template matches the expected structure of the associated component or model.

Now it can be added in your HTML this way:
For instance, if you have a `MyButton` component, you can type its template like this:

```typescript
<script type="module" src="path/to/hello-world.js"></script>
<my-button label="Cancel"></my-button>
```
import { html } from "@genesislcap/web-core";

>In this example, we created a custom web component using `GenesisElement`. We defined a button template and added a label attribute using the `@attr` decorator, allowing the button text to be customized via HTML. We implemented the `labelChanged` method, which is automatically called whenever the label value changes. The template dynamically updates with the new value, ensuring the button remains responsive to changes in its attributes.
const template = html<MyButton>`<button>Click Me</button>`;
```
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
---
title: 'Lifecycle'
sidebar_label: 'Lifecycle'
id: lifecycle
title: "Lifecycle"
sidebar_label: "Lifecycle"
id: "lifecycle"

keywords:
[
connectedCallback,
disconnectedCallback,
propertyNameChanged,
DOM Interaction,
Reactive Updates,
Component Lifecycle,
Initialization and Cleanup,
Lifecycle Methods,
]

tags:
- connectedCallback
- disconnectedCallback
- attributeChangedCallback
- Reactive Lifecycle
- Lifecycle Events

sidebar_position: 3
---
Expand All @@ -14,40 +33,44 @@ Here are some lifecycle methods that we have access to through `GenesisElement`:

### Connected & Disconnected

`connectedCallback` lifecycle runs when component is added to DOM - perfect time for setup.
`connectedCallback` lifecycle runs when a component is added to the DOM - perfect time for setup.

`disconnectedCallback` lifecycle runs when component is removed from DOM - perfect time for cleanup.
`disconnectedCallback` lifecycle runs when a component is removed from the DOM - perfect time for cleanup.

```typescript
import { attr, css, customElement, GenesisElement, html } from '@genesislcap/web-core';
import {
attr,
customElement,
GenesisElement,
html,
} from "@genesislcap/web-core";

const template = html`<button>Click Me</button>`;
const template = html<MyButton>`<button>Click Me</button>`;

@customElement({
name: 'my-button',
name: "my-button",
template,
styles,
})

export class MyButton extends GenesisElement {
@attr label: string = "Submit";
@attr disabled: boolean = false;

connectedCallback() {
super.connectedCallback(); // Let GenesisElement do its setup first
console.log('Button is now connected to the DOM and ready for interaction');
}

disconnectedCallback() {
super.disconnectedCallback(); // Let GenesisElement do its cleanup first
console.log('Button is no longer interactive and removed from DOM');
}
@attr label: string = "Submit";
@attr disabled: boolean = false;

connectedCallback() {
super.connectedCallback(); // Let GenesisElement do its setup first
console.log("Button is now connected to the DOM and ready for interaction");
}

disconnectedCallback() {
super.disconnectedCallback(); // Let GenesisElement do its cleanup first
console.log("Button is no longer interactive and removed from DOM");
}
}
```

### Changed Callbacks

Changed Callback lifecycle runs when attributes/properties update - handle state changes. The name varies depending on the name of the attribute.
Changed Callback lifecycle runs when **attributes/properties** update - handle state changes. The name varies depending on the name of the attribute.
matteematt marked this conversation as resolved.
Show resolved Hide resolved

:::note

Expand All @@ -56,23 +79,27 @@ In the following example you'll notice we have not included the `connectedCallba
:::

```typescript
import { attr, css, customElement, GenesisElement, html } from '@genesislcap/web-core';
import {
attr,
customElement,
GenesisElement,
html,
} from "@genesislcap/web-core";

const template = html`<button>Click Me</button>`;
const template = html<MyButton>`<button>Click Me</button>`;

@customElement({
name: 'my-button',
name: "my-button",
template,
styles,
})

export class MyButton extends GenesisElement {
@attr label: string = "Submit";
@attr disabled: boolean = false;
@attr label: string = "Submit";
@attr disabled: boolean = false;

labelChanged(oldValue, newValue) {
console.log(`Button text changed from ${oldValue} to ${newValue}`);
}
labelChanged(oldValue, newValue) {
console.log(`Button text changed from ${oldValue} to ${newValue}`);
}
}
```

Expand Down
Loading