Я ищу способ загрузить контент в вкладку на вкладке Vaadin TabSheet только после того, как вкладка будет выбрана, а не раньше. Ленивый Loading, это термин.
Ленивая загрузка из Vaadin 7 Tabsheet не является очевидным, что содержание каждой вкладки требуется во время строительства.
Я прочитал статью " Стратегия создания ленивых загрузочных вкладок" на форумах Vaadin. Я узнал от Йенса Янсона, что на стороне клиента Ваадин уже ленив. DOM не заполняется в браузере до тех пор, пока не будет выбрана вкладка. Но я обеспокоен ослаблением нагрузки на серверной стороне. Этот поток не решает эту проблему.
Вот один полный пример. Он может быть инкапсулирован в выделенный класс позже. Обратите внимание, что выбранное содержимое вкладки изменяется каждый раз, когда оно выбрано. Если вам нужна ленивая загрузка, но она не нуждается в обновлении каждый раз, я бы создал загруженное булевым полем и зависящее от него обновление. Счетчик интуитивно вы можете сделать вкладку нетерпением, предоставив аргумент конструктора. Это полезно для первой показанной вкладки, например.
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
import com.vaadin.ui.TabSheet.SelectedTabChangeListener;
import com.vaadin.ui.TextField;
public class TablesFrame extends CustomComponent {
private static class LazyTabChangeListener implements SelectedTabChangeListener {
@Override
public void selectedTabChange(SelectedTabChangeEvent event) {
LazyTab tab = (LazyTab) event.getTabSheet().getSelectedTab();
tab.refresh();
}
}
private abstract class LazyTab extends CustomComponent {
public LazyTab() {
this(false);
}
public LazyTab(boolean eager) {
if (eager) {
refresh();
}
}
abstract Component build();
public final void refresh() {
setCompositionRoot(build());
}
}
private LazyTab tab1 = new LazyTab(true) {
@Override
Component build() {
return new TextField("1");
};
};
private LazyTab tab2 = new LazyTab() {
@Override
Component build() {
return new TextField("2");
};
};
public TablesFrame() {
TabSheet ts = new TabSheet();
ts.addSelectedTabChangeListener(new LazyTabChangeListener());
ts.addTab(tab1, "Tab1");
ts.addTab(tab2, "Tab2");
setCompositionRoot(ts);
}
}
UPDATE Также возможно подклассу TabSheet. Таким образом, вы можете также использовать регулярные вкладки и иметь все операции TabSheet. Обратите внимание, что нетерпеливые LazyTabs и обычные вкладки здесь разные, потому что LazyTabs перезагрузится.
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.TabSheet;
public class LazyTabSheet extends TabSheet {
public LazyTabSheet() {
addSelectedTabChangeListener(new LazyTabChangeListener());
}
public static abstract class LazyTab extends CustomComponent {
public LazyTab() {
this(false);
}
public LazyTab(boolean eager) {
if (eager) {
refresh();
}
}
public abstract Component build();
public final void refresh() {
setCompositionRoot(build());
}
}
private static class LazyTabChangeListener implements SelectedTabChangeListener {
@Override
public void selectedTabChange(SelectedTabChangeEvent event) {
Component selectedTab = event.getTabSheet().getSelectedTab();
if (selectedTab instanceof LazyTab) {
((LazyTab) selectedTab).refresh();
}
}
}
}
Если вы хотите использовать аккордеон таким же образом, я бы не подклассифицировал вкладку, а реализовал функциональность через шаблон декоратора. Аккордеонные подклассы TabSheet, поэтому он должен управляться.
CustomComponent
? Почему не подкласс TabSheet
?
Вот реализация, в которой перечислены некоторые из приведенных выше предложений:
public abstract class LazyTab {
Component comp;
private boolean eager;
private boolean cached;
public static LazyTab of(boolean eager, boolean cached, Supplier<Component> componentSupplier) {
return new LazyTab(eager, cached) {
@Override
protected Component build() {
return componentSupplier.get();
}
};
}
protected LazyTab(boolean eager, boolean cached) {
this.eager = eager;
this.cached = cached;
if (eager) comp = build();
}
protected abstract Component build();
public final void refresh() {
if ((comp == null) ||!cached) comp = build();
}
/**
* @return get component on demand (depends on eager and cached properties)
*/
public final Component getComponent() {
return comp;
}
public static class LazyTabSheet extends TabSheet {
public LazyTabSheet() {
addSelectedTabChangeListener(new LazyTabChangeListener());
}
}
public static class LazyTabChangeListener implements TabSheet.SelectedTabChangeListener {
@Override
public void selectedTabChange(TabSheet.SelectedTabChangeEvent event) {
Component selectedTab = event.getTabSheet().getSelectedTab();
if (selectedTab instanceof LazyTab) {
((LazyTab) selectedTab).refresh();
}
}
}
}