Custom HTML Properties

Hi There,
I wanted to create a Custom bade Label component. This involved having a data-badge= property in the HTML. I can get that all added with the custom HTML that all works lovely.

What I was wondering is is there a way to pass a variable to the HTML. So I can pass a custom value for that data-bade.

An example may help make this more clear:

In my Custom HTML I have

<a href="" class="badge1" data-badge="27">Badge Notification Example</a>

What I would like to be able to do is pass a variable to the data-bade= part and change that to some variable that I am pulling out of the database.

I was then hoping I could make this into a reusable component.

Thanks for any help you can provide.

Cheers

Please see link for badge example: http://www.cssportal.com/blog/create-css-notification-badge/

Assuming Iā€™ve not misunderstood ā€¦

you could create a JS function that adds the attribute to an HTML component and call that JS function from Anvil (there are some examples in the forum).

You can add a role to a component which in HTML land adds a class of ā€œanvil-role-<yourrolename>ā€. You could use this to identify the component (getElementsByClassName()).

If Iā€™m barking up the right tree Iā€™ll try and expand on that :slight_smile:

1 Like

Thanks for the reply David, I think I should be able to do that with the custom JS function as you mentioned in your post here:

I shall report back!

Aha, hit a slight snag, it seems as though you cant use call_js in a Repeating Group form?

True
AttributeError: ā€˜ThisMonthā€™ object has no attribute ā€˜call_jsā€™
at ThisMonth, line 18
called from Dashboard, line 24

Could you paste the code for that form (either here or in PM)?
Iā€™ve not tried but i donā€™t think Anvil makes the distinction.

edit -

Hang on - you may need to call it from the parent form. The line item form is not a custom form and as such probably wonā€™t have that facility. Iā€™ll try it when I get a moment.

Ok, this works -

donā€™t use the automatically created line item form - create a new form of custom html type and set that as the repeating panel line item form instead.

You can add the JS to the custom form as normal and you can definitely call JS from there - just tried it.

https://anvil.works/ide#clone:UP2WQUKH6L3FYCR7=Y4I75DQFPDRT4EKGV4MBAYJF

Not from the same form but here is another project that I am working on that has the same requirement for the badge:

CompetiorTable Form:

from anvil import *
import anvil.server
import tables
from tables import app_tables

class CompetitiorTable (CompetitiorTableTemplate):
  def __init__(self, **properties):
    # You must call self.init_components() before doing anything else in this function
    self.init_components(**properties)

    # Any code you write here will run when the form opens.
    
    if self.item['keyword']['keyword'].lower() in self.item['title'].lower():
      self.inTitle.text = 'Yes'
    else:
      self.inTitle.text = 'No'
    
    if self.item['keyword']['keyword'].lower() in self.item['description'].lower():
      self.inDescription.text = 'Yes'
    else:
      self.inDescription.text = 'No'

Dashboard Form that uses Competitor Form as a Repeating Panel:

from anvil import *
import anvil.server
import tables
from tables import app_tables

class Dashboard (DashboardTemplate):
  def __init__(self, **properties):
    # You must call self.init_components() before doing anything else in this function
    self.init_components(**properties)

    # Any code you write here will run when the form opens.
    

  def GetInfo_click (self, **event_args):
    # This method is called when the button is clicked
    
    self.keyword = anvil.server.call('save_keyword_search',self.keywordBox.text,'10')
    self.competitorRepeatingPanel.items = anvil.server.call('get_videos',self.keyword['keyword'])
    self.resultsLabel.text = "{:,}".format(self.keyword['results'])
    self.results_panel.visible = True

So on the competitor table form. I will want to add a badge to each row that will be dependant upon a variable that I will be bringing in.

The issue is I cant seem to call call_js from the competitors form

Hope that helps and thanks for your time and help David.

Did you see my updated reply about swapping the autogenerated item form for a custom form (they might have crossed when posting)? I think that will do what you want. If not, let me know.

Ah sorry David, I missed it as I was reediting my posts constantly hehe. Iā€™ll take a look at that now and report back.

Thanks

Glad to see youā€™re working towards a good solution here. Iā€™m just jumping into this thread to issue my ritual warning about not accidentally introducing injection vulnerabilities into your app!

Specifically, you should get nervous any time you are just injecting HTML into a page. That HTML has probably been constructed with something that might have come from a user (either immediately, or something they might have entered into a database). If a malicious user can make you put arbitrary HTML into your pageā€¦they own your app, and can do malicious things. Generally, each time you use jQueryā€™s .html() function or set the innerHTML DOM propertiesā€¦take care. Often you can use something safer (eg setting a textContent ona DOM node or jQueryā€™s .text() function), or escape any special HTML characters (take care).

Note: This answer was updated to reflect Anvilā€™s JS integration, which was not available when this thread was first created

In this case, you can get away with setting the attribute. At the top of your Custom HTML form, you can do:

import anvil.js

And then in your code:

  badge = anvil.js.get_dom_node(self).querySelector(".badge1")
  badge.setAttribute("data-badge", 27)
2 Likes

Brilliant, thanks Meredydd & David you have both been a great help. I think these bits will get me to where I want (Meredydd, just to check so using the .attr that should be enough to keep the app injection safe?)

Meredydd, just to check so using the .attr that should be enough to keep the app injection safe?

Yes, if youā€™re setting something harmless like a data-* attribute. (Obviously some attributes are dangerous - if you can set an href or an onclick attribute, someone can get Javascript into there!)