Skip to content

Commit

Permalink
element doc and update values and state docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ECorreia45 committed Oct 18, 2024
1 parent 7fcd380 commit 218e055
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 7 deletions.
4 changes: 4 additions & 0 deletions docs/documentation/state/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ state: <T>(initialValue: T, sub?: StateSubscriber) =>
readonly[(StateGetter<T>, StateSetter<T>, StateUnSubscriber)]
```

State, when used in templates allow the DOM to only update where needed.

Markup templates do no traverse the DOM to check for updates and the state itself will only notify the template after verifying that the data has changed with a shallow comparison. That allows the DOM to only update when and where necessary.

### Input

You can provide an `initialValue` to start the state as well as a `StateSubscriber` which is function that will get called every time the state changes.
Expand Down
28 changes: 28 additions & 0 deletions docs/documentation/templating/values.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,34 @@ const type = 'button'
html`<button type="${type}">${label}</button>`
```

### Node

Markup templates work seamlessly with DOM nodes and this ability allows you to migrate any vanilla JavaScript solution easily to Markup templates.

You can inject any Node directly in the template and they will be rendered just fine.

```javascript
const button = document.createElement('button')
button.textContent = 'click me'
button.type = 'button'

html`${button}`.render(document.body)
```

### HTMLTemplate

Another thing you can inject in the templates for powerful compositions are the template instances themselves.

```javascript
const button = html`<button type="button">click me</button>`

html`${button}`.render(document.body)
```

This simple capability allows you to declare, store, and move around templates like you would with any data. This behavior resembles working with nodes in vanilla JavaScript and makes it easier to share and compose templates to build complex views.

Another benefits of composing templates is the fact that each template are tracked separately allowing only the part of the DOM to update when needed.

### Arrays

Injected arrays will have their items rendered as they are. This makes it super easy to render lists in general and comes handy with data handling.
Expand Down
74 changes: 74 additions & 0 deletions docs/documentation/utilities/element.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,77 @@ layout: document
---

## Element Utility

```typescript
interface ElementOptions<A> {
attributes?: A
textContent?: string
htmlContent?: string
ns?: 'http://www.w3.org/1999/xhtml' | 'http://www.w3.org/2000/svg'
}

type element = <A>(tagName: string, options?: ElementOptions<A>) => Element
```
The `element` attribute is simply a function that allows you to create DOM elements in one call.
Normally, when working with DOM elements we create and piece them together after.
```javascript
const button = document.createElement('button')
button.type = 'button'
button.textContent = 'click me'

button.addEventListener('click', () => {
console.log('clicked')
})
```

This is a lot of steps to create a simple button. Here is the same thing using `element`:

```javascript
const button = element('button', {
textContent: 'click me',
attributes: {
type: 'button',
onclick: () => {
console.log('clicked')
},
},
})
```

The `element` uses `addEventListener` behind the scenes and handles non-primitive values for you by easily detecting web component elements.

### Web components

The best part of working with `element` is with web components. It will handle all non-primitive props to ensure the web components get data as they should.

```javascript
const item = element('todo-item', {
attributes: {
data: {
id: crypto.randomUUID(),
name: 'buy groceries',
status: 'pending',
dateCreated: new Date(),
},
},
})
```

### SVG elements

To create SVG elements you can specify the `ns` option with the value of `http://www.w3.org/2000/svg` and that will give you any SVG element.

```javascript
const rect = element('rect', {
ns: 'http://www.w3.org/2000/svg',
attributes: {
x: 10,
y: 10,
width: 100,
height: 100,
},
})
```
18 changes: 11 additions & 7 deletions docs/documentation/utilities/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Utilities are just functions that rendered in template and that need to be calle

The power with working with states and template comes when you start defining your own utilities. Let's look at a quick example:

We have a common scenario where we have a input value that uses state and we need to display a certain message whether the value is valid or not.
We have a common scenario where we have a input field that uses state and we need to display a certain message whether the value is valid or not.

```javascript
const [value, updateValue] = state(null)
Expand Down Expand Up @@ -67,7 +67,9 @@ html`
`.render(document.body)
```

Now I also realize that i want to mark the field red when the input is bad and that relies on the same logic. So, i can extract that logic into a function for reusability:
This is not bad but logic in the template takes space and lots of them makes template hard to read.

I realized that i want to mark the field red when the input is invalid and that relies on the same logic we have in the function. So, i can extract that logic into a function for reusability:

```javascript
const [value, updateValue] = state(null)
Expand Down Expand Up @@ -117,9 +119,11 @@ html`
`.render(document.body)
```

This ability to just create and compose functions to handle everything is what further makes templating easy and fun to do.
You can see that we have functions that handle different logic composing them for even more complex logic dependent on the state.

This ability to just create and compose functions to handle everything is what further makes templating easy and fun in Markup.

We can further things up by introducing a utility for handling form values that we can use with multiple form fields at once.
We can further things up by wrapping everything in a reusable utility for handling form input values of any kind that we can use with multiple form fields.

```javascript
const formFieldValue = (pattern) => {
Expand Down Expand Up @@ -163,7 +167,7 @@ html`
style="color: ${name.color}"
/>
${when(
name.pristineOrValid,
name.isPristineOrValid,
html`<p>Your name</p>`,
html`<p style="color: ${name.color}">
Name must be at least 3 characters
Expand All @@ -177,11 +181,11 @@ html`
style="color: ${email.color}"
/>
${when(
email.pristineOrValid,
email.isPristineOrValid,
html`<p>Your email</p>`,
html`<p style="color: ${email.color}">Email is not valid</p>`
)}
`.render(document.body)
```

As you can see, when it comes to reactivity, Markup relies heavily and solely on functions to get the job done. This function oriented nature makes templating simple and somehow familiar to anyone.
As you can see, when it comes to reactivity, Markup relies heavily and solely on functions to get the job done. This function oriented nature makes templating simple and somehow familiar to anyone. Give it a try!

0 comments on commit 218e055

Please sign in to comment.