I want to add a TextItem component into a HLayout in SmartGwt.
I would just want to avoid adding each component to DynamicForm and then to a Layout
Instead I want to directly add a TextItem to HLayout.
public class Test4 implements EntryPoint {
DynamicForm dynamicForm = new DynamicForm();
TextItem textItem = new TextItem();
HLayout hLayout = new HLayout();
public void onModuleLoad() {
// dynamicForm.setFields(textItem);
hLayout.addMember(textItem);
hLayout.draw();
}
}
HLayout.addMember() method accepts a Widget or Canvas as an argument. TextItem extends the FormItem which doesn't extent any of the above classes. Thus it is imposible to achieve what your code states. Your only solution is to add it through a DynamicForm using the setFields() method. If you have more than one TextItems you can just call something like the below:
dynamicForm.setFields(textItem1, textItem2, textItem3, ..., textItemN);
If you do not wish to be able to change the value of the textItem you can always use a Label or create a custom widget from simpler classes to achieve the look of the TextItem.
Related
I have a Vaadin Navigator with multiple View elements. Each view has a different purpose however some also contain common traits that I have put inside custom components.
One of those custom components is the menu - it is positioned at the top and allows navigation between the different views. I create and add this component inside the constructor of each view (if you are interested in the menu's implementation see the end of this post). Here is a skeleton for each custom view:
class MyViewX implements View {
MenuViewComponent mvc;
public MyViewX() {
mvc = new MenuViewComponent();
addComponent(mvc);
}
#Override
public void enter(ViewChangeEvent event) {
}
}
So far, so good. In order to make things simple I will explain my problem using a simple label and not one of my other custom components but the dependency that I will describe here is the same for those components just like with the label.
Let's say I have a label which sole purpose is to display a greeting with the user's username. In order to do that I use VaadinSession where I store the attribute. This is done by my LoginController, which validates the user by looking into a database and if the user is present, the attribute is set and one of the views is opened automatically. The problem is that VaadinSession.getCurrent().getAttribute("username") returns null when called inside the constructor. This of course makes sense omho because a constructor should not be bound by a session-attribute.
So far I have managed to use the enter() method where there is no problem in retrieving session attributes:
class MyViewX implements View {
MenuViewComponent mvc;
public MyViewX() {
mvc = new MenuViewComponent();
addComponent(mvc);
}
#Override
public void enter(ViewChangeEvent event) {
String username = (String)VaadinSession.getCurrent().getAttribute("username");
Label greeting = new Label("Hello " + username);
addComponent(greeting);
}
}
The issue that comes from this is obvious - whenever I open the view where this label is present, a new label is added so if I re-visit the view 10 times, I will get 10 labels. Even if I move the label to be a class member variable the addComponent(...) is the one that screws things up. Some of my custom components really depend on the username attribute (in order to display user-specific content) hence I also have to place those in the enter(...) method. The addComponent(...) makes a mess out of it. I even tried the dirty way of removing a component and then re-adding it alas! in vain:
class MyViewX implements View {
MenuViewComponent mvc;
Label greeting;
public MyViewX() {
mvc = new MenuViewComponent();
addComponent(mvc);
}
#Override
public void enter(ViewChangeEvent event) {
String username = (String)VaadinSession.getCurrent().getAttribute("username");
greeting = new Label("Hello " + username);
// Remove if present
try { removeComponent(greeting); }
catch(Exception ex) { }
// Add again but with new content
addComponent(greeting);
}
}
but it's still not working. So my question is: what is the simplest way of updating a component that requires session-bound attributes?
The navigation via the menu custom component is omho not the issue here since all components of the menu are loaded in it's constructor. That's why it's also load that component in particular in a view's own constructor. Here is an example of a button in my menu that opens a view:
#SuppressWarnings("serial")
#PreserveOnRefresh
public class MenuViewComponent extends CustomComponent {
public MenuViewComponent(boolean adminMode) {
HorizontalLayout layout = new HorizontalLayout();
Label title = new Label("<h2><b>Vaadin Research Project</b></h2>");
title.setContentMode(ContentMode.HTML);
layout.addComponent(title);
layout.setComponentAlignment(title, Alignment.TOP_LEFT);
Button personalDashboardButton = new Button("Personal dashboard", new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
getUI().getNavigator().navigateTo(MainController.PERSONALDASHBOARDVIEW);
}
});
personalDashboardButton.setStyleName(BaseTheme.BUTTON_LINK);
layout.addComponent(personalDashboardButton);
layout.setComponentAlignment(personalDashboardButton, Alignment.TOP_CENTER);
// Add other buttons for other views
layout.setSizeUndefined();
layout.setSpacing(true);
setSizeUndefined();
setCompositionRoot(layout);
}
}
PERSONALDASHBOARDVIEW is just one of the many views I have.
It may be worth considering how long should your view instances "live", just as long they're displayed, until the session ends or a mix of the two. With this in mind and depending on what needs to happen when you enter/re-enter a view, you have at least the following 3 options:
1) Recreate the whole view (allowing for early view garbage-collection)
first register a ClassBasedViewProvider (instead of a StaticViewProvider) which does not hold references to the created views:
navigator = new Navigator(this, viewDisplay);
navigator.addProvider(new Navigator.ClassBasedViewProvider(MyView.NAME, MyView.class));
simple view implementation
public class MyView extends VerticalLayout implements View {
public static final String NAME = "myViewName";
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
// initialize tables, charts and all the other cool stuff
addComponent(new SweetComponentWithLotsOfStuff());
}
}
2) Keep some already created components and replace others
public class MyView extends VerticalLayout implements View {
private MySweetComponentWithLotsOfStuff mySweetComponentWithLotsOfStuff;
public MyView() {
// initialize only critical stuff here or things that don't change on enter
addComponent(new MyNavigationBar());
}
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
// oh, so the user does indeed want to see stuff. great, let's do some cleanup first
removeComponent(mySweetComponentWithLotsOfStuff);
// initialize tables, charts and all the other cool stuff
mySweetComponentWithLotsOfStuff = new SweetComponentWithLotsOfStuff();
// show it
addComponent(mySweetComponentWithLotsOfStuff);
}
}
3) Lazy creating and updating (or not) the content when entering
public class MyView extends VerticalLayout implements View {
private boolean isFirstDisplay = true;
private MySweetComponentWithLotsOfStuff mySweetComponentWithLotsOfStuff;
public MyView() {
// initialize only critical stuff here, as the user may not even see this view
}
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
// oh, so the user does indeed want to see stuff
if (isFirstDisplay) {
isFirstDisplay = false;
// lazily initialize tables, charts and all the other cool stuff
mySweetComponentWithLotsOfStuff = new SweetComponentWithLotsOfStuff();
addComponent(mySweetComponentWithLotsOfStuff);
} else {
// maybe trigger component updates, or simply don't do anything
mySweetComponentWithLotsOfStuff.updateWhateverIsRequired();
}
}
}
I'm sure (and curious) that there may be other options, but I've mainly used a variation of 1) using spring with prototype views and component tabs.
I would like to add a tooltip to a disabled text field.
Do you have any ideas how can I do it?
I'm using Vaadin 6.8.13.
When I select a specific item in combo box, disabled text field will be enabled. Otherwise, text field will be disabled
TextField readonly = new TextField("Read-Only");
readonly.setValue("I am sitting here read only");
readonly.setReadOnly(true);
readonly.setDescription("Not this time Mojojojo");
Is this what you want?
Sure, why should it not work -- unless you have not even tried it first.
Disable the TextField via setEnabled(false) and add a description via setDescription('...'):
#Grapes([
#Grab('org.vaadin.spring:spring-boot-vaadin:0.0.5.RELEASE'),
#Grab('com.vaadin:vaadin-server:7.4.4'),
#Grab('com.vaadin:vaadin-client-compiled:7.4.4'),
#Grab('com.vaadin:vaadin-themes:7.4.4'),
])
import org.vaadin.spring.annotation.VaadinUI
import com.vaadin.server.VaadinRequest
import com.vaadin.ui.*
#VaadinUI
class MyUI extends UI {
protected void init(VaadinRequest request) {
setContent( new TextField().with{
caption = "I have a Caption"
value = "And a Value"
enabled = false
description = "And have a Description"
it
})
}
}
// spring run vaadin.groovy
Try disabling the label and then putting it inside a layout. Then set that layout's description. The user won't know the difference.
VerticalLayout layout = new VerticalLayout();
TextArea textArea = new TextArea("Hello World");
textArea.setEnabled(false);
VerticalLayout textAreaWrapper = new VerticalLayout();
textAreaWrapper.addComponent(textArea);
textAreaWrapper.setDescription("Some description");
layout.addComponent(textAreaWrapper);
this.setContent(layout);
this.setSizeFull();
You could create your own class which extends VerticalLayout and creates a TextArea inside it. That way you don't have to create a layout wrapper each time you just create your "MyTextArea" or whatever you want to call it.
Screenshot
N.B.
From your question I had originally thought the following code wouldn't work but it works fine? I haven't tried it in Vaadin 6.8.13 though. I am using Vaadin 7.1.2.
VerticalLayout layout = new VerticalLayout();
TextArea textArea = new TextArea("Hello World");
textArea.setEnabled(false);
textArea.setDescription("Some description");
layout.addComponent(textArea);
this.setContent(layout);
this.setSizeFull();
Hi all first of all I´m noob using SmartGWT, I have a SelectItem component with setVisible(false) and added into a DynamicForm. This DynamicForm is added into a Layout. I need to set the SelectItem with visible to true when another component is changed.
I do this:
SelectItem -> setVisible(true);
DynamicForm -> .redraw();
Layout -> .redraw();
Following piece of code works, and toggles the visibility of SelectItem on button click.
However note that this could lead to a jumpy UI, as other form controls flow in and out to fill the gap.
A better approach would be to enable/disable the component as indicated in the comment, which does not require a redraw.
final DynamicForm form = new DynamicForm();
form.setWidth100();
form.setHeight100();
final SelectItem selectItem = new SelectItem("sel", "Select");
selectItem.setValueMap("First", "Second", "Third");
ButtonItem buttonItem = new ButtonItem("btn", "Set");
buttonItem.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
selectItem.setVisible(!selectItem.getVisible());
form.redraw();
// uncomment following two lines and comment above two lines to enable/disable
// boolean isDisabled = Boolean.TRUE.equals(selectItem.getDisabled());
// selectItem.setDisabled(!isDisabled);
}
});
form.setFields(selectItem, buttonItem);
Other ways to handle form layouts:
http://www.smartclient.com/smartgwt/showcase/#layout_form_sections
http://www.smartclient.com/smartgwt/showcase/#layout_form_splitting
How to make a blackberry BitmapField non-focusable in runtime? I want make it dimmed based on a certain event.
Extend the BitmapField to override the isFocusable() method like this:
public class FocusableBitmapField extends BitmapField {
//Default value depending on whether you want it that way.
private boolean focusable = true;
public boolean isFocusable() {
return focusable;
}
public boolean setFocusable(boolean focusable) {
this.focusable = focusable;
}
}
Most of times this works:
field.setEditable(false);
You can also create a non-focusable field by passing the style flag Field.NON_FOCUSABLE or Field.FOCUSABLE to the constructor, but once instantiated you cannot change it's focusable state. Even if you could, then the field won't look "dimmed" or "disabled", but simply the focus will jump to the next focusable field after it. An example of this are non-focusable label fields.
UPDATE: This would work for built in fields like EditFields, Checkbox, RadioButtons, etc. In your case, this does not work since a BitmapField is not "editable", it's a read only field. You can make a trick like #adwiv answer shows, but the "disabled" or gray overlay you'll have to implement it yourself.
I have a Custom component with a textField and a button, I want to onClick (of the Button), get the text from the textField and call another Component.
The error I get when I call mainLayout.addComponent(new A(textField.getValue()); is an
java.lang.IllegalStateException: Composition root must be set to non-null value before the com.example.vaadpro.
As the exception says, you have to call setCompositionRoot for your CustomComponent:
public class A extends CustomComponent {
HorizontalLayout layout = new new HorizontalLayout();
public A() {
layout.add(new Label("Hello world!"));
layout.add(new Button("Click me!"));
setCompositionRoot(layout); // This is needed!
}
}