Skip to content

Tutorial

Construction

htag.Tag is the basic object, and the only one you'll need to use, to build an htag app. The simplest htag app could be :

from htag import Tag

class App(Tag.div): #<= define the html tag container of the app
    """ This is the most simple htag component """

    def init(self):
        # I'm just a div'tag, with a textual node content "hello world"
        self <= "Hello world"   # shortcut for self.add("Hello world")

if __name__=="__main__":
    from htag.runners import Runner
    Runner( App ).run()    # <= this is the runner

As you can notice, it uses the simplest constructor init(), to construct itself (best practice). But could be replaced by the real form too:

    def __init__(self, **kwargs):
        # I'm just a div'tag, with a textual node content "hello world"
        super().__init__(**kwargs)
        self <= "Hello world"   # shortcut for self.add("Hello world")

The simplest form avoid you to deal with the real construction phase under the hood. Because kwargs are used to define html attributs (or instance properties) from the ground.

Main Tag is always rendered as a body'tag

Although App is declared as a Tag.div, it will be rendered as a body'tag, because it's the main Tag (the one which is drived by the runner)

Here is another htag app, which will use the same component (MyText) for "hello" and "world". You can notice that, the second ("world") is set with a default background style (green). kwargs prefixed by _ are automatically setted as attribut on the tag instance.

from htag import Tag

class MyText(Tag.span):
    def init(self,txt, *a):
        self <= txt

class App(Tag.body):
    def init(self):
        self <= MyText("Hello")
        self <= MyText("World",_style="background:green")

if __name__=="__main__":
    from htag.runners import Runner
    Runner( App ).run()    # <= this is the runner

This will produce something like :

<body id="140236411356880">
    <span id="140236411356544">Hello</span><span style="background:green" id="140236411356208">World</span>
</body>

id's are just here, to keep coherence with python objects on python side.

If you want to set html attributs, at runtime (not in contructor phase), you simply set the dictitems of the Tag. Here is a version of the previous example using them.

from htag import Tag

class MyText(Tag.span):
    def init(self,txt,color=None):
        self <= txt
        if color:
            self["style"]="background:%s" % color   # <- here is the trick

class App(Tag.body):
    def init(self):
        self <= MyText("Hello")
        self <= MyText("World","green")

if __name__=="__main__":
    from htag.runners import Runner
    Runner( App ).run()    # <= this is the runner

It will produce the same html rendering.

More on Tag creations (the complete guide)

The tutorial to create an "input" component

Interactions

As you seen before, you can pass prefixed kwargs to define html attributs (or define them in the dictitems of the Tag), so this thing will work too :

from htag import Tag

class App(Tag.body):
    def init(self):
        self <= Tag.button("Click me",_onclick="alert(42)")

if __name__=="__main__":
    from htag.runners import Runner
    Runner( App ).run()    # <= this is the runner

But, notice that the string which is setted in _onclick is just a javascript statement !

If you want to call "python side", you will need to use an another form, the simplest one :

from htag import Tag

class App(Tag.body):
    def init(self):
        self <= Tag.button("Hello",_onclick=self.addContent)
        self <= Tag.button("World",_onclick=self.addContent)

    def addContent(self,object): # <= object is the instance of the htag instance which have called this method (here a Tag.button)
        self <= object.innerHTML

if __name__=="__main__":
    from htag.runners import Runner
    Runner( App ).run()    # <= this is the runner

When you will click the button, the instance of the object will add "some content" to itself (you can verify, by refreshing the page (f5))

kind of methods

Here, the addContent method, is a sync method. But keep in mind, that it could be:

  • a async method (ex: async def addContent(...))
  • a sync generator (ex: def addContent(...): yield)
  • or an async generator (ex: async def addContent(...): yield)

The last two (the generator ones), let you use a yield statement, which will force current rendering to the client side, while processing the generator.

From here, you have seen 95% of the features of htag.

More on interactions (the complete guide)

Include ressources

htag provide a way to include some external ressources (think: css, js, favicon, ...). All theses ressources will be included in <head> tag, at construction time. htag will scan the python Tag'classes and collect all of them to produce the heading parts of the html rendering.

The trick is to define a class attribut statics, to add your ressource ... a simple example :

from htag import Tag

class App(Tag.body):
    statics = Tag.style("""body {background:yellow}""")

    def init(self):
        self <= "hello world"

if __name__=="__main__":
    from htag.runners import Runner
    Runner( App, port=9999).run()    # <= this is the runner

statics can be a Tag'instance or a list of Tag'instance.

Discovering statics

By default, htag will discover all Tag'subclasses to include their statics, from the current process. But sometimes, it can be useful to include only thoses which we really need ; it's possible thru the class attribut imports, which should contain a list of Tag'class.

Execute JS statements on client side

Sometimes, it can be useful to start a js statement ...

or make a js interaction with @expose decorator

** NEXT SOON **