I want to generate a Cell for a CellWidget with the UiBinder (UiRenderer). What I did to generate the cell is in MyCell.java:
public class MyCell implements AbstractCell<MyDto> {
public interface Resources extends ClientBundle {
#Source({Css.DEFAULT_CSS })
Css css();
}
public interface Css extends CssResource {
String DEFAULT_CSS = "test/MyStyle.css";
String test();
}
interface MyUiRenderer extends UiRenderer {
void render(SafeHtmlBuilder sb, String name, SafeStyles styles);
}
private static MyUiRenderer renderer = GWT.create(MyUiRenderer.class);
Resources resources = GWT.create(Resources.class);
#Override
public void render(SafeHtmlBuilder safeHtmlBuilder, MyDto model) {
SafeStyles style = SafeStylesUtils.fromTrustedString(resources.css().test().toString());
renderer.render(safeHtmlBuilder, model.getName(), style);
}
}
My MyCell.ui.xml file looks like this:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>
<ui:with field="name" type="java.lang.String" />
<ui:with field='styles' type='com.google.gwt.safecss.shared.SafeStyles'/>
<div style="{styles}"><ui:text from="{name}" /></div>
</ui:UiBinder>
MyStyle.css:
.test {
background-color: red;
font-size: 20px;
display: flex;
...
}
When I run my code I get the following error:
[DEBUG] [mobile] - Rebinding test.client.app.MyCell.MyUiRenderer
[DEBUG] [mobile] - Invoking generator com.google.gwt.uibinder.rebind.UiBinderGenerator
[ERROR] [mobile] - java.lang.String required, but {styles} returns com.google.gwt.safecss.shared.SafeStyles: <div style='{styles}'> (:9)
[ERROR] [mobile] - Deferred binding failed for 'test.client.app.MyCell.MyUiRenderer'; expect subsequent failures
[ERROR] [mobile] - (GWT.java:72) 2014-06-08 17:15:05,214 [FATAL] Uncaught Exception:
Then I tried to this:
<ui:with field="styles" type="java.lang.String" />
in my UiBinder but it does not work.
How can I use css style from a CssResource in my UiRenderer?
<div style="{styles}">
Two problems here. First, in order to change the style of an element, you have two options, setting the style attribute to include specific properties, or set the class attribute to point to a class you’ve defined in CSS somewhere. So, you really want to set class here, not style.
Second, you created a css class called "test", but are assigning here just the whole interface, styles. Instead, reference styles.test:
<div class="{styles.test}" />
Edit: one final piece you may be missing (but since "This does not work" is so vague I don't know if this is your actual problem): I don't see any call to ensureInjected() in your example. Make sure you call this on your Css instance before using it.
you have to put .asString after styles in the xml:
<div style="{styles.asString}"><ui:text from="{name}" /></div>
Related
I have a component implementing RouterLayout like this:
#Tag("side-menu")
#HtmlImport(value = "src/components/side-menu.html")
public class SideMenu extends PolymerTemplate<TemplateModel> implements RouterLayout {
#Id("menu")
private PaperListBox listBox = new PaperListBox();
public SideMenu() {
listBox.addMenu(new PaperItem("tutorial", TutorialView.class));
listBox.addMenu(new PaperItem("icons", IconsView.class));
}
}
I route a view child of the parent layout
#Route(value=IconsView.VIEW_ROUTE, layout = SideMenu.class)
public class IconsView extends Div {
public static final String VIEW_ROUTE = "icons";
public IconsView() {
add(new Label("ICONS VIEW"));
}
}
But the result overwrote all the content of side-menu.html file.
side-menu.html template base format
<side-menu>
<div>App Name</div>
<div id="menu"></div>
<div id=contenido><!-- I want to show here my view Icons --></div>
</side-menu>
But the result it's
<side-menu>
<div>
<label>ICONOS VIEW</label>
</div>
</side-menu>
The expected result is:
<side-menu>
<div>App Name</div>
<div id="menu"></div>
<div id=contenido>
<div>
<label>ICONOS VIEW</label>
</div>
</div>
</side-menu>
In vaadin documentation said this:
You can add child components to templates using the Component or
Element API, but because PolymerTemplate uses the shadow DOM the
shadow tree is rendered instead of the elements children that are in
the light DOM.
This means that the template needs to have a <slot></slot> to mark
the place where the light DOM elements should be rendered.
I found a solution for this composite layout:
I only needed to be modified my template side-menu.html and add a <slot> tag like this:
<side-menu>
<div>App Name</div>
<div id="menu"></div>
<slot></slot>
</side-menu>
And then when my view is loaded, it's rendered into the <slot> tag into the template
The problem in your case is that since you have bare template without functionality and databinding and custom template model, the server side is not aware of its contents. Thus Div.add() thinks it as empty div and overwrites its content.
One approach in your case would be to modify the content via Element API, which could be something like:
public IconsView() {
label = new Label("ICONS VIEW");
getElement().appendChild(label.getElement());
}
See API spec
https://demo.vaadin.com/javadoc/com.vaadin/vaadin-core/10.0.0.rc5/com/vaadin/flow/dom/Node.html#appendChild-com.vaadin.flow.dom.Element...-
Another approach would be to extend the html template to be fully functional polymer element
There is more about that e.g. here:
https://vaadin.com/docs/v10/flow/polymer-templates/tutorial-template-list-bindings.html
Lets say there are two scala templates in view folder
file1.scala.html
container.scala.html
Now I want to pass first template into 2nd template (container.scala.html) from controller. Like:
public class Application extends Controller {
static Result isItPossible()
{
Result theFile=ok(file1.render());
return ok(container.render(theFile));
}
}
Is it possible? If it is, How I can do it?
You can pass a rendered template to the container template. container would need to have some Html parameter:
container.scala.html:
#(content: Html)
<p>Here's my content: #content </p>
And from within the controller:
public class Application extends Controller {
return ok(container.render(file1.render()));
}
It's worth to mention that you don't need to combine your wrapping containers in the controller, as template engine has an ability to use Layouts for it (as described in docs). In that case you can use it like that:
container.scala.html
#()(content: Html)
<p>Here's my content: #content </p>
file1.scala.html
#container() {
<b>this is content of <i>file1</i> template</b>
}
controller
public class Application extends Controller {
static Result itIsPossible() {
return ok(file1.render());
}
}
I am trying to edit the Text of the textfield in Vaadin. I created a file (\WebContent\VAADIN\themes\loginthemes\style.css) with ONLY the following information:
textstyle {
font-family: HelveticaRounded;
font-size: 40px;
font-style: bold;
}
And inside my java file I have the following:
TextField username = new TextField("Username: ");
username.setStyleName("style");
// I also tried username.setStyleName("loginthemes");
The text for the textfield stays the same.
As Jan Galinski said, you should define a proper theme.
For one named "logintheme" you should create VAADIN/theme/logintheme/style.scss as :
#import "../reindeer/reindeer.scss";
.logintheme {
#include reindeer;
.textstyle {
font-family: HelveticaRounded;
font-size: 40px;
font-style: bold;
}
}
Tell the UI to use it:
#Theme("logintheme")
public class MyUI extends UI {
}
Also, your usage of setStyleName() is incorrect: the parameter is the name of your CSS class, not the name of the theme.
So in your case, it should be:
TextField username = new TextField("Username: ");
username.setStyleName("textstyle");
You must specify the theme on your UI class.
#Theme("logintheme")
public class MyUI extends UI {
}
also, you should reference an existing theme via #import, else your theme will look very "reduced".
How can I get add an icon with text to a menu item in GWT?
The following does not work:
<ui:with field='res' type='my.package.MyResources' />
<g:MenuItem text="test"><g:Image resource="{res.myIcon}" /></g:MenuItem>
Resulting error:
Not allowed in an HTML context: <g:Image resource='{res.myIcon}'>
public interface MyResources extends ClientBundle {
#Source("myIcon.png")
ImageResource myIcon();
}
The MenuItem allows only HTML or plain text as its content. So you cannot use an Image widget, but you can very well use an <img> element and retrieve the image URL from the ImageResource referenced by <ui:with> using getSafeUri() (you can call no-arg methods in UiBinder templates). In your case:
<g:MenuItem>
<img src="{res.myIcon.getSafeUri}"/><span>Your text here</span>
</g:MenuItem>
Or programmatically, using a simple template:
public interface MyTemplate extends SafeHtmlTemplates {
#Template("<img src=\"{0}\" /><span>{1}</span>")
SafeHtml createItem(SafeUri uri, SafeHtml message);
}
instantiated via:
MyTemplate template = GWT.create(MyTemplate.class)
and used like so:
new MenuItem(template.createItem(
yourResources.myIcon().getSafeUri(),
SafeHtmlUtils.fromString("Your text here")));
Please try this
<g:MenuItem>
<div class="className"/> MyMenuWithImg
</g:MenuItem>
That css class have the background image.
I ended up extending the GWT MenuItem class in a way that one can supply an ImageResource from ui-binder:
class MyMenuItem extends MenuItem {
#Uresstructor
public resMenuItem(String text, ImageResource res) {
super(SafeHtmlUtils.fromString(text));
ImageResourceRenderer renderer = new ImageResourceRenderer();
setHTML(renderer.render(res) + " " + text);
}
}
Usage:
<ui:with field='res' type='path.to.MyIconResources' />
<g:MenuBar>
<my:MyMenuItem text="test" icon="{res.myIcon}" />
</g:MenuBar>
If anyone comes up with a better idea (now or in the future) please comment accordingly.
How to update the style of a JSF component at runtime, I must clarify that I want to change the position of the component and in some cases hide it.
<ui:define name="reverso" id="reverso" >
<!-- Logo Estado Próspero -->
<p:graphicImage value="./resources/oficiales/prospero.png" style="width: 90px; height: 50px;position: relative; left: 150px" />
<h:form id="dataRfc">
<h:outputText id="display_rfc" rendered="true" value="#{IDWizard.rfc}" binding="#{IDWizard.outRfc}" style="color: #333333;text-align:center;margin-top: 30px" />
</h:form>
</ui:define>
public void setNoPersonal(String noPersonal) {
this.noPersonal = noPersonal;
this.outNombre.setValue(this.noPersonal);
this.outNombre.setRendered(true);
this.outRfc.setStyle("text-align:left;color:red;margin-top:2px");
//component.getAttributes().put("style", "color:red");
this.outRfc.setRendered(true);
}
You can just use EL expressions in the style and styleClass attributes. You can use the conditional operator ?: in EL to print different strings based on a boolean condition.
E.g.
<h:someComponent styleClass="#{bean.show ? 'show' : 'hide'}" />
with this getter
public boolean isShow() {
return show;
}
and this CSS
.show {
display: block;
}
.hide {
display: none;
}
Note that the above still renders the component to the client side, so you would be able to toggle the visibility using plain JavaScript.
Or, if you actually want to show/hide it entirely server side, then you could use the rendered attribute for this instead. It also just accepts EL expressions:
<h:someComponent rendered="#{bean.show}" />
You only need to keep in mind that when this evaluates false, then this component is not present in the client side at all, so you won't be able to show it again using plain JavaScript or Ajax. When showing it using Ajax, you need to re-render its parent component instead.
Update based on your new code snippet, this is not the right way. You should not bind the component to the bean for this. You should also define CSS styles in its own .css file which is much easier to maintain and keeps your bean and view from specific CSS clutter.
E.g. (I randomly guess that the styles are dependent on some kind of error/success state)
<h:outputText id="display_rfc" value="#{IDWizard.rfc}" rendered="#{IDWizard.show}"
styleClass="#{IDWizard.success ? 'success' : 'error'}" />
with those getters
public boolean isShow() {
return show;
}
public boolean isSuccess() {
return success;
}
and this CSS
.success {
text-align: center;
color: #333333;
margin-top: 30px;
}
.error {
text-align: left;
color: red;
margin-top: 2px;
}
You just have to set those booleans accordingly in bean's (post)constructor or action(listener) method.