How to set Widget as Anchor content in GWT instead of the usual String? - gwt

I'm in a situation where I want a whole Widget to be a link to another page. Both Anchor and Hyperlink only accept Strings or SafeHTML as visual representation. However, I need e.g. a <div>...</div> to be a link.
This would be similar to:
<div><p>This whole thing is a link</p></div>
Is there a way to do this withou custom coding my own SafeHTML? To be more concrete, I want a GXT HBoxLayoutContainer to be clickable and bookmarkable.

The easiest solution would be using UiBinder:
<ui:UiBinder
xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container">
...
<g:HTMLPanel>
<a href="somesite">
<container:HBoxLayoutContainer>...</container:HBoxLayoutContainer>
</a>
</g:HTMLPanel>

Related

GWT anchor to kick off new css class

Im building a nav menu and am struggling with something really simple here. In my UI binder i have this
<header class="{res.css.mainHeader}">
<a href="#{res.css.mainNav}" class="{res.css.openMenu}">
open
</a>
<a href="#" class="{res.css.closeMenu}">
close
</a>
<h1>new header</h1>
</header>
So when I write and test this in html, it works fine. you click on the word open, and everything animates, shows all the cool stuff, the world is a happy place. But i can't figure out how to translate this into GWT.
When I run the above code, I get this error
[WARN] [itrgwtprototype] - Escaping unsafe runtime String expression used for URI with UriUtils.fromString(). Use SafeUri instead: <a class='{res.css.openMenu}' href='#{res.css.mainNav}'> (:20)
But I have a sneaking suspicion that GWT has a better way to do it than SafeUri. How do i make this work? The CSS stuff is correct, but the anchor click is whats messed up.
thanks.
You are setting the anchor href property with a css value (href="#{res.css.mainNav}").
If you want to translate it entirely in GWT you should listen to ClickEvent on you open menu and then do something like open a panel or something else. In order to do so you can replace the anchor with a Label (or InlineLabel) and listen on click events on it.

anchor element click event

I have been using uibinder for a while and got pretty good at it. I know all about the use of HTMLPanel and Anchor for adding click handlers. However, there are cases where this design approach simply doesn't fit the bill.
say I have a unordered list, and each list has some anchor elements.
<ul><li><a ...></li>...</ul>
it is good to make each li as a component (java class) so you can add multiple instances of the component inside the ul. this means inside the ui.xml, you start with li (no other way that I can see). but then there is no way to insert Anchor inside. you can not replace li with HTMLPanel since that would create a div which you don't want.
by leave the anchor as a in this uibinder, there would be no way to detect the anchor click event.
any ideas?
In your HTML, set ID to the anchor :
<a id='testachor'>...</a>
In your GWT code, wrap the anchor into a widget:
Anchor testAnchor = Anchor.wrap(Document.getElementById('testanchor'));
Then add click handler to it:
testAnchor.addDomHandler(new ClickHandler(){...}, ClickEvent.getType());
You can add Anchor widget inside <li> tag:
<g:HTMLPanel>
<ul>
<li>
<g:Anchor ui:field="link" />
</li>
</ul>
</g:HTMLPanel>

Get UiBinder widget to display inline instead of block

I'm trying to get my UiBinder-defined widget to display inline, but I can't. My current code is:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:style>
.section {
border: 1px solid #000000;
width: 330px;
padding: 5px;
display: run-in;
}
</ui:style>
<g:HTMLPanel>
<div class="{style.section}">
<div ui:field="titleSpan" class="{style.title}" />
<div class="{style.contents}">
<g:VerticalPanel ui:field="messagesPanel" />
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
This works fine in terms of how the widget looks internally, but I want to throw a bunch of these widgets into a FlowPanel and have them flow when the window is resized. The HTMLPanel is a div, but I can't get the display attribute to assign. I can't force the style name, since the following throws an error:
<g:HTMLPanel styleNames="{style.section}">
And I can assign an additional style, but it doesn't apply the display setting.
<g:HTMLPanel addStyleNames="{style.section}">
This displays the border and sets the size, as expected, but it doesn't flow. Firebug shows the styles on the div are border, width, and padding, but no display.
Is there a way to make a widget in UiBinder so that it'll display inline instead of block? And if so, can I make it compatible with having a VerticalPanel inside (can I do it without making the entire widget pure HTML without any GWT widgets)?
PS: I saw question 2257924 but it hasn't had any answers lately, and he seems to be focused on getting a tag, not specifically getting inline layout. I don't care directly about , if I can just get the top-level tag for my widget to flow inline, I'm happy.
It seems your problem is caused by using display: run-in instead of the more "standard" display: inline. IE and Firefox don't support run-in and it seems that Firebug prunes the style upon adding.
Try changing the style to display: inline (or inline-block if you want some properties of a block, like width, but beware of the quirks of IE + inline-block).
It should be <g:HTMLPanel styleName="{style.section}">, not <g:HTMLPanel styleNames="{style.section}"> - styleNames is a typo (which appears in the UiBinder docs, so I'm sure that's where you got it from). styleName is the correct thing to use.
Also, Igor Klimer is correct that you should use display: inline or display: inline-block rather than display: run-in.
In general, you can tell the available attribute names by looking for setXXX methods on the UIObject class, and the attribute name is just the XXX. So, UIObject has a setStyleName method, which you access using the attribute called styleName.

Trying to get UIBinder to give me a span not a div

I am building a widget with UiBinder, and I need to have it enclosed in a <span /> but UiBinder only gives me <div />. E.g. <g:HTMLPanel /> => <div />. HorizonPanel, FlowPanel, VerticalPanel also give out only <div />.
Does any one know a solution?
Try this:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:HTMLPanel tag="span">
<!-- your stuff -->
</g:HTMLPanel>
</ui:UiBinder>
You can keep using a <div> but just add display: inline to its CSS, which will make it display as though it were a <span>.
Edit: fixed place at the end where I said 'div' but meant 'span'.
With regards to the answer above by Robert (sorry I can't figure out how to comment that directly)
This won't work out of the box, as widgets can't be placed inside plain HTML (the compiler will give you "error: found widget in html context"). But there's a simple workaround:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:HTMLPanel>
<span>
<!-- Your content with widgets goes here -->
</span>
</g:HTMLPanel>
</ui:UiBinder>
One other useful thing to mention is InlineHTML and InlineLabel widgets capable of holding arbitary html or plain text respectively in a <span>

Embeding a TabLayoutPanel inside a DockLayoutPanel

I'm trying to embed a TabLayoutPanel inside a DockLayoutPanel but the tabs are not showing up :(
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:DockLayoutPanel unit='PX'>
<g:north size='200'>
<g:HTML>
<h1>
My Header
</h1>
</g:HTML>
</g:north>
<g:center>
<g:TabLayoutPanel barUnit='PX' barHeight='3'>
<g:tab>
<g:header size='7'>
<b>HTML</b>
header
</g:header>
<g:Label>able</g:Label>
</g:tab>
<g:tab>
<g:customHeader size='7'>
<g:Label>Custom header</g:Label>
</g:customHeader>
<g:Label>baker</g:Label>
</g:tab>
</g:TabLayoutPanel>
</g:center>
<g:west size='192'>
<g:HTML>
<ul>
<li>Sidebar</li>
<li>Sidebar</li>
<li>Sidebar</li>
</ul>
</g:HTML>
</g:west>
</g:DockLayoutPanel>
</ui:UiBinder>
If you're seeing nothing at all, make sure that the TabLayoutPanel either (a) has an explicit size, or (b) is ultimately attached to the RootLayoutPanel (see http://code.google.com/webtoolkit/doc/latest/DevGuideUiPanels.html#Resize for more details).
If the problem is a lack of styling on the tabs (i.e., you're just seeing raw text where the tabs should be), you'll need to add some styles (the CSS rules you'll need are described in TabLayoutPanel's javadoc). There are not yet any default styles for TabLayoutPanel, but we'll be adding some soon.
The example from the JavaDoc is somewhat misleading - the bar height of 3 will hide the tab headings and a height needs to be specified for the body. Use something like:
<g:TabLayoutPanel barUnit='PX' barHeight='25' height="200px" >
or
<ui:style>
.tab {
height: 200px;
}
<g:TabLayoutPanel barUnit='PX' barHeight='25' styleName="{style.tab}" >
Also, you can find a basic CSS style for TabLayoutPanel on comment #5 in the following issue:
http://code.google.com/p/google-web-toolkit/issues/detail?id=4429
I have been having the same issue using the new TabLayoutPanel too (the tabs doesn't show up even if it's the only thing on the page). I decided to back to using the (now deprecated) TabPanel instead. Try and see if that works instead:
Example code:
<g:TabPanel width="100%" height="100%" ui:field="gwtimeTabPanel">
<g:Tab>
<g:TabHTML>Tab title</g:TabHTML>
<g:FlowPanel>
<!-- tab contents goes here -->
</g:FlowPanel>
</g:Tab>
</g:TabPanel>
For the people who mainly use Java code to define the UI.
Explenation
You should set the size of the parentpanel of the TabLayoutPanel and of the TabLayoutPanel itself. For instance I had a VerticalPanel and a TabLayoutPanel, I added this TabLayoutPanel to the VerticalPanel (which makes it the parentpanel of TabLayoutPanel) like this:
veticalPanel.add(tabLayoutPanel);
RootPanel.get().add(verticalPanel);
which did nothing...
Answer
you should declare the size of your panels like this
//set size
vertialPanel.setSize("100%","100%");
tabLayoutPanel.setSize("100%","100%")
RootPanel.get().add(verticalPanel);