Attribute

Attribute can have value of various data types.

  1. For static attribute, use value of string, number or boolean. true adds attribute with empty string while false will remove attribute.
  2. For dynamic attribute, use value of Supplier type that contains string, number or boolean.

attribute.js :

import Component from "./node_modules/@xylem-js/xylem-js/dom/Component.js";
import createStore from "./node_modules/@xylem-js/xylem-js/core/createStore.js";
import mountComponent from "./node_modules/@xylem-js/xylem-js/dom/mountComponent.js";
import parseHTML from "./node_modules/@xylem-js/xylem-js/dom/parseHTML.js";

class Attribute extends Component
{
	build()
	{
		const style$ = createStore('background-color: palegoldenrod');

		this.afterAttachToDom.subscribe(() => {
			setTimeout(() => { style$._('background-color: palegreen') }, 1500);
			setTimeout(() => { style$._('background-color: paleturquoise') }, 3000);
		});

		return parseHTML([
			'<p>', {
				'data-id': 1001,
				hidden: false,
				style: 'color: white; background-color: black; padding: 10px',
			},
			[
				'The quick brown fox jumps over the lazy dog'
			],
			'</p>',
			'<p>', { hidden: true }, [ 'This is hidden' ], '</p>',
			'<p>', {
				style: style$,
			},
			[
				'The quick brown fox jumps over the lazy dog'
			],
			'</p>',
		]);
	}
}

mountComponent(new Attribute(), document.getElementById('app-container'));

attribute-jsx.tsx :

import Component from "./node_modules/@xylem-js/xylem-js/dom/Component.js";
import createStore from "./node_modules/@xylem-js/xylem-js/core/createStore.js";
import mountComponent from "./node_modules/@xylem-js/xylem-js/dom/mountComponent.js";

class Attribute extends Component
{
	build()
	{
		const style$ = createStore('background-color: palegoldenrod');

		this.afterAttachToDom.subscribe(() => {
			setTimeout(() => { style$._('background-color: palegreen') }, 1500);
			setTimeout(() => { style$._('background-color: paleturquoise') }, 3000);
		});

		return <>
			<p
				data-id={1001}
				hidden={false}
				style="color: white; background-color: black; padding: 10px"
			>
				The quick brown fox jumps over the lazy dog
			</p>
			<p hidden={true}>This is hidden</p>
			<p
				style={style$}
			>
				The quick brown fox jumps over the lazy dog
			</p>
		</>;
	}
}

mountComponent(new Attribute(), document.getElementById('app-container')!);

Some attributes like class and style support additional data types as well.

class attribute

In addition to data types mentioned above, class attribute also supports object and array values.

object

The key of object represents class while the value represents the presence or absence of the class. The value can be boolean or Supplier<boolean>.

The final value of class attribute is the joined value of keys of object with a space character ( ) as separator.

style.css :

.theme-dark {
	background-color: #303030;
	color: #e8e8e8;
}

.theme-light {
	background-color: #f0f0f0;
	color: #282828;
}

class-attribute.js :

import Component from "./node_modules/@xylem-js/xylem-js/dom/Component.js";
import createStore from "./node_modules/@xylem-js/xylem-js/core/createStore.js";
import map from "./node_modules/@xylem-js/xylem-js/core/map.js";
import mountComponent from "./node_modules/@xylem-js/xylem-js/dom/mountComponent.js";
import parseHTML from "./node_modules/@xylem-js/xylem-js/dom/parseHTML.js";

class ClassAttribute extends Component
{
	build()
	{
		const isThemeDark$ = createStore(true);

		return parseHTML([
			'<p>', {
				class: {
					'theme-dark': isThemeDark$,
					'theme-light': map(isThemeDark$, v => !v),
				},
			},
			[
				map(isThemeDark$, v => v ? 'Dark Theme' : 'Light Theme'),
			],
			'</p>',
			'<div>',
			[
				'<button>', {
					'@click': () => isThemeDark$._(!isThemeDark$._()),
				},
				[
					'Toggle Theme',
				],
				'</button>',
			],
			'</div>',
		]);
	}
}

mountComponent(new ClassAttribute(), document.getElementById('app-container'));

array

array can contain string or object.

The final value of class attribute is the joined value of strings and keys of object with a space character as separator.

class-attribute.js :

import Component from "./node_modules/@xylem-js/xylem-js/dom/Component.js";
import createStore from "./node_modules/@xylem-js/xylem-js/core/createStore.js";
import map from "./node_modules/@xylem-js/xylem-js/core/map.js";
import mountComponent from "./node_modules/@xylem-js/xylem-js/dom/mountComponent.js";
import parseHTML from "./node_modules/@xylem-js/xylem-js/dom/parseHTML.js";

class ClassAttribute extends Component
{
	build()
	{
		const isThemeDark$ = createStore(true);

		return parseHTML([
			'<p>', {
				class: [ 'font-monospace', {
					'theme-dark': isThemeDark$,
					'theme-light': map(isThemeDark$, v => !v),
				}, 'mx-auto' ],
			},
			[
				map(isThemeDark$, v => v ? 'Dark Theme' : 'Light Theme'),
			],
			'</p>',
			'<div>',
			[
				'<button>', {
					'@click': () => isThemeDark$._(!isThemeDark$._()),
				},
				[
					'Toggle Theme',
				],
				'</button>',
			],
			'</div>',
		]);
	}
}

mountComponent(new ClassAttribute(), document.getElementById('app-container'));

style attribute

In addition to data types supported by all attributes, style attribute also supports object and array values.

object

The key of object represents CSS property while the value represents the value of CSS property or absence of the CSS property. The value can be string, number, boolean or Supplier<string|number|boolean>.

The final value of class attribute is the joined value of keys of object with a semi-colon followed by a space character (; ) as separator.

import Component from "./node_modules/@xylem-js/xylem-js/dom/Component.js";
import createStore from "./node_modules/@xylem-js/xylem-js/core/createStore.js";
import map from "./node_modules/@xylem-js/xylem-js/core/map.js";
import mountComponent from "./node_modules/@xylem-js/xylem-js/dom/mountComponent.js";
import parseHTML from "./node_modules/@xylem-js/xylem-js/dom/parseHTML.js";

class StyleAttribute extends Component
{
	build()
	{
		const isThemeDark$ = createStore(true);

		return parseHTML([
			'<p>', {
				style: {
					'background-color': map(isThemeDark$, v => v ? '#303030' : '#f0f0f0'),
					'color': map(isThemeDark$, v => v ? '#e8e8e8' : '#282828'),
				},
			},
			[
				map(isThemeDark$, v => v ? 'Dark Theme' : 'Light Theme'),
			],
			'</p>',
			'<div>',
			[
				'<button>', {
					'@click': () => isThemeDark$._(!isThemeDark$._()),
				},
				[
					'Toggle Theme',
				],
				'</button>',
			],
			'</div>',
		]);
	}
}

mountComponent(new StyleAttribute(), document.getElementById('app-container'));

array

array can contain string or object.

The final value of class attribute is the joined value of strings and keys of object with a semi-colon followed by a space character (; ) as separator.

import Component from "./node_modules/@xylem-js/xylem-js/dom/Component.js";
import createStore from "./node_modules/@xylem-js/xylem-js/core/createStore.js";
import map from "./node_modules/@xylem-js/xylem-js/core/map.js";
import mountComponent from "./node_modules/@xylem-js/xylem-js/dom/mountComponent.js";
import parseHTML from "./node_modules/@xylem-js/xylem-js/dom/parseHTML.js";

class StyleAttribute extends Component
{
	build()
	{
		const isThemeDark$ = createStore(true);
		const fontSizeEm$ = createStore(1);

		return parseHTML([
			'<p>', {
				style: [
					'display: block; padding: 24px',
					{
						'background-color': map(isThemeDark$, v => v ? '#303030' : '#f0f0f0'),
						'color': map(isThemeDark$, v => v ? '#e8e8e8' : '#282828'),
					},
					'font-family: system-ui, sans-serif',
					{
						'font-size': map(fontSizeEm$, v => `${v}em`),
					},
					'text-decoration: underline 2px'
				],
			},
			[
				map(isThemeDark$, v => v ? 'Dark Theme' : 'Light Theme'),
			],
			'</p>',
			'<div>',
			[
				'<button>', {
					'@click': () => isThemeDark$._(!isThemeDark$._()),
				},
				[ 'Toggle Theme' ],
				'</button>',
			],
			'</div>',
			'<div>',
			[
				'Font size: ',
				'<button>', {
					'@click': () => fontSizeEm$._(1),
				},
				[ '1x' ],
				'</button>',
				'<button>', {
					'@click': () => fontSizeEm$._(1.5),
				},
				[ '1.5x' ],
				'</button>',
				'<button>', {
					'@click': () => fontSizeEm$._(2),
				},
				[ '2x' ],
				'</button>',
			],
			'</div>',
		]);
	}
}

mountComponent(new StyleAttribute(), document.getElementById('app-container'));