Update docs

This commit is contained in:
Robin Guerrier 2024-10-07 22:29:28 -04:00
parent 604ebdd7fd
commit 9180b7da5e

View File

@ -46,13 +46,32 @@ The value of the `return` attribute is also written as a path. A number of paths
The second segment of the path is the property to return from the object. For example: `"/target/value"` or `"/my-element/textContent"` or `"/event/clientX"`.
For instance, you can add a click event attribute to a div, and return the x coordinate of the mouse on click using using the return attribute like this:
```hoon
;div
=event "/click/get-x-coordinate"
=return "/event/clientX"
;
==
```
- Note: the property name is exactly the same as what you would access on the object in JavaScript, so you will need to use camel case in some situations.
#### Implementing forms
There are two ways to implement forms in %mast. You can either use a %mast `return` attribute to return the values of inputs on event, or you can use the typical `<form>` element API.
To make use of the form API, just add a "/submit/..." `event` attribute on your form element to add a sumbit event listener. If you do this, your shrub will receive a `ui-event` poke on form submit, and the value of each input in the form will be included in the data map of the event poke with each input's `name` attribute as its key.
To make use of the form API, just add a "/submit/..." `event` attribute on your form element to add a submit event listener. If you do this, your shrub will receive a `ui-event` poke on form submit, and the value of each input in the form will be included in the data map of the event poke with each input's `name` attribute as its key.
For example, in your Sail you can implement a form like this:
```hoon
;form(event "/submit/my-form")
;input(name "my-input");
;button: Submit
==
```
#### The key attribute
@ -64,14 +83,49 @@ A `key` is a globally unique value which identifies the element (two distinct el
The attributes `debounce` and `throttle` let you add debouncing and throttling to events when placed on an element with an `event` attribute. These attributes take a number value for their duration in seconds.
For example, you can add debounce to an input that sends its value when the user types:
```hoon
;input
=event "/input/get-value"
=return "/target/value"
=debounce "0.7"
;
==
```
Using throttle, you can make use of rapid-fire events like mousemove:
```hoon
;div
=event "/mousemove/handle-move"
=return "/event/clientX /event/clientY"
=throttle "0.5"
;
==
```
The `js-on-event`, `js-on-add`, and `js-on-delete` events allow you to run arbitrary JavaScript when placed on an element that either has an `event` triggered on it, when the element is added to the DOM through a diff, or deleted through a diff.
For example, with js-on-event you can immediately add a class to an element on an event instead of waiting for an update from your ship:
```hoon
;div
=id "my-id"
=event "/click/js-example"
=js-on-event "document.getElementById('my-id').classList.add('clicked')"
;
==
```
---
### Shrub components
Any mast shrub that you write can also function as a component within some other mast shrub. This lets you split up your interface into composable and reusable building blocks for rendering your shrubs, which each serve as standalone UIs.
Whether your mast shrub exists on the client nested as a component, as a standalone UI, or both simultaneously, within your ship it exists as the same shrub and you do not need to treat it any differently in your code.
To add a shrub component in your Sail, write an element where the name is prefixed with `imp_` followed by the name of your shrub's /imp file. This element also needs to have a text node that encodes the `pith` of the %src dependency that your shrub renders. These component elements can be dynamically added or removed like any other element.
For example:
@ -131,3 +185,131 @@ And the corresponding Sail would look something like this:
==
```
Here is a simple front-end for the diary shrub:
```hoon
/@ ui-event
/@ txt
/@ diary-diff
^- kook:neo
=<
|%
++ state pro/%manx
++ poke (sy %ui-event %rely ~)
++ kids *kids:neo
++ deps
^- deps:neo
%- my
:~ :^ %src & [pro/%diary (sy %diary-diff ~)]
:+ ~ %y (my [[|/%da |] only/%txt ~] ~)
==
++ form
^- form:neo
|_ [=bowl:neo =aeon:neo =pail:neo]
::
++ init
|= pal=(unit pail:neo)
^- (quip card:neo pail:neo)
::
:: initialize the shrub's manx state.
::
`manx/!>((render bowl))
::
++ poke
|= [sud=stud:neo vaz=vase]
^- (quip card:neo pail:neo)
?+ sud !!
::
%ui-event
=/ event !<(ui-event vaz)
::
:: for a ui-event poke, switch over its path,
:: and implement your event handlers.
::
?+ path.event !!
::
:: handling a form submit event that adds a diary entry:
:: get form data from the data.event map by input name,
:: and produce a poke for the diary back-end.
::
[%submit %diary-form ~]
=/ data=@t (~(got by data.event) 'diary-input')
=/ diff=diary-diff [%put-entry now.bowl data]
=/ dest=pith:neo p:(~(got by deps.bowl) %src)
:_ pail
:~ [dest %poke diary-diff/!>(diff)]
==
::
:: handling a button click event that deletes a diary entry:
:: the path contains the id of the entry to delete,
:: which is used to produce a delete poke for the back-end.
::
[%click %delete @ta ~]
=/ id=@da (slav %da i.t.t.path.event)
=/ diff=diary-diff [%del-entry id]
=/ dest=pith:neo p:(~(got by deps.bowl) %src)
:_ pail
:~ [dest %poke diary-diff/!>(diff)]
==
::
==
::
:: this shrub rerenders any time its back-end data changes,
:: e.g. when the above event handlers add or delete entries.
:: simply update your shrub's manx state on %rely,
:: and %mast will take care of syncing the client.
::
%rely
`manx/!>((render bowl))
::
==
--
--
::
|%
::
++ render
|= =bowl:neo
=/ diary-data (get-data bowl)
^- manx
;html
;head;
;body
::
:: this event attribute adds a submit event
:: and it corresponds to the first ui-event handler.
::
;form(event "/submit/diary-form")
;textarea(name "diary-input");
;button: Enter
==
;div
;* %+ turn diary-data
|= [id=@da =txt]
^- manx
;div(key <id>)
;span: {(trip txt)}
::
:: this event attribute adds a click event
:: and it corresponds to the second ui-event handler.
::
;button(event "/click/delete/{<id>}"):"x"
==
==
==
==
::
:: this helper function gets a list of diary entries
:: from the %src dependency back-end.
::
++ get-data
|= =bowl:neo
^- (list [@da txt])
=/ deps (~(got by deps.bowl) %src)
%+ turn ~(tap by kid.q.deps)
|= (pair iota:neo (axal:neo idea:neo))
:- `@da`+.p
!< txt q.pail:(need fil.q)
::
--
```