##// END OF EJS Templates
Changed build script to include local typings to compilation task
Changed build script to include local typings to compilation task

File last commit:

r41:3b6c4159c66c v1.0.0 default
r50:346ba910a542 v1.0.5 default
Show More
readme.md
198 lines | 4.9 KiB | text/x-minidsrc | MarkdownLexer

@implab/djx

SYNOPSIS

import { djbase, djclass, bind, prototype, AbstractConstructor } from "@implab/djx/declare";

import { DjxWidgetBase } from "@implab/djx/tsx/DjxWidgetBase";
import { createElement } from "@implab/djx/tsx";

interface MyWidgetAttrs {
    title: string;

    counter: number;
}

interface MyWidgetEvents {
    "count-inc": Event;

    "count-dec": Event;
}


@djclass
export class MyWidget extends djbase(
    DjxWidgetBase as AbstractConstructor<DjxWidgetBase<MyWidgetAttrs, MyWidgetEvents>>
) {

    @bind({ node: "titleNode", type: "innerHTML" })
    title = "";

    @prototype()
    counter = 0;

    render() {
        const Frame = (props: any) => <div>{props.children}</div>;
        return <div
            className="myWidget"
            tabIndex={3}
            style={ alignContent: "center", border: "1px solid" }
        >
            <h1 data-dojo-attach-point="titleNode"></h1>
            <Frame>
                <span class="up-button" onclick={e => this._onIncClick(e)}>[+]</span>
                <span class="down-button" onclick={() => this._onDecClick()}>[-]</span>
            </Frame>
        </div>;
    }

    _onIncClick(e: MouseEvent) {
        this.emit("count-inc", { bubbles: false });
    }

    _onDecClick() {
        this.emit("count-dec", { bubbles: false });
    }
}

DESCRIPTION

This package provides you with tools to glue your good-fellow dojo with modern techniques of building the webapp. The core concept is built around widgets and using .tsx to write it. Here some features:

  • djbase(), @djaclass - traits to declare your classes with dojo/_base/declare
  • @implab/djx/tsx - traits to build the rendering of your widgets with tsx
  • DjxWidgetBase - abstract class which supports tsx markup and data-dojo-attach-* attributes.
  • @bind(...) - annotations provides an easy way of using standard dojo widget attribute bindings.

djbase, @djclass

These two traits provides convenient way of using dojo/_base/declare in Typescript for declaring your classes.

djbase(...constructors) - this method accepts a list of constructors in its parameters and returns the fake base type which then can be used to derive your own class. This allows you to provide the Typescript with the correct information about the base type and even use super!. The only one caveat of this approach is that you MUST decorate your class with @djclass annotation.

Consider the following example:

import { djbase, djclass } from "@implab/djx/declare";
import { FooMixin } from "./FooMixin";
import { BarMixin } from "./BarMixin";
import { BoxMixin } from "./BoxMixin";

@djclass
export class Baz extends djbase(FooMixin, BarMixin, BoxMixin) {
    writeHello(out: string[]) {
        out.push("-> Baz");

        super.writeHello(out);

        out.push("<- Baz");
    }
}

All mixins are declared like the one below:

import { djclass, djbase } from "@implab/djx/declare";

interface Super {
    writeHello(out: string[]): void;

}

@djclass
export class BarMixin extends djbase<Super>() {
    writeHello(out: string[]) {
        out.push("-> Bar");

        super.writeHello(out);

        out.push("<- Bar");
    }
}

finally create an instance and call the writeHello method

const baz = new Baz();

const data: string[] = [];
baz.writeHello(data);

console.log(data.join("\n"));

you will get the following output:

-> Baz
-> Box
-> Bar
-> Foo
<- Foo
<- Bar
<- Box
<- Baz

Let's take a closer look to the Baz declaration it uses djbase to derive from three mixins and the class is decorated with @djclass to accomplish the declaration and make a real constructor.

To allow an access to the next sibling method (in terms of multiple inheritance) Dojo provides this.inherited(arguments) method but this approach leads to the problem with 'strict' mode of ES5 and eliminates the type information about a calling method. This library solves the problem calling inherited/next method by utilizing super keyword. Under the hood there are proxy methods generated in the prototype of the declared class which make calls to this.inherited(...) method. This technique is compatible with 'strict' mode.

Mixins are declared the similar, they are also may have the base types although the most common case is declaring the mixin without any base classes. To allow the mixin to access the next method you should declare the interface with desired methods and use the special form of djbase<Super>() without arguments.

DjxWidgetBase<Attrs, Events>

TODO

Markup (.tsx)

Add to your tsconfig.json the following options

{
    "compilerOptions": {
        "types": ["@implab/djx"],
        "experimentalDecorators": true,
        "jsxFactory": "createElement",
        "jsx": "react",
    }
}

Import createElement into your .tsx file

import { createElement } from "@implab/djx/tsx";

You are ready to go!

TODO