Any number of arguments can be given. How they're interpreted depends on their types:
Strings can be used to create and insert new elements, set classnames for the current element, and add text to the current element.
The format of a string is: (tag | . class | key[=:]val | key[=:]"val containing spaces")* ('#' text | key[=:])?
So a string may consist of any number of...
tag elements, like h1 or div. These elements are created, added to the current element, and become the new current element for the rest of this $ function execution.
CSS classes prefixed by . characters. These classes will be added to the current element. Optionally, CSS classes can be appended to a tag without a space. So both div.myclass and div .myclass are valid and do the same thing.
Property key/value pairs, like type=password, placeholder="Your name" or data-id=123. When the value contains spaces, it needs to be quoted with either "double quotes", 'single quotes' or backticks. Quotes within quoted values cannot be escaped (see the next rule for a solution). Key/value pairs will be handled according to Property rules below, but with the caveat that values can only be strings.
CSS key/value pairs using two syntaxes:
key:value (no space after colon): The value ends at the next whitespace. Example: m:$3 bg:red r:8pxkey: value; (space after colon): The value continues until a semicolon. Example: box-shadow: 2px 0 6px black; transition: all 0.3s ease;Both forms support CSS shortcuts (see below). You can mix them: m:$3 box-shadow: 0 2px 4px rgba(0,0,0,0.2); bg:$cardBg
The elements must be separated by spaces, except before a .cssClass if it is preceded by either tag or another CSS class.
And a string may end in...
TextNode to the current element. The text ranges til the end of the string, and may contain any characters, including spaces and quotes.$('button text="Click me" click=', () => alert('Clicked!')) or $('input.value=', someUserData, "placeholder=", "Type your stuff"). In case the value is a proxied object, its .value property will be applied reactively without needing to rerender the parent scope.$('div margin-top:', someValueInPx). In case the value is a proxied object, its .value property will be applied reactively without needing to rerender the parent scope.When a function (without arguments nor a return value) is passed in, it will be reactively executed in its own observer scope, preserving the current element. So any $() invocations within this function will add child elements to or set properties on that element. If the function reads observable data, and that data is changed later on, the function we re-execute (after side effects, such as DOM modifications through $, have been cleaned - see also clean).
When an object is passed in, its key-value pairs are used to modify the current element according to the Property rules below, unless the key starts with a $ character, in which case that character is stripped of and the key/value pair is treated as a CSS property, subject to the CSS shortcuts below. In case a value is a proxied object, its .value property will be applied reactively without needing to rerender the parent scope. In most cases, the string notation (key= and key:) is preferred over this object notation, for readability.
When a DOM Node (Element or TextNode) is passed in, it is added as a child to the current element. If the Node is an Element, it becomes the new current element for the rest of this $ function execution.
$('input placeholder=Name') results in <input placeholder="Name">.function it is set as an event listener for the event with the name given by the key. For example: $('button text=Press! click=', () => alert('Clicked!'))`. The event listener will be removed when the current scope is destroyed."value" or "selectedIndex", it is set on the current element as a DOM property instead of an HTML attribute. For example $('checked=', true) would do el.checked = true for the current element.. character, its either added to or removed from the current element as a CSS class, based on the truthiness of the value. So $('.hidden=', isHidden) would toggle the hidden CSS class. This only works if the = is the last character of the string, and the next argument is the value. Its common for the value to be a proxied object, in which case its .value is reactively applied without needing to rerender the parent scope."create", the value will be added as a CSS class to the current element immediately, and then removed right after the browser has finished doing a layout pass. This behavior only triggers when the scope setting the create is the top-level scope being (re-)run. This allows for creation transitions, without triggering the transitions for deeply nested elements being drawn as part of a larger component. The string may also contain multiple dot-separated CSS classes, such as .fade.grow. The initial dot is optional. Alternatively, to allow for more complex transitions, the value may be a function that receives the HTMLElement being created as its only argument. It is only called if this is the top-level element being created in this scope run. See transitions.ts in the Aberdeen source code for some examples."destroy" the value will be used to apply a CSS transition if the current element is later on removed from the DOM and is the top-level element to be removed. This happens as follows: actual removal from the DOM is delayed by 2 seconds, and in the mean-time the value string is added as a CSS class to the element, allowing for a deletion transition. The string may also contain multiple dot-separated CSS classes, such as .fade.shrink. The initial dot is optional. Alternatively, to allow for more complex transitions, the value may be a function that receives the HTMLElement to be removed from the DOM as its only argument. This function may perform any transitions and is then itself responsible for eventually removing the element from the DOM. See transitions.ts in the Aberdeen source code for some examples."bind" a two-way binding between the .value property of the given proxied object, and the current input element (<input>, <select> or <textarea>) is created. This is often used together with {@link ref}, in order to use properties other than .value."text", the value will be appended as a TextNode to the current element. The same can also be done with the # syntax in string arguments, though text= allows additional properties to come after in the same string: $('button text=Hello click=', alert)."html", the value will be added as HTML to the current element. This should only be used in exceptional situations. Beware of XSS! Never use this with untrusted user data.For conciseness, Aberdeen supports some CSS shortcuts when setting CSS properties.
| Shortcut | Expands to |
|---|---|
m, mt, mb, ml, mr |
margin, margin-top, margin-bottom, margin-left, margin-right |
mv, mh |
Vertical (top+bottom) or horizontal (left+right) margins |
p, pt, pb, pl, pr |
padding, padding-top, padding-bottom, padding-left, padding-right |
pv, ph |
Vertical or horizontal padding |
w, h |
width, height |
bg |
background |
fg |
color |
r |
border-radius |
Also, when the value is a string starting with $, it is treated as a reference to a CSS variable, expanding to var(--variableName). For numeric variable names (which can't be used directly as CSS custom property names), Aberdeen prefixes them with m, so $3 expands to var(--m3). This is primarily intended for use with setSpacingCssVars, which initializes spacing variables named 0 through 12 with an exponential spacing scale.
The most inner DOM element that was created (not counting text nodes nor elements created by content functions), or the current element if no new element was created. You should normally not need to use the return value - use this function's DOM manipulation abilities instead. One valid use case is when integrating with non-Aberdeen code that requires a reference to a DOM element.
$('button.secondary.outline text=Submit color:red disabled=', false, 'click=', () => console.log('Clicked!'));
We want to set disabled as a property instead of an attribute, so we must use the key= syntax in order to provide
false as a boolean instead of a string.
let inputElement: Element = $('label text="Click me" input type=checkbox');
// You should usually not touch raw DOM elements, unless when integrating
// with non-Aberdeen code.
console.log('DOM element:', inputElement);
const state = proxy({ count: 0 });
$('div', () => { // Outer element
// This scope re-renders when state.count changes
$(`p#Count is ${state.count}`);
$('button text=Increment click=', () => state.count++);
});
const user = proxy({ name: '' });
$('input placeholder=Name bind=', ref(user, 'name'));
$('h3', () => { // Reactive scope
$(`#Hello ${user.name || 'stranger'}`);
});
const show = proxy(false);
$('button click=', () => show.value = !show.value, () => $(show.value ? '#Hide' : '#Show'));
$(() => { // Reactive scope
if (show.value) {
$('p#Details are visible!');
}
});
const myColor = proxy('red');
$('p text="The color is " text=', myColor, 'click=', () => myColor.value = 'yellow')
// Clicking the text will cause it to change color without recreating the <p> itself
This is often used together with ref, in order to use properties other than .value.
The core function for building reactive user interfaces in Aberdeen. It creates and inserts new DOM elements and sets attributes/properties/event listeners on DOM elements. It does so in a reactive way, meaning that changes will be (mostly) undone when the current scope is destroyed or will be re-execute.