Writing HTML

How to write concise html markup in Jaspr.

With jaspr, you write html as part of your component tree. Each html tag (like div, p, img, etc.) has an assigned method you can use (reps. div(), p(), img(), etc.).

Let's look at the following html snippet:

<div>
  <h1>This is a title</h1>
  <p>Hello <b>World!</b></p>
</div>

Within a jaspr component, this can be represented as such:

div([
  h1([text('This is a title')]),
  p([text('Hello '), b([text('World!')])]),
]);

The special text() method does not add a html tag but renders plain text inside other elements.

HTML utilities

There exist methods for the most common html tags, like div, a, p, img as well as more special tags like video, form, input and others.

If you want support for a tag that does not have such a method yet, please don't hesitate to open an issue on github.

Each method has the following signature:

Component <tagname>(List<Component> children, {
  Key? key,
  String? id,
  String? classes,
  Styles? styles,
  Map<String, String>? attributes,
  Map<String, EventCallback>? events,
});

In addition to these parameters some methods have tag-specific attributes, like img(src: "...") or a(href: "...").

For readability, it is recommended to put the list of child components last in the parameter list: div(id: "main", [text('Hello World')]) is more readable than div([text('Hello World')], id: "main"). In case of no children specify an empty list ([]). Some tags also omit this parameter, like img.

Try it out on JasprPad

Finally, here are some more examples of this syntax. You can switch between the dart code and rendered html output.

Paragraph with rich text
  p([text('This is some '),b([text('html')]),text(' content.')])
Heading with blue text
h1(styles: Styles.text(color: Colors.blue), [text('Hello Jaspr!')])
Anchor with an image
  a(href: "https://github.com/schultek/jaspr", target: Target.blank, [
    img(src: "https://jasprpad.schultek.de/jaspr-192.png"),
  ])
Select input
  select([
    option(value: 'test', [text('Select me!')]),
    option(value: 'other', selected: true, [text('Or me!')])
  ])
Progress bar
progress(value: 85, max: 100, [])

Lower-Level Components

DomComponent

Under the hood, every html element in jaspr is represented by a DomComponent, which is a special component that takes a tag, some other parameters and a list of children, which can again be other DomComponents.

If you want to, you can write DomComponents manually instead of using the utility methods. This gives you great low-level control over your html structure, but is more verbose.

  var component = DomComponent(
    tag: 'div',
    id: 'my-id',
    classes: 'class-a class-b',
    styles: Styles.text(color: Colors.black),
    attributes: {'my-attribute': 'my-value'},
    events: {'click': (e) => print('clicked')},
    children: [
      /* ... */
    ],
  );

Using this component would render the following html:

<div id="my-id" style="color: red" class="class-a class-b" my-attribute="my-value">
  ...
</div>

Text

A simple component that renders a text node. The text() method simply returns a Text component.

A text node in html is just some standalone string that is placed inside another html element. Therefore the Text component also only receives a single string to render to the page.

  var text = Text('Hello World!');

As usual for web, styling is done through a combination of CSS attributes, either in a Stylesheet or inline though the styles attribute of the parent elements.

Formatting Whitespace

When pre-rendering your components in server and static mode, Jaspr will output cleanly formatted html on a best-effort basis. This means it will add newlines and indentations to your html element, while trying to not affect the way the html is rendered.

For example lets look at this simple Jaspr code:

div([
  b([text('A')]),
  em([text('B')]),
  span([text('C')]),
])

Which will generate the following html:

<div>
  <b>A</b>
  <em>B</em>
  <span>C</span>
</div>

Here Jaspr adds newlines and indentation for each child element. However in some cases, you might not want Jaspr to introduce extra whitespace because it would affect the way the html is rendered.

If you don't want Jaspr to format the output html for a part of your code, wrap it in a <span> element. This works since Jaspr will not apply and additional formatting to <span> elements.

So for example this code:

span([
  b([text('A')]),
  em([text('B')]),
  span([text('C')]),
]),

will generate to following html:

<span><b>A</b><em>B</em><span>C</span></span>