How do I set a GWT UiBinder element's inner HTML using SafeHTML instead of a String? - gwt

I have the following element created by UiBinder:
#UiField UListElement phones;
With the following markup:
<ul ui:field="phones" class="contact section"></ul>
I had previously been using the method setInnerHtml(String) to set the value. For example:
phones.setInnerHtml("<li><span class='title'>" + title +
"</span><div class='phone'><a href='tel:" + number + "'>" +
number + "</a></div></li>");
I would now like to use SafeHtmlTemplates to reduce the possibility of having XSS (cross-site scripting) problems. Using a SafeHtmlTemplate, I now get back SafeHtml which I would like to stick into my phones element variable. How do I do this? I don't see a method that would take a SafeHtml type variable.

To use SafeHtml you have to stick to GWTs widgets. More specific:
With the introduction of the com.google.gwt.safehtml package, all of the core GWT library's widgets that take String arguments that are interpreted as HTML have been augmented with corresponding methods that take a SafeHtml-typed value. In particular, all widgets that implement the HasHTML (or HasDirectionalHtml) interface also implement the HasSafeHtml (or HasDirectionalSafeHtml, respectively) interface.
If Ui:Binder should generate safe html you have to set the following property in your module xml:
<set-configuration-property name="UiBinder.useSafeHtmlTemplates" value="true" />

Related

How to use a method with SafeHtml param instead of String in UiBinder (XML)?

We're migrating our application from GXT 3 to GXT 4 (and also from GWT 2.5 to 2.8.2) and one of the things that changed is that lot of components' body/text/heading/etc. now have two separate setters. One accepts String param and the other one accepts SafeHtml.
Here's an example:
public void setToolTip(SafeHtml html) {
...
}
public void setToolTip(String text) {
...
}
The difference in those is that the method accepting String does not render html elements. The other one, however, does, which is perfectly fine if one uses Java code to build UI.
Unfortunately, we do have a lot of our UI built using GWT's XML method and I would like it to stay this way.
The problem is that I cannot figure out how to show e.g. a tooltip with SafeHtml body. When I try to do that I get compilation errors.
This is what I put in my XML file:
...
<form:TextArea ui:field="testField" toolTip="{messages.testMesssage}" >
...
And this is the error:
[ERROR] java.lang.String required, but {testMess.test} returns com.google.gwt.safehtml.shared.SafeHtml: <form:TextArea toolTip='{messages.testMesssage}' ui:field='testField'> (:184)
Thanks!
You may want to look at the GXT examples for tooltips in UiBinder. In there, it shows using the ToolTipConfig instead of trying to set "tooltip" directly.
<ui:with type="com.sencha.gxt.widget.core.client.tips.ToolTipConfig"
field="toolTipConfig">
<ui:attributes title="Information" body="Prints the current document" />
</ui:with>
...
<form:TextArea ui:field="testField" toolTipConfig="{toolTipConfig}" />

Set class or ID on <h:inputHidden> in JSF

I'm trying to set a class or id parameter on a <h:inputHidden> in JSF. The code looks like this:
<h:inputHidden value="#{getData.name}" class="targ" />
But in the browser, the class isn't set:
<input type="hidden" name="j_idt6" value="j_idt6">
I need to set a class to this parameter, because I have a JavaScript autocomplete function for a <h:inputText> that sets a value in the hidden input, which needs to be passed in the next page.
Any ideas? Thanks!
I know it's a little bit late, but it can help someone in the future.
As inputHidden shows nothing in the browser there's no sense to allow it to have a class.
You can use the Id but as the Id could change as you change the component parents using it would bring some headache.
I'd suggest as a workaround, you can give it a parent so you can manipulate it by javascript.
Exemple:
JSF
<h:panelGroup styleClass="someCssClass">
<h:inputHidden id="someId" value="someValue" />
</h:panelGroup>
Javascript (using jQuery, you could use pure javascript also)
$('.someCssClass input[type=hidden]').val('yourNewValue');
None of these answers here satisfied my needs (need the PrimeFaces component, need class not ID, wrapping is too much work), so here's what I came up with:
Use pass-through attributes: https://www.primefaces.org/jsf-2-2-pass-through-attributes
Use pass:hidden-class="blah" (in my case, it's xmlns:pass up top)
Use [attribute=value] selector:
https://www.w3schools.com/cssref/sel_attribute_value.asp
document.querySelector multiple data-attributes in one element
That basically boils down to using something like this (because h:inputHidden becomes a regular input): document.querySelector("input[hidden-class=" + blah + "]")
Please, see similar question - How can I know the id of a JSF component so I can use in Javascript
You can sed "id" property, but in final html code it can be not the same, but composite: for example, if your input with id="myhidden" is inside form with id="myform", final input will have id="myform:myhidden".
In the end, I used a standard HTML <input type="hidden"> tag, as I had no advantages for using the JSF one. If you're trying to set a value in a hidden input with JavaScript, I recommend using this workaround.

Why there are so many way to set CSS for Widgets in GWT or GWTP, I am confused? Can someone clarify this?

Ok, to set a Css for a widget in Gwt or Gwtp, we can do following:
-1. directly from gwt code. Ex: label1.getElement().getStyle().setBackground("blue");
-2. include "ui:style" in UiBinder xml file, but this css only visible to that UiBinder
-3. include "ui:width" in UiBinder xml file, it will visible to all UiBinder
- and there r many way to set the Css directly to the widget in UiBinder.
The one that made me confused is that if i used , ex
<ui:with field='res' type="com.myproj.client.MyResource" />
& if myResource.css has .gwt-TabLayoutPanel then i don't need to use "addStyleNames", ex <g:TabLayputPanel />, it can recognized CSS perfectly.
However, if i add .gwt-ScrollPanel into myResource.css & use <g: ScrollPanel /> then nothing happened.
So I have to create public interface MyCssResource extends CssResource, then add String gwt-ScrollPanel(); to MyCssResource. But Java eclipse do not allow hyphen - in the method name, so I have to change to String gwtScrollPanel();.
Finally, i have to add addStyleNames into <g: ScrollPanel />, ex <g: ScrollPanel addStyleNames="{res.css.gwtScrollPanel}" /> then it will work.
That also means if i want to use .gwt-TabLayoutPanel in MyCssResource, then i need to remove the hyphen - & this will cause inconsistency in my code.
So, can someone explain to me what is going on here? I am confused?
The only think you should be aware about, is that GWT obfuscates class names when you use then in ui-binders. For instance:
<ui:style>
.gwtTabLayoutPanel {}
</ui:style>
<g:TabLayoutPanel addStyleNames="{style.gwtTabLayoutPanel}" />
.gwtTabLayoutPanel will be renamed to something like .AB in the final injected style-sheet.
But most GWT widgets, are styled with un-obfuscated class names, so for using them in ui-binders files, you have to define as external in order to prevent GWT compier to obfuscate the class name:
<ui:style>
#external .gwt-TabLayoutPanel;
.gwt-TabLayoutPanel {}
</ui:style>
<g:TabLayoutPanel />
That's because when you create a TabLayoutPanel, it has a default class called .gwt-TabLayoutPanel. So you don't need to add that class manually in to your TabLayoutPanel.Just create a TabLayoutPanel and you will see the class ".gwt-TabLayoutPanel" is already there.
But ScrollPanel doesn't comes with a default class called .gwt-ScrollPanel. It is just a div. Try creating a ScrollPanel and see. It doesn't have any classes added initially.see the screenshot
If you want to add a class called .gwt-ScrollPanel you will have to do it manually.

GWT Templates & GXT Xtemplates - how to sanitize display fields

I'm just getting into using #Template and #XTemmplate within my code.
I'm always concerned about user originated content vs trusted content.
This is the sample from GWT SafeHtml
public interface MyTemplates extends SafeHtmlTemplates {
#Template("<span class=\"{3}\">{0}: {2}</span>")
SafeHtml messageWithLink(SafeHtml message, String url, String linkText,
String style);
}
This is the sample from the GXT XTemplate doc
public interface SampleXTemplates extends XTemplates {
#XTemplate("<div>Hello, {name}!</div>")
SafeHtml hello(String name);
}
In either, is there a way in the template to declare a display field to be sanitized or trusted?
Something ala HtmlSanitizer
All String values rendered in an XTemplate/SafeHtmlTemplates are automatically sanitized - try passing in <, >, or & characters. This is true whether they are passed in to an attribute or the space between tags. If GWT cannot enure the safety of such a string (such as passing it into the href attribute of the a tag, or into a style attribute), it will emit a warning. Your first example is likely to get such a warning.
SafeHtml instances can be passed in to declare 'I know that this string is safe'. Typically, you create those using SafeHtmlUtils, a SafeHtmlBuilder instance, or another template of some kind.
Safe urls can be SafeUri instances - create them with UriUtils. This will get around the possible warning in your first example.
Safe styles can be SafeStyles instances - create them using SafeStylesBuilder instances or static methods in the SafeStylesUtils class.
And finally, as an implementation detail, XTemplates are generated by parsing out the logic and the named parameters and getters, and turned into SafeHtmlTemplates before generated into JavaScript. This ensures that anything that SafeHtmlTemplates will make safe will also be safe in XTemplates.

Custom tags in UiBinder files

When using a <g:LayoutPanel> in UiBinder.ui.xml files, you can specify <g:layer> tags. Some other Google-built widgets have special tags like that as well - <g:tab> even has a sub-tag, <g:header>.
How can I specify these for my own widgets?
The new answer to this question, after some GWT improvements, is at https://stackoverflow.com/a/11785903/439317 . Copied below to avoid moderator deletion (maybe?).
You can use #UiChild to declare special functions in your widgets accessible in UiBinders.
for example,
class MyPanel extends AbsolutePanel {
#UiChild
public void addAt(Widget w, String parameter1, String parameter2) {
....
Then, in your uiBinder, you can say
<custom:MyPanel>
<custom:at parameter1="HI" parameter2="Anything you like!">
<g:AnySingleWidget />
</custom:at>
</custom:MyPanel>
See #UiChild at http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/uibinder/client/UiChild.html
What you're looking for is a custom element parser for UiBinder. See this issue. Unfortunately it's not supported yet.
You might be interested in this post for some guidance on how to extend the current parser on your own.