Html Programming

To reduce the amount of code one may need in a Python component for rendering (and sometimes to fully remove it) one can use some especially prefixed attributes when writing html code. These prefixes and interpreted by the AnPyLar engine and turned into code.

The rules:

  • The attribute name relates to the node.
  • The attribute value is meant to exist within the Python part of the component and will be evaluated as if had been prefixed with self. Where self refers to the component controlling the html code.

Let’s see the different directives.

Formatting

Unnamed arguments

This is done with the square brackets: []. For example, given this component definition

class MyComponent(AppComponent)
    title = 'My Title'

The following can be done directly in the html code:

<h1 [title]>{}</h1>

Which translates to:

  • Look for an attribute title in the holding component and perform formatting in the {} template

Just like if one had done this in Python code

class MyComponent(AppComponent)
    title = 'My Title'


 def render(self.node):
     with html.h1('{}') as h1:
         h1._fmt(self.title)

Named arguments

This is done with the curly braces: {}. For example, given this component definition

class MyComponent(AppComponent)
    title = 'My Title'

The following can be done directly in the html code:

<h1 {to_replace}=title>{to_replace}</h1>

Which translates to:

  • Look for an attribute title in the holding component and perform formatting in the {to_replace} template

This may seem overly verbose for a single replacement, but it is needed in case multiple {name} templates are present

Just like if one had done this in Python code

class MyComponent(AppComponent)
    title = 'My Title'


 def render(self.node):
     with html.h1('{to_replace}') as h1:
         h1._fmt(to_replace=self.title)

Event binding

Without event parameter

This is done with the regular parentheses: (). For example, given this component definition

class MyComponent(AppComponent)

    def react_to_click(self):
        print('Something was clicked')

The binding could be realised as in:

<button (click)="react_to_click">Click Me!</button>

With event parameter

This is done with the dollar sign: $$. For example, given this component definition

class MyComponent(AppComponent)

    def react_to_click(self, event):
        print('Something was clicked')

The binding could be realised as in:

<button $click$="react_to_click">Click Me!</button>

Notice how in this case the event generated by the click event will reach the method react_to_click

Passing callables

This is done by prefixing the attribute name with *. For example, from the Tour of Pyroes, given this component.

class PyroDetailComponent(Component):
    bindings = {
        'pyro': Pyro(),
    }
    ...

And the following in the html code:

<div *_display=pyro_.pyd_>
  <h2 {name}="pyro_.name_.map(lambda x: x.upper())">{name} Details</h2>
  <div><span>pyd: </span><txt [pyro_.pyd_]>{}</txt></div>
  <div>
      <label>name:
        <input *_fmtvalue=pyro_.name_ placeholder="name"/>
      </label>
  </div>
  <button (click)=router.back()>Go back</button>
</div>

The display of the outermost <div> is controlled like this:

<div *_display=pyro_.pyd_>

which translates to:

  • Invoke the _display method of the node.
  • With argument self.pyro_.pyd_, where self refers to the component and not to the node.

This effectively binds the generated values of the final pyd_ observable to be the control of when the <div> is displayed. Obviously if the value evaluates to False (for example 0), the <div> will be hidden and if it evaluates to True, it will be shown.