Vaadin: Sub window - vaadin

I'm trying to use a sub window but either the components I try to put in it show up in the "mainwindow" or I receive a java.lang.UnsupportedOperationException. I'll show you both cases. I'd like to place a HorizontalLayout in the sub window when I need to put in some real components and not just a Label and a Button.
public class SubWindow extends CustomComponent {
Window mainWindow; // Reference to main window
Window myWindow; // The window to be opened
public SubWindow(Window main) {
mainWindow = main;
createWindow();
}
public void createWindow() {
myWindow = new Window("My Dialog");
HorizontalLayout layout = new HorizontalLayout();
// Add the window inside the main window.
mainWindow.addWindow(myWindow);
layout.addComponent(new Label("A label"));
layout.addComponent(new Button("Ok"));
// The composition root MUST be set
setCompositionRoot(layout);
myWindow.addComponent(layout);
}
}
When I run this and open a new sub window using
window = new Window("Title");
setMainWindow(window);
window.addComponent(new SubWindow(window));
I get
SEVERE: Terminal error:
com.vaadin.event.ListenerMethod$MethodException
Cause: java.lang.UnsupportedOperationException
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:164)
...
Caused by: java.lang.UnsupportedOperationException
at com.vaadin.ui.CustomComponent.removeComponent(CustomComponent.java:248)
at com.vaadin.ui.AbstractComponentContainer.addComponent(AbstractComponentContainer.java:207)
...
On the other hand, if I switch place between setCompositionRoot(layout) and myWindow.addComponent(layout), the Label and the Button just end up in the main window instead of the newly created sub window.
What am I missing?

i suggest that you extend Window directly than go through a CustomLayout. A layout can't contain a window - it goes the other way around.
Change
public class SubWindow extends CustomComponent to public class SubWindow extends Window
myWindow = new Window("My Dialog"); to setCaption("My Dialog");
and
// The composition root MUST be set
setCompositionRoot(layout);
myWindow.addComponent(layout);
to setContent(layout);
That is the standard way of creating a subwindow, exactly the same way you create the main window. I would also move the mainWindow.addWindow(myWindow); outside of the class and not pass the mainwindow object to the subwindow, because that is not really the part of the subwindow object.

Related

Vaadin checkbox is not correctly rendered

Using Vaadin 14.0.13 without compatibility mode.
I use a view to create a Dialog with dynamic content:
#Route("")
public class MainView extends VerticalLayout {
public MainView(DialogContentProvider contentProvider) {
this.add(new Button("Click me!", event -> new Dialog(contentProvider.create()).open()));
}
}
The contentProvider is an interface
public interface DialogContentProvider {
Component create();
}
with this implementation:
public class CheckBoxContentProvider implements DialogContentProvider {
#Override
public Component create() {
return new Checkbox("My checkbox", true);
}
}
instantiated by Spring Boot (version 2.2.1.RELEASE) with a bean:
#Bean
public DialogContentProvider contentProvier() {
return new CheckBoxContentProvider();
}
When I click on the button, the dialog is opened but the checkbox haven't the box:
The source code is on github: https://github.com/gronono/bug-vaadin-checkbox
I don't understand why and how I can fix it. If I include the checkbox creation inside the main view, it works fine:
#Route("")
public class MainView extends VerticalLayout {
public MainView(DialogContentProvider contentProvider) {
// this.add(new Button("Click me!", event -> new Dialog(contentProvider.create()).open()));
this.add(new Button("Click me!", event -> new Dialog(new Checkbox("My checkbox", true)).open()));
}
}
This sound an awful lot like this (related github issue)
Basically, this happens when you don't have any View that uses a Checkbox directly, but through other means like reflection or in your case the contentProvider, because in no view of your app there is any import statement of Checkbox (--> therefore, vaadins scan during the installation will not detect usages of Checkbox, so it will not download npm stuff for checkbox).
in the github it says this will be fixed in 14.1
If you need a fix now, for me it worked when I declared a field of that type in any view with a #Route. That field doesn't have to be used.
#Route("")
public class MainView extends VerticalLayout {
private Checkbox unusedCheckbox; // this line fixes it.
public MainView(DialogContentProvider contentProvider) {
this.add(new Button("Click me!", event -> new Dialog(contentProvider.create()).open()));
}
}
Addendum: This is not related to the Checkbox component specifically, it happens with any vaadin component that isn't initially scanned in a route, but used anyway through reflective-, provider-, or generic means.
Edit: You can also work around this currently by adding a #Route(registerAtStartup = false) to your provider that uses the Checkbox directly. This will make vaadins scan see the checkbox usage (therefore importing its npm package), but will not actually register the provider as a real route..
Another way which I prefer if you need this for multiple components is to create a new View with a #Route(registerAtStartup = false) which only defines private variables for each component that you'll need in the application (and arent already used directly in some view of yours). This has the advantage of all these component usage definitions in one place, and once the official fix is released, you need only to delete one class and the deprecated workaround is gone.
#Route(registerAtStartup = false)
public class ComponentImportView extends VerticalLayout {
private Checkbox checkBox;
private Upload upload;
private ProgressBar progressBar;
}

Xamarin forms MasterDetailPage Menu icon not shown on iOS

I have Xamarin.Forms project.
I have MasterDetailPage inside NavigationPage.
I set icon property of the MasterDetailPage so that icon is supposed to be set as the top left position on the navigation bar. But it does not work.
public partial class App : Application
{
public App()
{
InitializeComponent();
var masterDetailpage = new MasterDetailPage {
Icon = "menuIcon.png",
Master = new Page { Title = "Sample"},
Detail = new Page()
};
MainPage = new NavigationPage(masterDetailpage);
}
}
This never works. If I put NavigationPage as MasterDetailPage's Detail property, and set icon on the Master. It works.
But it is very important to have MasterDetailPage inside NavigationPage and not vise versa.
The solution is to set the Icon property of the Page being used for the Master.
var masterDetailpage = new MasterDetailPage {
Master = new Page { Title = "Sample", Icon = "menuIcon.png"},
Detail = new NavigationPage(new Page())
};
This assumes you have a png in your iOS project under the Resources folder named menuIcon.png that is the hamburger icon you want. You will also need to use a NavigationPage around the Detail because the Icon is shown in the Navigation Bar area.
The Unicode char can be used to show the "hamburger" menu icon.
You may specify Title="☰" for the master page ContentPage-top level tag.
If you use an icon, you may draw a better icon than char. But using Unicode char is simple enough if this is acceptable for you.
It works for iOS and doesn't break Android.
Links:
Trigram for heaven (U+2630)
The Unicode character for menu icons ("navicons") ☰.
If you wrap the master page in a navigation page, put the icon on the navigation page.
This works for me:
public partial class App : Application
{
public App()
{
InitializeComponent();
var masterDetailpage = new MasterDetailPage {
Icon = "menuIcon.png",
Master = new Page { Title = "Sample"},
Detail = new Page()
};
MainPage = new NavigationPage(masterDetailpage) { Title = "Sample", Icon = "menuIcon.png" };
}
}
In case it helps someone You can set the title of the menu right before setting your MainPage as I have done in the sample code below:
var master = new MasterPage();
master.Master.Icon = "my_icon.png";
master.Master.Title = AppResources.Menu; // To get the value from resource files
MainPage = master;
MasterPage inherits from MasterDetailsPage And I was unable to directly set the value from constructor of MasterPage because of Xamarin's weird errors.
I think you have to add to your AddDelegate a common fix
namespace myApp.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate :
global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
UIWindow window;
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
// fix for iOS
window = new UIWindow(UIScreen.MainScreen.Bounds);
window.RootViewController = App.GetMainPage().CreateViewController();
window.MakeKeyAndVisible();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
}
}
In your PCL project in App.xaml.cs you have to add
public App()
{
// The root page of your application
MainPage = GetMainPage();
}
public static Page GetMainPage()
{
return new RootPage();
}

Popup Print Window in Vaadin 7 with Table

I am new on Vaadin.
How to pass Table component to new popup screen in Vaadin 7? Assume I already created table using com.vaadin.ui.Table.
Table aaa = new Table();
Currently Vaadin tutorial just show how to create print popup without pass component/data.
Based on below code
public static class PrintUI extends UI {
#Override
protected void init(VaadinRequest request) {
// Have some content to print
setContent(new Label(
"<h1>Here's some dynamic content</h1>\n" +
"<p>This is to be printed.</p>",
ContentMode.HTML));
// Print automatically when the window opens
JavaScript.getCurrent().execute(
"setTimeout(function() {" +
" print(); self.close();}, 0);");
}
}
...
// Create an opener extension
BrowserWindowOpener opener =
new BrowserWindowOpener(PrintUI.class);
opener.setFeatures("height=200,width=400,resizable");
// A button to open the printer-friendly page.
Button print = new Button("Click to Print");
opener.extend(print);
Appreciated if someone could show me how to pass Table aaa into PrintUI class.
Window window = new Window("my test table popup");
window.setContent(table);
window.setModal(true);
getUI().addWindow(window);
The only way that I have found to pass objects to the UI class in popup window is to store them in session:
Table table = new Table();
VaadinSession.getCurrent().setAttribute("table", table);
In the popup window:
Table t = (Table) VaadinSession.getCurrent().getAttribute("table");
You can also initialize your Table in your PrintUI class. If you need to initialize a specific Table instance, you can pass, let's say, your table id parameter to the UI via .getParameter("idTable") (which, in the end, works as adding a GET parameter to the URL) and then retrieve it in your PrintUI's init() method via the request parameter with .getParameter("idTable").

Vaadin call create a component throught another component

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!
}
}

blackberry react to menuitem

I started writing a bb app with a menu.
My problem is I don't know how to react if the selected item is clicked. The menu contains some fields in a VerticalFieldManager that is added in a class that extends MainScreen.
I'm sorry for asking such basic stuff, but i googled 1.5 hours now and didnt find a solution or example, Its my very first blackberry app.
Here you go.
This snippet of code defines a new menu item, with a constructor where you specify the label of the menu item and its position on the menu, and a run method which is called when the user clicks on your menu item.
The run method is called on the UI (event) thread, so you are free to update your user interface components from here, or do whatever else you need to do.
I also included a snippet of a screen class that adds the menu item to its menu.
final class MyMenuItem extends MenuItem
{
MyMenuItem()
{
super("Menu item text", 100000, 0);
}
public void run()
{
// The user has clicked on the menu item, and
// this method was called. Do what you need to do.
}
}
final class MyScreen extends MainScreen
{
// ...
protected void makeMenu ( Menu menu, int instance )
{
// let the system build a default menu first
super.makeMenu(menu, instance);
// add your menu item to the screen
menu.add ( new MyMenuItem() );
}
// ...
}

Resources