I'm using the Vaadin add-on SliderPanel (https://vaadin.com/directory#!addon/sliderpanel) in my project and am having a very hard time making it go away and reappear on the correct view. When I load the application and log in, it correctly takes me to the correct class/page, 'Dashboard', with no SliderPanel. When I navigate to any other class/page which is supposed to re-display the SliderPanel, it does not appear as expected. In order for me to get it to show, I have to resize the window. Same thing happens when I resize the window then go back to the 'Dashboard' page...I have to resize the window and the SliderPanel tab goes away. How can I get the SliderPanel tab to update itself when changing views with the navigator?
In my UI I have #push() annotated above the main class.
#Push()
public class EvoltwebUI extends UI implements ClickListener {...}
Inside the class I have these annotations and servlet class:
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = EvoltwebUI.class, widgetset = "com.evolt.evoltweb.widgetset.EvoltwebWidgetset")
public static class Servlet extends VaadinServlet {
}
I've registered the views like this:
private void registerViews() {
navigator.addView("dashboard", DashboardViewImpl.class);
navigator.addView("groups", GroupsViewImpl.class);
navigator.addView("research", ResearchViewImpl.class);
navigator.addView("reporting", ReportsViewImpl.class);
navigator.addView("execution", AdhocExecView.class);
navigator.addView("tcreview", TestCaseReviewView.class);
navigator.addView("toolbox", ToolboxView.class);
}
The 'enter' method on each view/class looks like this:
#Override
public void enter(ViewChangeEvent event) {
presenter.onViewEnter(event.getParameters());
generateFields();
ProgressPanel.setViewName("Test Case Review - Please load a group from the Test Group Explorer Slider Panel on the left.");
evoltWebUI.getTreeViewSlider().defaultTab();
}
I've tried using these, but I am having the same type of issue to where it will not come back if setVisible is false. :
leftTreeViewSlider.setVisible(true);
leftTreeViewSlider.setVisible(false);
I've also tried extending SliderPanel to access the actual size of the tab to shrink it, but when setting it back to the normal size I have to resize the window to get it back.
import org.vaadin.sliderpanel.SliderPanel;
import org.vaadin.sliderpanel.SliderPanelBuilder;
import com.vaadin.ui.Component;
public class SliderPanelMod extends SliderPanel{
public SliderPanelMod(SliderPanelBuilder builder) {
super(builder);
}
public void resizeTab(int t) {
this.getState().tabSize = t;
}
public void defaultTab() {
resizeTab(40);
}
}
Does anyone have any ideas what would be causing this?
Related
I created a class named "Footer" having just a Label. I also have a few views like loginview, orderview). And I would like to add that footer to every view. This is my code until now.
#ParentLayout(OrderView.class)
public class footer extends VerticalLayout implements RouterLayout {
public footer() {
add(new Span("This text should be underneath the page in the views"));
}
}
Underneath you have my orederview where I want to see that text from the footerclass.
#Route("order")
public class OrderView extends VerticalLayout implements RouterLayout {
public OrderView (){
// What am I supposed to code here to get that text from Footerclass.
}
}
I would like to know what I am missing.
Thanks for the help.
Your usage of the annotations is wrong. Here is super simplified outline how you should create MainLayout and route that defines a component that is shown in the mainlayout when navigated to that route.
public class MainLayout extends VerticalLayout implements RouterLayout {
private Div childWrapper = new Div();
public void MainLayout() {
setSizeFull();
Span header = new Span("This text should be above the page in the views");
Span footer = new Span("This text should be underneath the page in the views");
add(header);
addAndExpand(childWrapper)
add(footer);
}
#Override
public void showRouterLayoutContent(HasElement content) {
childWrapper.getElement().appendChild(content.getElement());
}
}
#Route(value = "order", layout = MainLayout.class)
public class OrderView extends VerticalLayout {
public OrderView (){
}
}
There is video tutorial about Router concept on vaadin.com page that explains this in detail.
Instead of
new Label("This text should be underneath the page in the views");
try
add(new Span("This text should be underneath the page in the views"));
In Vaadin Flow the Label component is meant to be used coupled with another component, not for adding stand-alone text like in Vaadin 8 and older. Also, every component needs to be added to the layout before they can become visible, just creating them isn't enough.
Unfortunately LoginOverlay doesn't have API for adding extra components within it, but there is an open ticket about the feature that you can add thumbs up on to add more weight to it, and there's also a workaround presented in the comments: https://github.com/vaadin/web-components/issues/626
I created a Dashboard with a menubutton fragment. When I click on a button a new Screen is opening. And now I want to open a specific tab of this screen. In default always the first tab of a screen opens up, but I need to specify. My code looks like this:
public void onBaldUeberfaelligBtnClick() {
screenBuilders.screen(this)
.withScreenClass(AufgabenuebersichtBrowse.class)
.build()
.show();
}
You can introduce a method in your AufgabenuebersichtBrowse class that switches to the needed tab. And then invoke this method after creating the screen, something like this:
public class AufgabenuebersichtBrowse extends ... {
#Inject
private TabSheet tabSheet;
public void switchToMyTab() {
tabSheet.setSelectedTab("tab2");
}
public void onBaldUeberfaelligBtnClick() {
AufgabenuebersichtBrowse screen = screenBuilders.screen(this)
.withScreenClass(AufgabenuebersichtBrowse.class)
.build();
screen.switchToMyTab();
screen.show();
}
See also the docs on opening screens: https://doc.cuba-platform.com/manual-7.2/opening_screens.html#screen_parameters
I'm having issues with my UI in vaadin at the moment. I have my views connected with RouterLayout like this:
-AppView (the main UI) | url: /
--OperationsView (a nested layout inside a container in AppView) | url: /operations
---Operation1View (a nested layout inside a container in OperationsView) | url: /operation1 <-
This isn't working
My declarations before any class are:
AppView declaration
#Route(value = AppView.ROUTE)
OperationsView declaration
#Route(value = OperationsView.ROUTE, layout = AppView.class)
Operation1View declaration
#Route(value = Operation1View.ROUTE, layout = OperationsView.class)
The problem is the third layout doesn't display correctly. It takes the whole page when accesed and mess up everything in the UI when going to another page. Shouldn't the url be: /operations/operation1 and not /operation1? However I can't get it to work correctly. Am I missing something? Or having 3 nested layouts is not possible with vaadin?
A possible solution (?): Should I dismiss the third nested layout and add methods in the second layout to remove the contents in the container and display the items I want? I really don't care about url navigation in this one. This is the last thing I can come up with.
Thanks in advance
Or having 3 nested layouts is not possible with vaadin?
It's possible. But are you implementing a RouterLayoutin both OperationsView and AppView classes?
Take a look into example here: Multiple parent layouts with #ParentLayout. It has a set-up pretty close to yours.
public class MainLayout extends Div implements RouterLayout {
}
#ParentLayout(MainLayout.class)
public class MenuBar extends Div implements RouterLayout {
public MenuBar() {
addMenuElement(TutorialView.class, "Tutorial");
addMenuElement(IconsView.class, "Icons");
}
private void addMenuElement(Class<? extends Component> navigationTarget,
String name) {
// implementation omitted
}
}
#Route(value = "tutorial", layout = MenuBar.class)
public class TutorialView extends Div {
}
#Route(value="icons", layout = MenuBar.class)
public class IconsView extends Div {
}
Shouldn't the url be: /operations/operation1 and not /operation1?
No, as in your #Router annotation you have specified that it's operation1. By specifying a layout you are defining the DOM structure, not the navigation route.From docs :
Sets the parent component for the route target component.When navigating between components that use the same layout, the same component instance is reused. Default layout target is the UI, but the layout should not be a custom UI as UI is a special class used to know where the route stack ends and no parent layouts should be involved.
All layout stacks will be appended to the UI as it represents the Body element.
BUT If you want it to be operation\operation1, you should use a #RoutePrefix instead ParentLayout Route Control
It takes the whole page when accesed and mess up everything in the UI when going to another page
Could you show a screenshot or add some details how it messes up?
Edit:
It's actually turned out to be harder to implement than I anticipated, but this seems to work:
MainView.java
#Route("")
public class MainView extends VerticalLayout implements RouterLayout {
....
OperationsView.java
//This is needed if you want "operations" to be accessible on its own
#Route(value = "operations",layout = MainView.class)
#ParentLayout(MainView.class)
public class OperationsView extends VerticalLayout implements RouterLayout {
Div content=new Div();
public OperationsView(){
System.out.println("operations view");
add(new Label("operations view"));
add(content);
}
}
Operation1View.java
#Route(value="operation1",layout = OperationsView.class)
#RoutePrefix("operations")
public class Operation1View extends VerticalLayout {
public Operation1View(){
add(new Label("Operations view"));
}
}
I have a problem where Vaadin does not update the display of a GridLayout in time. The GridLayout is a component in a VerticalLayout, that I use to list all uploaded files. When I upload a file everything works fine on the server-side but the client does not see the change until he creates a new request to the server (by uploading another file or triggering some other event / rarely the update works fine though).
Here is the component that contains the problematic GridLayout:
public class ListedMultiFileUpload extends VerticalLayout {
private MultiFileUpload multiFileUpload;
private GridLayout fileList;
public ListedMultiFileUpload(UploadFinishedHandler uploadFinishedHandler, UploadStateWindow uploadStateWindow) {
multiFileUpload = new MultiFileUpload(uploadFinishedHandler, uploadStateWindow);
fileList = new GridLayout(2, 5);
fileList.setImmediate(true);
addComponents(multiFileUpload, fileList);
}
public SmartMultiUpload getSmartUpload() {
return multiFileUpload.getSmartUpload();
}
public void addFile(String fileName, final Runnable fileRemover) {
final Label label = new Label(fileName);
final Button button = new Button("X");
button.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
fileList.removeComponent(label);
fileList.removeComponent(button);
fileRemover.run();
}
});
fileList.addComponent(label);
fileList.addComponent(button);
markAsDirtyRecursive();
}
}
I already tried setting the GridLayout to immediate as well as marking the whole component as dirty but nothing seems to make a difference.
So basically am I doing something wrong here? Or if not, is there a "nice" way I could force the client to update its components?
As proposed by #Morfic I enabled the Server-Push addon in automatic mode and now the required updates to the client are made by that addon. Not sure how much I like that solution but it works.
I have the following GWT classes:
public class MyDefaultView extends Composite {
// Uses UiBinder and just contains all the widgets for this view.
}
public class MyDefaultActivity extends AbstractActivity {
#Inject
private MyDefaultView myDefView;
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
panel.setWidget(myDefView);
}
}
public class MyActivityMapper implements ActivityMapper {
#Override
public Activity getActivity(Place place) {
if(place instanceof MyDefaultPlace)
return new MyDefaultActivity();
else
return null;
}
}
public class MyAppModule implements EntryPoint {
#Override
public void onModuleLoad() {
// Lots of initialization and wiring...
// Why do I need this?!?
MyDefaultView myDefaultView = GWT.create(MyDefaultView.class);
RootPanel.add(myDefaultView);
Place myDefaultPlace = GWT.create(MyDefaultPlace.class);
PlaceHistoryHandler historyHandler = getHistoryHandler();
historyHandler.register(myPlaceController, myEventBus, myDefaultPlace);
historyHandler.handleCurrentHistory();
}
}
Why do I need to add MyDefaultView to RootPanel, if I'm just going to call PlaceHistoryHandler#handleCurrentHistory() and display MyDefaultView when the module loads?
If I shouldn't be adding MyDefaultView directly to RootPanel, then what should I be adding?
Thanks in advance!
1) You don't need to add MyDefaultView, but you need to a panel that implements AcceptsOneWidget and set that panel on the activity manager. This will take care of having your views made visible.
2) In most applications you have a part of the application that is always visible. For example a bar at the top showing among other things the user name. This kind panel needs to be added to the root panel. In that panel on the position where your views should be visible a widget/panel that implements AcceptsOneWidget should be used. This widget should be set as display in your activityManager, via setDisplay. That widget will be passed to the start method in your activity. Here is how the code to use with the ActivityManager and RootPanel could look like:
final ActivityManager activityManager = new ActivityManager(myActivityMapper, eventBus);
activityManager.setDisplay(rootView.getViewPanel());
Rootpanel.add(rootView);