Skip to content
This repository has been archived by the owner on Jan 7, 2023. It is now read-only.
/ tal-jsx Public archive

A utility library which lets you use JSX Syntax in TAL (https://github.com/bbc/tal)

License

Notifications You must be signed in to change notification settings

lionralfs/tal-jsx

Repository files navigation

tal-jsx

Update (2023-01-07): TAL is being deprecated, so I archived this repository and deprecated the npm package.

Making TAL more declarative

build status npm version

Installation

npm install tal-jsx --save

or include the following script in your page:

<script src="https://unpkg.com/tal-jsx@latest/dist/taljsx.umd.js"></script>

in which case the library is exposed on window (window.taljsx.render and window.taljsx.h).

In your .babelrc:

{
  "plugins": [
    [
      "transform-react-jsx",
      {
        "pragma": "h"
      }
    ]
  ]
}

Usage

First, make sure h and render are available (import { h, render } from 'tal-jsx').

// create a widget by rendering some jsx:
const loginBox = render(
  <Container class="loginbox">
    <Label class="loginbox__title">Please log in!</Label>
    <Button onClick={() => console.log('clicked')}>
      <Label>Cancel</Label>
    </Button>
  </Container>
);

// then, you can use the widget as before:
this.appendChildWidget(loginBox);

But why?

For readability purposes mostly. A deeply nested widget tree becomes very difficult to read.

An example

Take a look at this:

const wrapper = new Container();
wrapper.addClass('wrapper');

const textbox = new Container();
textbox.addClass('textbox');

const title = new Label('Example title');
title.addClass('title');

const desc = new Label('Some text');
desc.addClass('description');

textbox.appendChildWidget(title);
textbox.appendChildWidget(desc);

const button = new Button();
button.appendChildWidget(new Label('OK'));

wrapper.appendChildWidget(button);

This could now be written as:

const wrapper = render(
  <Container class="wrapper">
    <Container class="textbox">
      <Label class="title">Example title</Label>
      <Label class="desc">Some text</Label>
    </Container>
    <Button>
      <Label>OK</Label>
    </Button>
  </Container>
);

Much nicer, right?

Limitations

  • You need Babel (alternatively, you could write the transformed JSX by hand).
  • This was mainly built for static content. There is no such thing as state updates or a diffing algorithm.

Carousels

To render Carousels, you can use <Carousel> like this:

const handler = new ActivateFirstHandler(); // or any other KeyHandler

const myCarousel = render(
  <Carousel orientation="horizontal" handler={handler}>
    <Button>
      <Label>Item 1</Label>
    </Button>
    <Button>
      <Label>Item 2</Label>
    </Button>
  </Carousel>
);

The orientation can be either horizontal or vertical.

It also accepts the widget lengths as attributes:

<Carousel lengths={300}>...</Carousel>

Events

To bind event listeners to widgets, you can use one (or more) of the following attributes:

  • onClick
  • onKeyDown
  • onKeyPress
  • onKeyUp
  • onSelectedItemChange
  • onFocus
  • onFocusDelay
  • onBlur
  • onBeforeDataBind
  • onDataBound
  • onDataBindingError
  • onBeforeAlign
  • onAfterAlign
  • onBeforeSelectedItemChange
  • onSelectedItemChange

DOM JSX

You can also use DOM JSX inside a <Label>. For example:

let label = render(
  <Label>
    <a href="#">
      <div />
    </a>
    <p>TEST</p>
    <div>
      <strong>ok</strong>
    </div>
  </Label>
);

Be careful with mixing TAL JSX and DOM JSX though, as you won't be able to:

  • Go back to using TAL components/widgets inside DOM elements
  • Use DOM JSX outside of a <Label> element.

License

MIT © Lion Ralfs