Reactive Logic - PageAmp/pageamp GitHub Wiki

Logic Attributes

Attributes prefixed with : are trated as logic attributes. They don't appear in generated HTML and can be used in logic expressions.

When their value change, all dependent expressions are re-evaluated and the page is automatically updated.

For example, this source page:

<html>
  <head :bgColor="#fff">
    <style>
      body {
        background-color: [[bgColor]];
      }
    </style>
  </head>
</html>

will generate this code:

<html>
  <head>
    <style>
      body {
        background-color: #fff;
      }
    </style>
  </head>
</html>

Special Attributes

Logic attributes prefixed with :class-, :style-, :on- and :event- have special behaviours.

Class Attributes

In addition to using the standard class attribute, CSS classes can be dynamically added and removed with the :class- attributes.

For example, this DIV:

<div class="box" :class-red=[[alarm]] :alarm=[[false]]></div>

will have class="box red" or class="box" depending on :alarm being true or false.

Style Attributes

In addition to using the standard style attribute, CSS styles can be dynamically set with the :style- attributes.

For example, this DIV:

<div class="box"
     :style-background=[[alarm ? 'red' : null]]
     :alarm=[[false]]></div>

will have style="background: red" or no style at all depending on :alarm being true or false.

Value Handlers

Attributes prefixed with :on-<name> define expressions that are evaluated whenever the <name> attribute changes value.

For example this code:

<body :count=[[0]]
      :on-count=[[delayedSet('count', count + 1, 1)]]>
    Seconds: [[count]]
</body>

implements a seconds counter. Here are the details:

  • Server-side, count is assigned to zero. The handler is called just like in the client, but it uses the delayedSet() function with a 1 second delay, so it has no effect on the output page.
  • Client-side the page is initially displayed as it arrived, with the "Seconds: 0" text. As soon as the client runtime starts, it repeats what the server did in the server. This time, the delayedSet() does work and count is incremented after the delay elapses. This in turn re-evaluates the handler expression and so on.

Event Handlers

Attributes prefixed with :event-<type> declare client-side event handlers associated to an element.

For example this code:

<body :count=[[0]] :event-click=[[count++]]>
    Clicks count: [[count]]
</body>

will initially display "Clicks count: 0" and will then change at each user click.

:data

:data is a reserved attribute name, used to give an element a `data context.

:aka

:aka is a reserved attribute name, used to give a logic name to page elements.

Logic Expressions

You can inject expressions surounded with [[ and ]] anywhere in page text and attribute values. They can access logic attributes, implement complex behaviour, and their resulting value is automatically applied to the page.

Expressions are reactive. This means that they are automatically re-evaluated, and re-applied to the page, when the logic attributes they refer to change value.

In this example:

<html>
  <body :count=[[0]]
        :on-count=[[delayedSet('count', count + 1, 1)]]>
    Seconds: [[count]]
  </body>
</html>

the body text expression gets updated and re-applied to the page each time :count changes value.

Multi-line, Multi-statement Expressions

TBD

Functions

Logic scopes

PageAmp doesn't treat HTML as plain text, like a templating engine would do. Both in the server and in the client, HTML is parsed into an actual DOM before page logic is executed.

Expressions can see logic attributes defined in their own element as well as in all its parent nodes.

For example:

<html>
  <head :bgColor="$fff">
    <style>
      body {
        background-color: [[bgColor]];
      }
    </style>
  </head>
  <body>
    <!--
      expressions here cannot directly see "bgColor"
    -->
  </body>
</html>

Elements, though, can be given a logic name with :aka:

<html>
  <head :aka="head" :bgColor="$fff">
    <style>
      body {
        background-color: [[bgColor]];
      }
    </style>
  </head>
  <body>
    <!--
      expressions here can see "head" so they can
      indirectly access "bgColor" through it
    -->
    [[head.bgColor]]
  </body>
</html>

Actually, the :aka attribute above is redundant: elements <html>, <head> and <body> are always implicitly given the names "page", "head" and "body", respectively.

:aka was chosen over :name because the latter is often a desirable name for a logical attribute.

⚠️ **GitHub.com Fallback** ⚠️