class HtmxTags(Tags):
def tag_column(self) -> Column:
"""Component to be used in Grid
Returns:
Column: column object instance that returns the htmx
"""
return Column(
self.name,
lambda row: self.htmx_form(row.id),
required_fields=[self.table.id],
)
def htmx_form(self, record_id: int):
"""html component for tag POST and DELETE via htmx
to be functional the tag_endpoint has to be exposed by a controller
Args:
record_id (int): record ID
Returns:
DIV: html
"""
endpoint = f"/{request.app_name}"
tag_table = self.tag_table
tag_tablename = tag_table._tablename
db = tag_table._db
inline_id = f"{tag_tablename}-{record_id}"
spans = []
rows = db(tag_table.record_id == record_id).select()
# return [row.tagpath.strip("/") for row in rows]
for row in rows:
# tag_row = self.tag_table[row.tag_id]
tag_html_id = f"{tag_tablename}-{record_id}-{row.id}"
hx_delete = f"{endpoint}/htmx/{tag_tablename}/{row.id}"
button = BUTTON(
_class="delete is-small",
**{
"_hx-delete": hx_delete,
"_type": "button",
"_hx-on:click": f'document.getElementById("{tag_html_id}").remove()',
},
)
span = SPAN(row.tagpath.strip("/"), button, _class="tag", _id=tag_html_id)
spans.append(span)
div_tags = DIV(*spans, _class="tags")
input_div = DIV(
P(
INPUT(
**{
"_class": "input is-small",
"_name": "tag",
"_type": "text",
"_placeholder": "enter tag",
}
),
_class="control",
),
P(
BUTTON(
SPAN(I(_class="fas fa-check"), _class="icon is-small"),
**{
"_class": "button is-small is-success",
"_hx-post": f"{endpoint}/htmx/{tag_tablename}/{record_id}",
"_hx-target": f"#{inline_id}",
"_hx-include": "closest div",
"_hx-trigger": "click",
"_hx-swap": "outerHTML",
},
),
_class="control",
),
_class="field has-addons",
)
return DIV(div_tags, input_div, _id=inline_id)
def enable(self, uses: Tuple = ()) -> None:
"""Register the htmx endpoint needed for using the tag_column in a Bulma grid
Args:
uses (Tuple, optional): uses that are passed ot the action.uses
decorator. Defaults to ().
"""
route = f"htmx/{self.tag_table._tablename}/<path:path>"
@action(route, method=["POST", "GET", "DELETE"])
@action.uses(*uses)
def _(path=None):
# if the method is DELETE the ID is for the join table
if request.method == "DELETE":
tag_id = int(path)
tag_row = self.tag_table[tag_id]
record_id = tag_row.record_id
tag_row.delete_record()
return self.htmx_form(record_id)
# if the method is POST the ID is for record table
elif request.method == "POST":
record_id = int(path)
post_vars = request.POST or {}
tag = post_vars.get("tag")
if tag:
self.add(record_id, tag)
return self.htmx_form(record_id)