I need some widgets that share the same code base, thus I introduced an abstract class providing these shared members and methods and created an implementation which adds additional functionality. but every time I wanted to add this to a VStack I got the following error:
java.lang.AssertionError: A widget that has an existing parent widget may not be added to the detach list
in order to verify if this is b/c of the class hierarchy I created the same in a method, but I'm still receiving the same error. the code below should describe what I want to achieve.
public class Test extends VStack {
// constructor that adds button and a clickhandler for the button
// that will call addComplex()
public void addComplex() {
HStack stack = new HStack();
stack.setHeight("22px");
stack.addMember(new IButton("remove"));
stack.addMember(new ListBox());
DynamicForm form = new DynamicForm();
form.setFields(new TextItem());
stack.addMember(form);
addMember(stack);
}
}
when I just call
addMember(new Label(""));
I get no error.
furthermore, considering that the stuff in the method addComplex is in a separate class, and I add a new instance in the constructor of this Test-class, no error is thrown. the error is only thrown when I want to add the HStack via a button click
why can't I add this HStack to my VStack?
Update
it was b/c of the ListBox, which is a GWT component, and no SmartGWT component. this was the detail I missed.
can anybody tell me: why has a GWT widget an existing parent, and a SmartGWT widget does not? or is the error message just bogus?
the problem was that ListBox is from GWT, not SmartGWT. replacing it with the appropriate SmartGWT widget it works like a charm.
I have found, as a general rule:
Thou shalt not mix GWT and SmartGWT if thou seeketh functionality beyond the basic displaying of thine widgets.
I ran into this same exception when attempting to hide/show a DynamicForm or a VLayout that contained some plain GWT widgets... The page loaded fine, but I ran into trouble when I tried to add some hide/show interaction functionality...
Related
My Vaadin 14's mainpage is a MainView with the root Route.
MainView is used as a "template" for the other View (with layout = MainView.class) so I see it more like a "abstract" view that should not be initialized by itself and is only used for the other views as layout.
Now the issue: If a user accesses the MainView the BeforeEnterEvent is called AFTER the constructor. This may lead to exceptions thrown because the user is not authenticated yet and the constructor executes stuff like building the Tabs already.
Is there a way to prevent the user from accessing the route of the MainView or an event that is executed before the constructor is called? Accessing the View is only allowed if the user is authenticated.
#Route("")
public class MainView extends AppLayout implements BeforeEnterObserver {
public MainView() {
super();
// Creates all the Tabs that are used in the MainView, may throw exception if the user calls the URL of this View before authenticated
setupView();
}
...
#Override
public void beforeEnter(BeforeEnterEvent event) {
// Reroute to Login if User is NOT authenticated
}
}
#Route(value = "foo", layout = MainView.class)
public class OtherView {
Update:
The fix is released as experimental feature in Vaadin 14.2.
The issue with instances being created too early was actually closed a few hours ago. It will take some time before it's released.
That being said, an instance method can't possibly be called before the constructor, so it does not fix your particular case.
I would suggest moving your view setup code to onAttach. If you only want to run the setup code once, you can use AttachEvent#isInitialAttach to only execute your code on the first attach.
Once the issue I linked above is released, you can have the code in the constructor, but the instance that has the observer method will still be created before beforeEnter is called, just not the child view instances.
To not have any views created, you can add listener directly to the UI using UI#addBeforeEnterListener as soon as the UI is created, utilizing a UI init listener. Again, only when the fix has been released.
Your code may have a security issue, as described in the tutorial series for spring security with Vaadin. it is explained how to secure Views in the VaadinServiceInitListener instead.
But the proposed solution also adds a beforeEnterListener to the Views, so I don't think your problem is resolved with this.
A solution to your problem may be to throw a custom Exception (let's call it NotAuthorizedException for further reference) in the constructor of MainView if the user is not authorized. Then you let your LoginView implement HasErrorParameter<NotAuthorizedException>
I was able to fix it temporarely with an additional check for authentication. It may not be the best solution but it works for now. In the future #Tazavoo's answer should be implemented.
public MainView() {
super();
if (!isAuthenticated())
return;
setupView();
}
I am using Vaadin wizard addon and I have a problem with the following case:
When the user only presses forward/next step, there is no problem. However, if the user wants to go to the previous step, I am accidentally adding a Button click listener to the same event(That is my assumption. I have debugged the program and saw that if the user goes to the previous page, the event fires twice)
I have tried to remove the event listener before going to the next page, however, I could not find a method to remove all of the event listeners once. Also, I don't know where to remove them, since I could not find a function executed before the user is moved to the next page in Vaadin wizard.
I am following this example:
https://github.com/tehapo/WizardsForVaadin/tree/master/wizards-for-vaadin-demo/src/main/java/org/vaadin/teemu/wizards
Is there a method to remove all of the ClickListeners?
If it exists, where should I add that functionality?
Also, I am using ListDataProvider and NativeSelect components too.
NativeSelect has HasValue.ValueChangeListener<String> listener and in the default implementation, I Could not find a method such that I can use this:
NativeSelect<String> select = new NativeSelect<>("List");
select.addValueChangeListener(new HasValue.ValueChangeListener<String>() {
// some overwritten valuechange method
}
select.removeValueChangeListener(); // This does not exist
I am setting the click listener in the public Component getContent() {} method
In Vaadin 8 you need to use the Registration interface to remove Listeners.
When you add a Listener it will return the Registration:
final Registration registration = select.addValueChangeListener(this::doSomething);
And then to remove it:
registration.remove();
Using vaadin (7.7.3) I'm filtering a grid by name, this filtering takes a couple seconds to remove the objects from the Grid gui. And so, if I click on that timelapse a row of the Grid which is removed from the Container, it raises an exception:
Caused by: java.lang.IllegalArgumentException: Given item id (5422bef6-e472-4d3e-af54-316c52d373da) does not exist in the container
at com.vaadin.ui.Grid$AbstractSelectionModel.checkItemIdExists(Grid.java:1371)
at com.vaadin.ui.Grid$SingleSelectionModel.select(Grid.java:1460)
at com.vaadin.ui.Grid$SingleSelectionModel$1.select(Grid.java:1445)
I guess this is normal because it removes the objects from the Container and then it will propagate to the gui.
I have thought of catching the exception overwriting the checkItemIdExists() method in my Grid class but it would catch the exception for every situation and that is not the behavior I am looking for.
My question is: How can I capture this exception just in this case?
The only workaround I have found, is to override the selection model of the grid in Vaadin to disable the checkItemIdExists method. This is the method that launches the exception you have.
import com.vaadin.ui.Grid.SelectionModel;
import com.vaadin.ui.Grid.SingleSelectionModel;
public class SingleSelectionModelNotChecked extends SingleSelectionModel implements SelectionModel {
#Override
protected void checkItemIdExists(Object itemId) throws IllegalArgumentException {
// Nothing to do. No check is done, no exception is launched when the filter is applying.
}
}
You can now include this into your gird with:
setSelectionModel(new SingleSelectionModelNotChecked());
Of course, now the grid cannot check that the element selected in in the grid or not.
You can use Viritin Add-on https://vaadin.com/directory#!addon/viritin
it supports server side paging, Vaadin Grid will load all data from database or you will use your dataSource to send ContainerDataSource.
i have added a pageable listview with two components,one is text field and other is a dropdown. Normal way of checking for validation is by adding a feedback panel.But when same method is used in grid its giving an error saying that feedback component with wicket:id="xy" has already been parsed.
is there any way to validate those components?
JAVA CODE HTML CODE
Somewhere in the code (e.g. your overridden Form#onSubmit() or Form#onError(), one of your Ajax behaviors, etc.) you add the component with wicket ID "FeedbackSubQuestions_" again, even though this component has already been added before. Something like the following:
public class MyPage extends WebPage {
public MyPage() {
this.add(new FeedbackPanel("FeedbackSubQuestions_"));
this.add(new Form<Void>("myForm"){
#Override
protected void onError() {
// This call the produce the error as the feedback component is already in the component hierarchy
MyPage.this.add(new FeedbackPanel("FeedbackSubQuestions_"));
}
});
...
Adding all the form components with validation and their ajax behaviors
...
}
}
In wicket, once you construct the component hierarchy, subsequent interactions with the page do not need to reinitialise any of it anymore. That is, once you add the feedback panel in order for it to display your feedback you do not need to add this panel again. If there are errors to be displayed (e.g. a form validation fails, or Component#error(String) is called manually) the feedback will pick those up automatically when the feedback panel is being rendered again (e.g. when you add it to your ajax response or the whole page is being re-rendered as part of the form submission process).
In Eclipse RCP, I am creating views for the Perspective using IPageLayout.addView(...)
But this way I don't have a reference to the view. Therefore I don't know how I can tell ViewA to update ViewB.
What's the best pattern to use here?
Besides what VonC has mentioned above, you can also use ISourceProviderListener if the changes you need are not triggered by selection.
Have ViewB implements ISourceProviderListener
Create an implementation of ISourceProvider and register it in the services
Have ViewA get the ISourceProvider and update it to trigger the changes in ViewB
Read the documentation on those interfaces along with IServiceLocator and ISourceProviderService to get better idea how it all plays out.
You can also see this Lars Vogel's tutorial which has some example how to use the ISourceProvider
You have the different communication paradigm summarize in the IBM article
To make a view capable of listening to selection changes, a view must implement the ISelectionListener interface and must register itself with the workbench page
Using the IAdaptable interface: A class that implements IAdaptable has the capability to dynamically return certain types of adapters that can then be used to retrieve further information.
property change listener paradigm
Regarding the first approach, the article details:
A smarter way to consume UI selections is to register the consumer views as listeners to specific view parts. As you can see in the example below, the view ID of the source view part is mentioned as a parameter during registering a selection listener.
getSite().getPage().addSelectionListener("SampleViewId",(ISelectionListener)this);
This approach will eliminate the redundant callbacks to the consumer view that would otherwise occur if that view were registered as a nonspecific listener.
The code snippet in Listing 2 shows the createPartControl() method of a view that creates a JFace TableViewer and adds it as a selection provider to the workbench site. This code enables any UI selection changes in the TableViewer to propagate to the page and finally to the interested consumer views.
Listing 2. Setting up a selection provider
public void createPartControl(Composite parent) {
// Set up a JFace Viewer
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
viewer.setSorter(new NameSorter());
viewer.setInput(getViewSite());
// ADD the JFace Viewer as a Selection Provider to the View site.
getSite().setSelectionProvider(viewer);
}
You will find a similar approach in the RCP tutorial for eclipse3.5 (update February, 4th 2010)
There are different ways for view and plugin communications: eventbroker, listener etc..
EvenBroker (e4) Implementation:
Use eventbroker to send message (string) between views and plugins.
Sender Side:
#Inject
private IEventBroker eventBroker;
private static final String STATUS ="status";
eventBroker.send(STATUS, "status test message..");
Receiver Side:
#Inject
private IEventBroker eventBroker;
private static final String STATUS ="status";
#Inject #Optional
public void getEvent(#UIEventTopic(STATUS) String message) {
... //call method
}