Label with XHTML Content setCaption() removes formatting

Hello,

My Vaadin application has a Label that displays the status of another Java application (Online/Offlline), through a database query.

When the component is instantiated, i use the following code:

engineLabel = new Label("<b>Engine Status:</b> Verifying... " + "<b>|</b>", Label.CONTENT_XHTML);

Then, the caption is updated when the database returns the status:

if(isRunning.getOnOff())
{
	engineLabel.setCaption("<b>Engine Status:</b> <font color=\"green\">Running</font> " + "<b>|</b>");
}
else
{
	engineLabel.setCaption("<b>Engine Status:</b> <font color=\"red\">Offline</font> " + "<b>|</b>");
}
engineLabel.setContentMode(Label.CONTENT_XHTML);
engineLabel.requestRepaint();

The problem is that the label loses it’s XHTML formatting after using the setCaption(), displaying content as plain text, even if i set the content mode with engineLabel.setContentMode(Label.CONTENT_XHTML).

If there is a better approach to this situation, please let me know…

Also, engineLabel.requestRepaint() does not refresh the component, maybe with the progress indicator hack I can get it to refresh periodically.

You should use setValue() instead of setCaption().

It is working now, thanks a lot!

I have a similar issue with formatted captions. In my case the label’s caption should match the the number of line breaks in the value so that the caption is on the same level as the first line of the potentially multiline value. The problem looks like AbstractComponent’s paint() method which calls target.addAttribute, while paintContent() chooses the proper text formatter based on the content mode. Unfortunately paint() is declared final, so I see no obvious way around this. What’s the obvious solution that I am missing?

replacing the same clause in paint() with a call to this method would be one option:


public void paintCaption(PaintTarget target) throws PaintException {
      if (getCaption() != null) {
                    target.addAttribute("caption", getCaption());
      }
  }

Captions are a little different from values. They are not rendered by the component itself (with some exceptions like Button) but by the layout containing the component. Furthermore, the text of the caption is set with DOM.setInnerText() so no HTML or similar formatting would be allowed even if the server would send some. UTF-8 text within the caption is ok. CSS in themes might also cause line feeds etc. to be ignored in captions even if the server would send some - not sure if this is the case.

I would recommend not using the caption of a Label but instead another Label for displaying your “captions” with any formatting you want. This is simple enough to do with some layouts (GridLayout, often CssLayout, …), although FormLayout would be a problem and should be replaced with a GridLayout in that case.

Henri,
Thanks for the tip. There was a reason for paint being final. I should have waited before diving in, but I did get the joy of building the vaadin package a couple times. I ended up replacing DOM.setInnerText with DOM.setInnerHTML in VFormLayout. I think all of my form captions are either plain text or text followed by a variable number of “
&nbps;” strings I don’t think this will pose much of a problem.

I had originally considered using GridLayout, but FormLayout seemed semantically more correct for laying out labeled data, e.g. the captions are styled like all other caption.