Spaces:
Sleeping
A newer version of the Streamlit SDK is available:
1.46.1
Custom Components
The majority of the time the default ft
components are all you need
(for example Div
, P
, H1
, etc.).
Pre-requisite Knowledge
If you don’t know what an ft component is, you should read the explaining ft components explainer first.
However, there are many situations where you need a custom ft component
that creates a unique HTML tag (for example <zero-md></zero-md>
).
There are many options in FastHTML to do this, and this section will
walk through them. Generally you want to use the highest level option
that fits your needs.
Real-world example
This external tutorial walks through a practical situation where you may want to create a custom HTML tag using a custom ft component. Seeing a real-world example is a good way to understand why the contents of this guide is useful.
NotStr
The first way is to use the NotStr
class to use an HTML tag as a
string. It works as a one-off but quickly becomes harder to work with as
complexity grows. However we can see that you can genenrate the same xml
using NotStr
as the out-of-the-box components.
from fasthtml.common import NotStr,Div, to_xml
div_NotStr = NotStr('<div></div>')
print(div_NotStr)
<div></div>
Automatic Creation
The next (and better) approach is to let FastHTML generate the component
function for you. As you can see in our assert
this creates a function
that creates the HTML just as we wanted. This works even though there is
not a Some_never_before_used_tag
function in the fasthtml.components
source code (you can verify this yourself by looking at the source
code).
Tip
Typically these tags are needed because a CSS or Javascript library created a new XML tag that isn’t default HTML. For example the
zero-md
javascript library looks for a<zero-md></zero-md>
tag to know what to run its javascript code on. Most CSS libraries work by creating styling based on theclass
attribute, but they can also apply styling to an arbitrary HTML tag that they made up.
from fasthtml.components import Some_never_before_used_tag
Some_never_before_used_tag()
<some-never-before-used-tag></some-never-before-used-tag>
Manual Creation
The automatic creation isn’t magic. It’s just calling a python function
__getattr__
and you can call it yourself to get the same result.
import fasthtml
auto_called = fasthtml.components.Some_never_before_used_tag()
manual_called = fasthtml.components.__getattr__('Some_never_before_used_tag')()
# Proving they generate the same xml
assert to_xml(auto_called) == to_xml(manual_called)
Knowing that, we know that it’s possible to create a different function
that has different behavior than FastHTMLs default behavior by modifying
how the ___getattr__
function creates the components! It’s only a few
lines of code and reading that what it does is a great way to understand
components more deeply.
Tip
Dunder methods and functions are special functions that have double underscores at the beginning and end of their name. They are called at specific times in python so you can use them to cause customized behavior that makes sense for your specific use case. They can appear magical if you don’t know how python works, but they are extremely commonly used to modify python’s default behavior (
__init__
is probably the most common one).In a module
__getattr__
is called to get an attribute. Infasthtml.components
, this is defined to create components automatically for you.
For example if you want a component that creates <path></path>
that
doesn’t conflict names with
pathlib.Path
you can do that. FastHTML automatically creates new components with a
1:1 mapping and a consistent name, which is almost always what you want.
But in some cases you may want to customize that and you can use the
ft_hx
function
to do that differently than the default.
from fasthtml.common import ft_hx
def ft_path(*c, target_id=None, **kwargs):
return ft_hx('path', *c, target_id=target_id, **kwargs)
ft_path()
<path></path>
We can add any behavior in that function that we need to, so let’s go through some progressively complex examples that you may need in some of your projects.
Underscores in tags
Now that we understand how FastHTML generates components, we can create
our own in all kinds of ways. For example, maybe we need a weird HTML
tag that uses underscores. FastHTML replaces _
with -
in tags
because underscores in tags are highly unusual and rarely what you want,
though it does come up rarely.
def tag_with_underscores(*c, target_id=None, **kwargs):
return ft_hx('tag_with_underscores', *c, target_id=target_id, **kwargs)
tag_with_underscores()
<tag_with_underscores></tag_with_underscores>
Symbols (ie @) in tags
Sometimes you may need to use a tag that uses characters that are not allowed in function names in python (again, very unusual).
def tag_with_AtSymbol(*c, target_id=None, **kwargs):
return ft_hx('tag-with-@symbol', *c, target_id=target_id, **kwargs)
tag_with_AtSymbol()
<tag-with-@symbol></tag-with-@symbol>
Symbols (ie @) in tag attributes
It also may be that an argument in an HTML tag uses characters that can’t be used in python arguments. To handle these you can define those args using a dictionary.
Div(normal_arg='normal stuff',**{'notNormal:arg:with_varing@symbols!':'123'})
<div normal-arg="normal stuff" notnormal:arg:with_varing@symbols!="123"></div>