2016-03-10 11 views
0

Когда я добавляю компоненты к компоненту Ваадина (например, TabSheet или Tree), добавленные компоненты кэшируются. Когда пользователь щелкает вкладку (или узлы дерева), если она содержит данные db, она показывает устаревшие данные, не отражающие последнее состояние db.Убедитесь, что Vaadin загружает последние данные при нажатии на добавленные компоненты (например, TabSheet или Tree ...)

Интересно, есть ли способ обеспечить загрузку последних данных?

Я решить эту проблему, определив свой пользовательский интерфейс:

public interface Reloadable { 
    void reload(); 
} 

И каждый компонент реализует этот пополняемый интерфейс, такие как:

@SpringComponent 
public class TeachersView extends VerticalLayout implements Reloadable, Serializable { 

    @Inject 
    private TeacherDao teacherDao; 
    private final static int PAGESIZE = 10; 

    private MTable<Teacher> mTable = new MTable<>(Teacher.class); 

    @PostConstruct 
    public void init() { 
    // mTable settings skip here 
    reload(); 
    addComponent(mTable); 
    } 

    @Override 
    public void reload() { 
    mTable.setBeans(new SortableLazyList<>(
     sortablePagingProvider , 
    () -> (int) teacherDao.count() , 
     PAGESIZE 
    )); 
    } 

    private SortableLazyList.SortablePagingProvider<Teacher> sortablePagingProvider = 
    (firstRow, asc, sortProperty) -> { 
     return teacherDao.findAll(
     new PageRequest(
      firstRow/PAGESIZE, PAGESIZE, 
      asc ? Sort.Direction.ASC : Sort.Direction.DESC, 
      sortProperty == null ? "id" : sortProperty 
     ) 
    ).getContent(); 
    }; 
} 

И этот вид впрыскивается UI класса:

@SpringUI(path = "/ui") 
@Theme("valo") 
public class VaadinUI extends UI { 
    @Inject 
    private TeacherDao teacherDao; 

    @Inject 
    private TeachersView teachersView; 

    @Override 
    protected void init(VaadinRequest vaadinRequest) { 
    Panel panel = new Panel("Admin Panel"); 

    HorizontalSplitPanel splitPanel = new HorizontalSplitPanel(); 
    splitPanel.setSplitPosition(15, Unit.PERCENTAGE); 
    panel.setContent(splitPanel); 

    Tree tree = new Tree("Menu"); 
    splitPanel.setFirstComponent(tree); 

    Label home = new Label("Home"); 

    Map<String, Component> map = new HashMap<>(); 
    map.put("Teachers", teachersView); 
    map.put("Home", home); 

    map.forEach((k, v) -> tree.addItem(k)); 

    tree.addItemClickListener(event -> { 

     Component view = map.get(event.getItemId()); 
     if (view instanceof Reloadable) { 
     ((Reloadable) view).reload(); 
     } 
     splitPanel.setSecondComponent(view); 
    }); 

    splitPanel.setSecondComponent(home); 
    setContent(panel); 
    } // init() 
} 

Отметьте tree.addItemClickListener, Я должен проверить каждый компонент, если он реализует Reloadable, если true, вызовите его.

Это работает. Но я не знаю, соответствует ли это стандарту способом достижения этого? Я думаю, что это должен быть общий сценарий, должно быть что-то вроде встроенного интерфейса для компонентов для реализации, например onRender (но я не могу найти его). Я что-то пропустил?

Спасибо.

+1

Ваше решение выглядит нормально, особенно если оно работает.Мы можем думать о методе attach() в интерфейсе Component, но attach() будет вызываться только один раз, когда компонент добавляется в контейнер. –

ответ

1

Прежде всего я собираюсь предложить этот урок на Spring & Vaadin, который вы, возможно, уже видели, но я буду ссылаться на него в нескольких местах, и я думаю, что это хорошая отправная точка для Vaadin & Весенняя интеграция.

Во-вторых, из любопытства, почему вы используете дерево для создания меню?

В примере, если вы, кажется, моделирование навигации между некоторые виды имеют, которая уже available in Vaadin, и так как вы используете Spring, расширения Vaadin spring & spring-boot делает его очень легко define and navigate between your views. Затем вы можете определить определенное поведение для каждого представления в своем собственном методе enter(). Я использовал Vaadin dashboard demo как вдохновение для изменения ниже:

@SpringView(name = TeachersView.NAME) 
public class TeachersView extends VerticalLayout implements View { 
    public static final String NAME = "Teachers"; 

    private Label title = new Label("Teachers view"); 

    @PostConstruct 
    void init() { 
     addComponent(title); 
    } 

    @Override 
    public void enter(ViewChangeListener.ViewChangeEvent event) { 
     // recreate or reload stuff here 
     title.setValue("Teachers view reloaded @ " + new Date()); 
    } 
} 
@SpringView(name = HomeView.NAME) 
public class HomeView extends VerticalLayout implements View { 
    public static final String NAME = ""; 

    @PostConstruct 
    void init() { 
     addComponent(new Label("Home")); 
    } 

    @Override 
    public void enter(ViewChangeListener.ViewChangeEvent event) { 
     // meh, nothing special to do here 
    } 
} 
public class SpringVaadinUI extends UI { 

    @Autowired 
    private SpringViewProvider viewProvider; 

    @Override 
    protected void init(VaadinRequest vaadinRequest) { 
     addStyleName(ValoTheme.UI_WITH_MENU); 
     Panel panel = new Panel("Admin Panel"); 

     HorizontalSplitPanel splitPanel = new HorizontalSplitPanel(); 
     splitPanel.setSplitPosition(15, Unit.PERCENTAGE); 
     panel.setContent(splitPanel); 

     VerticalLayout navigationBar = new VerticalLayout(); 
     navigationBar.setPrimaryStyleName(ValoTheme.MENU_ROOT); 
     navigationBar.addComponent(createNavigationButton("Home", FontAwesome.HOME, HomeView.NAME)); 
     navigationBar.addComponent(createNavigationButton("Teachers", FontAwesome.GROUP, TeachersView.NAME)); 
     splitPanel.setFirstComponent(navigationBar); 

     CssLayout navigationDisplay = new CssLayout(); 
     splitPanel.setSecondComponent(navigationDisplay); 

     Navigator navigator = new Navigator(this, navigationDisplay); 
     navigator.addProvider(viewProvider); 

     setContent(panel); 
    } 

    private Button createNavigationButton(String caption, FontAwesome icon, final String viewName) { 
     Button button = new Button(caption, icon); 
     button.setPrimaryStyleName(ValoTheme.MENU_ITEM); 
     button.addStyleName(ValoTheme.BUTTON_SMALL); 
     button.addStyleName(ValoTheme.BUTTON_BORDERLESS); 
     button.addClickListener(event -> getUI().getNavigator().navigateTo(viewName)); 
     return button; 
    } 
} 

Результат аналогичен: Demo

Если по каким-то причинам вы не можете или не хотите использовать навигатор, тогда ваше решение выглядит отлично. Тем не менее, какое бы решение вы ни выбрали, вы должны знать, что by default Spring создает singletons. За исключением нескольких таких, как пользовательский интерфейс, вы, вероятно, должны изменить свои компоненты на prototypes, чтобы каждый раз получать новый экземпляр. В противном случае все ваши пользователи получат одинаковые экземпляры при обращении к приложению, которые, как я думаю, вам не понадобится.

+0

Спасибо, ваше решение именно то, что я хочу. Я новичок в ваадине в течение 3 дней. Не найдено, что «Навигатор» действительно (теперь я знаю). Кстати, ваши два представления - это статический класс, который должен быть неправильным. И '@Autowired private SpringViewProvider viewProvider;' сообщается 'no beans типа SpringViewProvider type 'от IntelliJ, но работает во время выполнения. – smallufo

+1

@smallufo Вы абсолютно правы, извините, я скоро его обновлю. Первоначально они были внутренними классами, и я должен был сделать их статичными, потому что иначе Spring не смог их создать. Что касается «SpringViewProvider», это может иметь какое-то отношение к версии IJ .. Я знаю, что они добавили поддержку загрузки Spring, начиная с последней версии, возможно, 14 ?! В любом случае, рад, что я мог бы помочь :-) – Morfic

+0

@smallufo btw, если вы только начинаете с Vaadin, вы можете взглянуть на раздел [Рамка из документов] (https://vaadin.com/docs/) или [Книга Ваадина] (https://vaadin.com/download/book-of-vaadin/vaadin-7/pdf/book-of-vaadin.pdf). ура – Morfic