Directives appear as attributes in your HTML within the template for the element. Fudgel comes with several directives to handle common use cases. Directives are split into structural directives, which affect adding and removing DOM elements, and general directives, which leaves the DOM structure intact.
{{ }}
Text nodes and attributes may use a syntax similar to
Mustache, using double
braces. The content within will be evaluated as JavaScript and
the value that is returned will be inserted in place of the
braces. Below, extraClasses
refers to the
controller's property and the content within the braces will be
updated whenever the referenced variable changes. Learn more
about the types of
expressions you can use in
Fudgel.
When you use a boolean value as the entire attribute value, such
as in the next example, the attribute will be set to an empty
string if true
and removed if false
.
This is useful for attributes that are either present or not,
such as disabled
, checked
, and
readonly
.
.
If you need to pass more complicated data and if the element supports it, you can assign properties directly to the element. Again, if the referenced variables change, the property will automatically be updated. This is done by prefixing the property name with a dot and changing the name to kebab-case (hyphenated). Properties leverage expressions to get values.
@
Event handlers are bound with a @
-prefixed
attribute. The event is available as $event
.
Expressions are used to find what
function to call.
Event handlers can also have modifiers, indicating what should be done with the event. These are separated by a period and appear after the event name, always in kebab-case.
capture
- Dispatch the event to the registered
listener before dispatching to any event targets beneath it
in the DOM tree.
document
- Bind the event to the document.once
- Invoke the listener at most once.outside
- Bind the event to the document and
only fire when there's a click outside of the targeted
element.
passive
- Signifies that this event is passive
and the developer will not call preventDefault
on the event, allowing the engine to tweak how the event is
processed.
prevent
- Calls preventDefault
on
the event.
self
- Only fires the event when the click is
on the target element.
stop
- Calls stopPropagation
on
the event.
window
- Bind the event to the window.You can also fire events only when certain key combinations are pressed.
alt
- The alt key must be pressed.ctrl
- The control key must be pressed.meta
- The meta key must be pressed, which is
the same as the Command key on Mac or Super key on Windows.
shift
- The shift key must be pressed.exact
- The exact key combination must be
pressed. This means using
keypress.ctrl.exact
only fires when a
control-key combination is pressed but will not fire if the
shift key is also pressed.
Finally, any other event modifier will be treated as a key
value. This means using keypress.a
will only fire
when the "a" key is pressed. Key values are listed on
MDN's Keyboard Event Key Values page. Make sure to use all lowercase and kebab-case names, such as
keypress.enter
and
keypress.arrow-left
.
Some keys are difficult to represent as HTML attributes, so you
can use their ASCII values or code point values, such as
keypress.code-32
for space (hex 0x20, ASCII code
point 32) and keypress.code-252
for ΓΌ.
*if
Conditionally display an element with *if
. This
will automatically be updated if using a property on your
controller. If the condition is false, the DOM element is
removed. When it is true, the DOM element is put back.
Showing {{username}} an unknown user
*repeat
Repeating a chunk of HTML a number of times is very easy. You can use a fixed number or execute code to find the number.
5 stars: *
Some stars: *
*for
Iterating across an object, array, set, map, or any other
iterable is also possible, plus this also updates when the
property on your controller is updated. The key and value are
assigned to key
and value
.
You can rename key
and value
to suit
your needs. Also, nested scopes inherit from each other, exactly
how you think they should. Scopes are discussed more on the
Expressions page.
{{username}}:
#class
There's a directive that makes it much easier to add and remove
classes dynamically. The #class
directive allows
you to define class names to add or remove if the associated
value is truthy or falsy. It accepts an object where the
property names are the class names and the property values are
the conditions.
5 }">N: {{n}}
#ref
The controller might need to access a DOM element directly. To
make this very easy, add the #ref
attribute to the
element. This will assign the element to the controller's
property with the same name as the attribute.
Technically, with this simple example, you could use
inputField.focus()
directly without a controller.
This example just makes it more clear that the property is added
to the controller.
You are welcome to add your own directives. There are three categories of directives: structural, prefixed, and exact matches.
Structural directives add and remove DOM elements where the
structural directive is placed. These start with *
,
such as *for
and *if
.
Prefixed directives start with a single character and are used
to match all attributes that start with that character. Fudgel
comes with .
to set properties and @
to bind events.
Exact matches will match the entire attribute name. The
convention for these is to have them start with a hash, such as
the built-in #ref
directive.
For all three types, you add a directive using
addDirective()
.
Your custom directive function must perform whatever manipulation in the DOM that is necessary. For structural directives, a comment is automatically added just before the element with the directive; this is an anchor point you can use for adding or removing elements.
If you'd like to deal with the attribute value in a way that's
similar to how Fudgel works with other property lookups, you
will be very interested in parse()
and
getScope()
, exported as part of the
utilities.