How can I add Alt Text to an image?

When I add an Image to my form and inspect the resulting html I see:

<img src="_/theme/Bad.png" style="max-width: 100%;">

I do not see an “alt text” Image property.

I need to produce:
<img src="_/theme/Bad.png" style="max-width: 100%;" alt="Bad">

What are my options?

Hi @sweetdavida, welcome to the forum!

I can think of a jQuery solution… how comfortable are you with that?

Maybe someone else has a more Anvil based approach… but I couldn’t come up with one…

This should work… in your form code:

js.call_js("add_alt_text", "Bad", self.image_1)

then in your native libraries

<script>
  function add_alt_text(alt_text, component){
    component = component.v._anvil.element;
    component.attr("alt", alt_text);
  };
</script>
3 Likes

Thanks. The script as you posted adds the alt to the div, not the image. So I am still working on this…

:man_facepalming: - oops

Ok - try this:

move to your form show event…

def form_show(self, **event_args):
    js.call_js("add_alt_text", "Bad", self.image_1)

add the find command…

<script>
  function add_alt_text(alt_text, component){
    component = component.v._anvil.element;
    component.find('img').attr("alt", alt_text);
  };
</script>
1 Like

Thank you for that answer. It works on a static form in the “show” event.
However, I need the alt on an image in a RowTemplate and I am still having issues.
Currently the code sets the image source and corresponding alt text in the “refreshing_data_bindings” event.

  else:
    self.image_1.source = "_/theme/Bad.png"
    js.call_js("add_alt_text", "Bad", self.image_1)

This works for the image, but the alt never makes it into the html:
image
The image is being set on the object as can be seen in the console log, but this must be after the html has been generated?
image
Does anyone know why the source makes it, but the alt text doesn’t? Any other thoughts?

I think we should move this to a feature request?

I couldn’t work out how to add the alt text attribute to the img element before form show. And the solution is a very convoluted which is a shame…

Ideally anvil would just have an alt text option in img properties.

2 Likes

Think I’ve got a solution.

Custom component - not sure why I didn’t think of it earlier 🤦.

Is it 1 image or lots of images? This will change the approach somewhat.

For 1 image:
Have you used the custom HTML forms much?

Add a new custom HTML form.
In the custom HTML create your HTML code as you’ve described.

Then in the app browser side bar for this form click ‘use as component’

You can then add this component to your main form and it will have the alt property you require.

If any of those steps are unclear I’ll get you a clone link or add some images and code when I get a chance.

Here’s a dependency you can use… that has an image component with an alt text option…
https://anvil.works/build#clone:4QGV5KUAC3GBQAPH=OJ6CC37KJOJIABNGUMI7FALN

It has two properties - source and alt. You can set these in properties or in code.

self.image_alt_1.source = "_/theme/bad.png"
self.image_alt_1.alt = "Bad"

I think it’s what you’re after…

Screen Shot 2020-02-22 at 16.51.01

To use it as a dependency clone the app. (Rename it to ImageAltComponent)
Then in your Main App go to

  • :gear: settings
  • :jigsaw: dependencies
  • add a dependency - ImageAltComponent


For those interested here’s the code for the component (no javascript required and much more in an anvil style :innocent:):

class ImageAlt(ImageAltTemplate):
  _source = ''
  _alt = ''
  
  def __init__(self, **properties):
    self.init_components(self, **properties)
    
  @property
  def source(self):
    return self._source
  
  @source.setter
  def source(self, value):
    self._source = value
    self.html = f'<img src="{self._source}" alt="{self._alt}" style="max-width: 100%; display: block; margin: auto;" >'
    
  @property
  def alt(self):
    return self._alt
  
  @alt.setter
  def alt(self, value):
    self._alt = value
    self.html = f'<img src="{self._source}" alt="{self._alt}" style="max-width: 100%; display: block; margin: auto;" >'
    

The initial custom html is as above, but with a placeholder image so that something appears when you add the component into the app design view.

4 Likes

Thanks again. That worked, only now the click/mousedown event is not there.
I couldn’t find a basic example of how to map those html events to an anvil event. I am not strong in javascript. Perhaps someone can point me to a good example there too.

I do think that your earlier statement about this being a feature request is a good one.
Having alt text is a basic requirement for accessible web pages and it appears to have been overlooked. For example this app’s ‘chrome audit rating’ is being downgraded without alt text:

It is great that there are all these ways to try to get this to work, but ‘alt’ is mainstream and we are working pretty hard for this.

1 Like

Hello @sweetdavida, you are free to open a feature request here on the forum if you have not already.

1 Like

@stucork, thanks for all your help. I did get it to work by adding an onclick event to the image, and adding javascript to raise the anvil component event. Thanks again.

No worries. What did you want to happen when the image is clicked?

I might have a play to add the event.

just in case it’s useful the clone link has been updated with the a click event… I changed the cursor to a pointer just because… :point_up_2:… and added a jquery function to set the event handler (in the native libraries)

<script>
  function _on_click () {
    this.on('click', function() {
      anvil.call(this, '_click')
    })
  };
</script>

then this is the code for the component:

class ImageAlt(ImageAltTemplate):
  _source = ''
  _alt = ''
  
  def __init__(self, **properties):
    self.init_components(self, **properties)
    self.call_js('_on_click')
    
  @property
  def source(self):
    return self._source
  
  @source.setter
  def source(self, value):
    self._source = value
    self.html = f'<img src="{self._source}" alt="{self._alt}" style="max-width: 100%; display: block; margin: auto;cursor: pointer;" >'

    
  @property
  def alt(self):
    return self._alt
  
  @alt.setter
  def alt(self, value):
    self._alt = value
    self.html = f'<img src="{self._source}" alt="{self._alt}" style="max-width: 100%; display: block; margin: auto;cursor: pointer;" >'

  def _click(self):
    self.raise_event('click')

2 Likes

great - i’ll move it to a feature request…

2 Likes