Adding an anvil component into HTML

What I’m trying to do:
I use a HTML table to create 5 columns. I want some of the columns to contain Anvil components.

What I’ve tried and what’s not working:
I found this code snippet that lets me put an outlined IconButton on this page.


I couldn’t find that class defined in my app’s css or any other documentation about it.

Is it possible to use a general Anvil component inside HTML similar to this?

Sure, it’s simple.

However, one question first:

Why not just use the anvil’s DataGrid component? You can create the columns usign the designer and also put custom components inside of it easily.

In case you can’t use a DataGrid for whatever reason, you can still add custom components to HTML Slots, as defined in the page you mentioned.

When creating a form (the form that will have the HTML for a table), you need to create as a Custom HTML Form (instead of a Blank Form or other option that you have). You can then write your HTML by clicking in the three-dots menu to the right of the “Split” button and choose “Edit HTML”. Anywhere you want to put custom components you can add a slot, as is instructed in the same page you mentioned in the docs.

If you elaborate more on what exactly you want to do, we can maybe help you better.

Sorry I think I wasn’t clear in my question. I have a dummy app with two ways of doing what I want right now. The top is written with HTML tables, and the bottom is made with Anvil’s FlowPanel by specifying the width on add_component.

image

Though I found a way to get what I want to work for my app, I’m still curious if there’s a way to add a component in HTML. E.g. Let’s say that I want to use an IconButton instead of the word ‘edit’ in my example. Slots seem to be for when you want to add a component from the parent when the HTML component is used as a child component.

Reading the docs again, I think the way to add an Anvil component is to find the appropriate dom_nodes in Python and call add_component. Is that understanding correct?

The dom_nodes property return a type of read-only dict with all the anvil-names you defined in your html.

So for your html that looks like this:

<table class="meal_ingredient_row_table">
    <tbody>
      <tr>
        <!-- <td anvil-name="warning" style="width: 15%">
          <img src="_/theme/material_icons/red_warning.svg" />
        </td> -->
        <td anvil-name="warning-column" style="width: 10%">
          <button class="warning-button" anvil-name="warning-button">
            <i class="material-symbols-outlined">warning</i>
          </button>
        </td>
        <td anvil-name="quantity-column">column A</td>
        <td anvil-name="food-column">column B</td>
        <td anvil-name="edit-column" style="width: 15%"><a style="color: orange">edit</a></td>
        <td anvil-name="delete-column" style="width: 15%"><a style="color: red;">delete</a></td>
      </tr>
    </tbody>
  </table>

When you call self.dom_nodes what you get is this:

mappingproxy({
'warning-column': <HTMLTableCellElement proxyobject>, 
'warning-button': <HTMLButtonElement proxyobject>, 
'quantity-column': <HTMLTableCellElement proxyobject>, 
'food-column': <HTMLTableCellElement proxyobject>, 
'edit-column': <HTMLTableCellElement proxyobject>, 
'delete-column': <HTMLTableCellElement proxyobject>
})

If you try edit_column = self.dom_nodes['edit-column'], the content of the edit_column variable will be the js dom node for the TableCellElement, where you can add things on it, change the textContent, etc. However, this is js in python, not pure python. So to add this on it you will need to know how to handle javascript.

What I said about slots could apply here. If you change your html that has this:

<td anvil-name="edit-column" style="width: 15%"><a style="color: orange">edit</a></td>

To this:

<td anvil-name="edit-column" anvil-slot="edit-column" style="width: 15%"><a style="color: orange">edit</a></td>

Now you can add the IconButton to the column. You can even add it programatically using

de = IconButton(align='center')
self.add_component(de, slot="edit-column")

You can also remove the text “edit” automatically when the slot has a text, but I don’t remember now how to do it. Let me know if this is what you expected.

Edit: again, you can achieve the same (and easier) just using a data table component from anvil, in this simple, toy problem.

2 Likes

Your example of how to use slots was really helpful in clarifying, thank you!

I just took another read of the DataGrids component documentation. I think I will reimplement what I have with FlowPanel with this container instead. I think the items in RepeatPanel would let me get all the rows without having an explicit reference to them.

2 Likes