Component¶
For the reference see: Component
A Component takes over a section of the display. It can render inside that section (the section is inside an HTML tag) and is king when it comes to manage anything rendered inside (like binding to events of buttons, changing the text of elements, re-rendering elements on-demand, rendering from network content, applying privately scoped styles, …)
It can host subcomponents which can be in turn in charge of portions of the display which fall within the realm of the main Component.
The usual combination for rendering involves 3 pieces
HTML
CSS
Python
Which can be combined in a single Python class or be divided in 3 proper
.html
, .css
and .py
files.
Note
You can use ComponentInline
, which already configures
htmlpath=None
and stylepath=None
for you, to avoid looking
for external html and css resources for the component
Properties of a Component¶
Attributes and other definitions in the Component can be accessed by:
Subcomponents (and subcomponents of it)
It can access attributes of parent Component instances and the parent Module
It can declare:
bindings: which auto-generates an attribute bound to an Observable
services: which will be added as attributes and instantiated to provide a service to the component and subcomponents
Note
components is not missing from the declaration. The subcomponents mentioned above are generated by means of direct instantiation, by tag based auto-instantiation, or because they are children in a route definition hierarchy in the module.
It can define the tag under which it will be rendered or let it be auto-generated (see
selector
)It can host Html content either fetched from a file or declared inline (see
htmlpath
andhtmlsheet
)It can host CSS content either fetched from a file or declared inline (see
stylepath
andstylesheet
)It can render everything programmatically if needed be and/or modify the generated content/styles (see methods
render
andstyler
)It can react to being loaded unloaded from the DOM (see the methods
loading
andunloading
or the more generic versionload
)
Component instantiation¶
In order for a component to do its work it has to be instantiated. There are several possibilities. But before seeing them:
If a component is directly instantiated, it will look for the matching
selector
tag to render itself.Should the tag not be found, the default behavior is to render the tag and then render itself inside
If a tag is found in generated/fetched html code which matches the
selector
of a component, it will be instantiated so that it can render itself inside the tag.
Note
Remember, as stated above, that if no selector
is specifically
defined, the Component will auto-generate one. It will use its own
class name (with hyphens in between lower/upper-case boundaries,
then lowercased and receiving a unique suffix)
This dual behavior gives the programmer complete flexibility about how components will render by simply specifying the matching tags in html code, or by instantiating the component directly and letting it auto-render.
Module Bootstrapping¶
The component is declared in the components
directive of a Module. It
will be instantiated before the routing engine takes over.
from .app_component import AppComponent
class MyModule(Module):
...
components = AppComponent # can be a single item or an iterable
...
Route Bootstrapping¶
Components will be instantiated (and given a place to render) when the defined routes are visited
from .one_component import OneComponent
from .two_component import TwoComponent
class MyModule(Module):
...
routes = [
{'path': 'one', 'component': OneComponent,},
{'path': 'two', 'component': TwoComponent,},
]
...
Inline instantiation¶
When a component is being rendered in render
, an instance of another
component can be created (it will become a sub-component)
from .two_component import TwoComponent
class OneComponent(Module):
def render(self, node):
... # do some work
...
TwoComponent() # create sub-component inline
Tag auto-instantiation¶
Specify the selector
belonging to the component to be rendered in the Html
code.
Note
The component has to be imported somewhere. If not, the python file will be just a text file sitting somehwere in the file hierarchy.
In the snippet below it is imported in the same module in which the instantiation will happen in the Html code, but it can actually be imported anywhere
First the component to be rendered, to show the selector
being set to a
fixed value.
class TwoComponent(Module):
selector = 'two-component'
...
from .two_component import TwoComponent
class OneComponent(Module):
# Use the selector defined inside TwoComponent
htmlsheet = '''
<h1>hello</h2>
<two-component></two-component>
'''
def render(self, node):
... # do some work
...
Tag auto-instantiation (2)¶
Same as in the previous example but issuing the tag programmatically
from anpylar import Component, html
from .two_component import TwoComponent
class OneComponent(Module):
# Use the selector defined inside TwoComponent
htmlsheet = '''
<h1>hello</h2>
'''
def render(self, node):
... # do some work
...
html._tag('<two-component>') # or the alias html._tagout
This is also possible as:
from anpylar import Component, html
from .two_component import TwoComponent
class OneComponent(Module):
# Use the selector defined inside TwoComponent
htmlsheet = '''
<h1>hello</h2>
'''
def render(self, node):
... # do some work
...
TwoComponent.selector_render()
Component proceedings¶
The lifecycle of a component follows this path.
Initialization
__init__
will be called if definedIf css is defined as a path (
stylepath
) or inline (stylesheet
) it will be placed in the DOM.Note
The css will be scoped to the component and it is thus private to your component.
This may generate an ajax call if the application has not been packaged and a path or auto-path (
stylepath
) is defined.The default behavior is to look for a css file which uses the Python class name transformed (underscores are placed in the upper/lower-case boundaries, all lowercased and with
.css
as the extension)If html is defined as a path (
htmlpath
) or inline (htmlsheet
) it will be placed in the DOM. This also includes generating super-charged DOM objects for each element generated, which can be later used in the code.This may generate an ajax call if the application has not been packaged and a path (or auto-path) is defined
See also
Pseudo-Programming can be done inside the html code with special directives in the names of attributes. See: Html Programming
The default behavior is to look for an html file which uses the Python class name transformed (underscores are placed in the upper/lower-case boundaries, all lowercased and with
.html
as the extension)The method
styler()
will be calledIf no stylesheet has been defined, this method can return text content containing the stylesheet
The method
render(node)
will be callednode is the html element under which rendering takes place. If html code (from either a file or an inline definition) was available, it will already be present and ready under node.
If not, any html element generated with the
anpylar.html
module tags will be placed under node
DOM Loading/Unloading
After the initialization or when the component is again being navigated to, the method
loading()
will be called to indicate that the component is being placed in the DOMWhen the component is being unloaded from the DOM (for example: navigating away to other route) the method
unloading()
will be called.
These two methods allow executing actions like for example clearing an input field when a component is loaded/unloaded. Upon the next visit to the component, the user will always have a fresh input field to type in.
There is a generic method load(loading=True)
which can be overridden
too. The default behavior is to call loading
or unloading
.
Deactivation
If the route that took to this component defines it,
can_deactivate()
will be called before navigating away (beforeunloading
)
can_deactivate
can prevent navigating away, because the component may ask the application user if changes have to be saved.
Component actions¶
Those are the ones not defined by the platform. These will be the consequence of binding and callback functions set during rendering and/or loading/unloading.
It’s the programmer the one providing the sauce here.