Почему я не могу обновить панель навигации (PermanentSlot)?

Краткое резюме:

Я пытаюсь обновить панель навигации после события смены места. Для этого я создал GWTP Test*.java, который пытаюсь отобразить в SLOT_NavBar. Однако это не работает. Чтобы увидеть, не сделал ли я что-то не так, я просто сделал рендеринг в моем слоте SLOT_AdminToolMainContent, который отлично работает. Вопрос в том, почему я могу отрендерить TestView в одном слоте, но не могу в другом. GWTP не дает мне никаких подсказок о том, что я здесь делаю неправильно, и я не могу найти в документации ничего, что могло бы мне помочь.

Я уверен, что проблема должна быть либо в недоразумении с моей стороны, либо в чем-то действительно глупом, что я делаю, но я просто не вижу причины, по которой это не работает.


У меня есть корневой ведущий:

AdminToolPresenter.java

public class AdminToolPresenter extends Presenter<AdminToolPresenter.MyView, AdminToolPresenter.MyProxy> {
        
    public interface MyView extends View {      
    }

    @ProxyStandard
    @NameToken(AdminNameTokens.adminTool)
    @UseGatekeeper(AdminGatekeeper.class)
    public interface MyProxy extends ProxyPlace<AdminToolPresenter> {
    }
    
    /** */
    public static final PermanentSlot<MenuPresenter> SLOT_Menu = new PermanentSlot<>();
    
    /** */
    public static final NestedSlot SLOT_AdminToolMainContent = new NestedSlot();
    
    /** */
    private MenuPresenter menuPresenter;
    
    @Inject
    public AdminToolPresenter(EventBus eventBus, MyView view, MyProxy proxy, MenuPresenter menuPresenter) {
        super(eventBus, view, proxy, RevealType.RootLayout);
        this.menuPresenter = menuPresenter;
    }
    
    @Override
    protected void onBind() {

        this.setInSlot(SLOT_Menu, this.menuPresenter);
    }

    @Override
    protected void onReveal() {
        LOGGER.fine("AdminToolPresenter.onReveal()");
    }
}

и его вид:

AdminToolView.java

public class AdminToolView extends ViewImpl implements AdminToolPresenter.MyView {
    
    @SuppressWarnings("unused")
    private final static Logger LOGGER = Logger.getLogger(AdminToolView.class.getName());

    public interface Binder extends UiBinder<Widget, AdminToolView> {
    }
    
    @UiField HTMLPanel menuPanel;
    
    @UiField SimplePanel adminMainContent;

    @Inject
    public AdminToolView(Binder uiBinder) {

        this.initWidget(uiBinder.createAndBindUi(this));
        
        this.bindSlot(AdminToolPresenter.SLOT_Menu, this.menuPanel);
        this.bindSlot(AdminToolPresenter.SLOT_AdminToolMainContent, this.adminMainContent);
    }
}

Все, что я делаю с этим, работает отлично, например:

TestPresenter.java

public class TestPresenter extends Presenter<TestPresenter.MyView, TestPresenter.MyProxy> implements TestUiHandlers {
    
    private final static Logger LOGGER = Logger.getLogger(TestPresenter.class.getName());
    
    interface MyView extends View , HasUiHandlers<TestUiHandlers> {
    }

    @NameToken(AdminNameTokens.test)
    @ProxyStandard
    interface MyProxy extends ProxyPlace<TestPresenter> {
    }

    @Inject
    TestPresenter(EventBus eventBus, MyView view, MyProxy proxy) {

        // This is working just fine. The content gets displayed correctly in the SLOT_AdminToolMainContent slot
        super(eventBus, view, proxy, AdminToolPresenter.SLOT_AdminToolMainContent);
        
        this.getView().setUiHandlers(this);
    }
    
    @Override
    public void prepareFromRequest(PlaceRequest request) {
        LOGGER.severe("prepareFromRequest");
        super.prepareFromRequest(request);
    }
    
}

TestView.java

class TestView extends ViewWithUiHandlers<TestUiHandlers> implements TestPresenter.MyView {
    
    interface Binder extends UiBinder<Widget, TestView> {
    }

    @UiField SimplePanel main;

    @Inject TestView(Binder uiBinder) {
        this.initWidget(uiBinder.createAndBindUi(this));
    }
}

Совершенно никаких проблем! Однако, если я попытаюсь привязать это к другому слоту:

Проблема

@Inject
TestPresenter(EventBus eventBus, MyView view, MyProxy proxy) {

    // MenuPresenter.SLOT_NavBar instead of AdminToolPresenter.SLOT_AdminToolMainContent
    super(eventBus, view, proxy, MenuPresenter.SLOT_NavBar);
    
    this.getView().setUiHandlers(this);
}

Тогда он просто ничего не делает! Я только слот поменял - так почему это не работает? Вот MenuPresenter и связанный с ним код:

MenuPresenter.java

public class MenuPresenter extends PresenterWidget<MenuPresenter.MyView> implements MenuUiHandlers {

    private final static Logger LOGGER = Logger.getLogger(MenuPresenter.class.getName());
    
    interface MyView extends View, HasUiHandlers<MenuUiHandlers> {
        
    }
    
    /** Slot for the navigation bar. */
    public static final NestedSlot SLOT_NavBar = new NestedSlot();
    
    @Inject
    MenuPresenter(EventBus eventBus, MyView view) {     
        super(eventBus, view);      
        this.getView().setUiHandlers(this);
    }

    @Override
    protected void onReveal() {
        LOGGER.severe("onReveal()");
    }
}

MenuView.java

class MenuView extends ViewWithUiHandlers<MenuUiHandlers> implements MenuPresenter.MyView {
    
    interface Binder extends UiBinder<Widget, MenuView> {
    }

    @UiField HTMLPanel navBarPanel;

    @UiField MaterialSideNav sideNav;

    private PlaceManager placeManager;
    
    @Inject MenuView(Binder uiBinder, PlaceManager placeManager) {
        
        this.initWidget(uiBinder.createAndBindUi(this));
        
        this.bindSlot(MenuPresenter.SLOT_NavBar, this.navBarPanel);
        
        this.placeManager = placeManager;
    }
}

MenuView.ui.xml

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui"
    xmlns:m="urn:import:gwt.material.design.client.ui"
    xmlns:m.addins="urn:import:gwt.material.design.addins.client.ui">   
    <ui:with field="tokens" type="com.mz.client.admin.place.AdminNameTokens"/>    
    <ui:style gss="true">
    /* .. */    
    </ui:style> 
    <g:HTMLPanel ui:field="main">
        
        <g:HTMLPanel addStyleNames="{style.navbar-wrapper}">
            <g:SimplePanel ui:field="navBarPanel" />                        
        </g:HTMLPanel>
        
        <m:MaterialHeader>

            <m:MaterialNavBar backgroundColor="white" activates="sideNav" layoutPosition="RELATIVE" addStyleNames="{style.nav-bar}">                
                <m:MaterialNavSection>              
                </m:MaterialNavSection>             
            </m:MaterialNavBar >
            
            <m:MaterialSideNav ui:field="sideNav" m:id="sideNav" type="FIXED" alwaysShowActivator="true" width="280" addStyleNames="{style.side-nav}" >         
                <m:MaterialLink targetHistoryToken="{tokens.getHome}" iconType="HOME" iconPosition="LEFT" textColor="black" text="Home" />                  
            </m:MaterialSideNav>
            
        </m:MaterialHeader>
        
    </g:HTMLPanel>
</ui:UiBinder>

Пожалуйста, объясните мне, почему это не работает - это сводит меня с ума. Я ничего не получаю от GWTP, как чувак, ты пытаешься сделать что-то странное здесь. Никаких предупреждений, ошибок или информации. Просто ничего, и я не вижу, что я делаю неправильно здесь!


Чтобы дать вам представление о том, как это выглядит: синяя полоса — это <g:SimplePanel ui:field="navBarPanel"/>, который вы видите в MenuView:

введите здесь описание изображения


person supernickname    schedule 19.06.2016    source источник
comment
Зачем Вам нужно: @NameToken(AdminNameTokens.test) в TestPresenter?   -  person masterdany88    schedule 21.06.2016
comment
@ masterdany88 Причина в том, что NavBar должен зависеть от места. Например. если вы посещаете #item или что-то еще ниже этого места, как в localhost:8080/#items/expensiveItems, тогда я хочу, чтобы NavBarPresenter обновлял себя при изменении этого места. Преимущество будет заключаться в том, что 1) он отображается динамически и 2) у меня есть опция prepareFromRequest, если она мне нужна на панели навигации. Да, я проверил, работает ли это. За кулисами вызывается `prepareFromRequest, но представление не отображается.   -  person supernickname    schedule 21.06.2016
comment
@ masterdany88 Хорошо, я, возможно, сейчас говорю чушь об этом. Если два места указывают на одно и то же место, prepareFromRequest вызывается только одно, или я сломал еще одну вещь O_o   -  person supernickname    schedule 21.06.2016


Ответы (4)


Вы пытались заменить PernamentSlot на SingleSlot? Я не уверен, что вы можете обновить PernamentSlot.


Вы пытались заменить PresenterWidget на Presenter в расширении класса в классе MenuPresenter?

MenuView это виджет, места нет, так что видимо Вы никуда не добавляли этот вид, поэтому он просто сам себя не отображает. Попробуйте поместить в это представление какой-нибудь статический контент и посмотрите, покажет ли он себя.

Попробуйте в главном представлении добавить в конструктор widget.add(new MenuView());. где виджет инициализируется (используя java или uibinder) элементом представления.

Чтобы отобразить обычный Presenter (то есть место), у вас должен быть URL-адрес для него (например: localhost: 8080/myApp | localhost: 8080/myApp#MenuPresenter).

Чтобы отобразить PresenterWidget, вы должны где-то его вызвать!

person masterdany88    schedule 20.06.2016
comment
Привет! Я только что попытался заменить PemanentSlot на SingleSlot, но результат тот же. Да, MenuView — это не место, но оно отображается правильно. У меня есть боковая навигация и панель навигации, которые отображаются правильно - единственное, что не работает, это то, что панель навигации не обновляется. Menu*.java не проблема. Он добавляется в AdminToolPresenter#onBind (см. выше). Все работает, как я и ожидал, за исключением одной вещи с панелью навигации: / - person supernickname; 20.06.2016
comment
Как вы связываете PresenterWidget? Можете ли вы опубликовать все полные файлы, связанные с Test*? - person masterdany88; 20.06.2016
comment
Я добавил TestView - вам нужен .ui.xml и модуль? В этом нет ничего слишком захватывающего, и, как указано в вопросе ... вся штука Test*.java работает, если я визуализирую ее в SLOT_AdminToolMainContent. Так что это не может быть проблемой. - person supernickname; 20.06.2016
comment
ИМХО все может быть проблемой :D Я попытаюсь воссоздать вашу ситуацию, поэтому мне нужно как можно больше информации/кода. - person masterdany88; 21.06.2016

Согласно документации здесь:

NestedSlot: то же, что и SingleSlot, но может принимать только Presenters, у которых есть Proxies (нет PresenterWidget).

и Вы пытаетесь поставить там PresenterWidget- ЧТО НЕПРАВИЛЬНО, попробуйте:

  1. замените NestedSlot на Slot или SingleSlot (принимает PresenterWidget),
  2. или измените MenuPresenter, чтобы расширить обычный Presenter вместо PresenterWidget.

Попробуйте сделать это и дайте мне обратную связь.

person masterdany88    schedule 20.06.2016
comment
Но у меня TestPresenter extends Presenter<>, а не TestPresenter extends PresenterWidget<>. Я не понимаю .. кроме того .. Slot<T> или SingleSlot<T> являются общими. Это означает, что мне понадобится базовый TestBasePresenter, без каких-либо дополнительных функций. Я не вижу смысла в этом - мне это кажется неправильным. За исключением того, что ... это не имеет смысла, потому что это работает, если я нарисую его в SLOT_AdminToolMainContent, который NestedSlot похож на SLOT_NavBar - person supernickname; 20.06.2016
comment
Я знаю, что оба они NestedSlot, и это работает для одного и не для другого, но я думаю, что это не относится к Вашей проблеме. Я также думаю, что Вам следует использовать для этого breadcrumps и widget. Прочтите еще раз эту статью: dev.arcbees.com/gwtp/core/presenters возможно Вы что-то упускаете. Попробуйте воссоздать Ваш код на основе этого примера. - person masterdany88; 21.06.2016
comment
MenuPresenter расширяет PresenterWidget, что неверно. AdminToolPresenter расширяет Presenter, что правильно Вы должны изменить это! - person masterdany88; 21.06.2016
comment
Хорошо, я переделал меню в Presenter, но пока это ничего не изменило.. Я прочитаю другие ваши предложения! Большое спасибо за то, что приложили столько усилий, чтобы помочь мне! - person supernickname; 21.06.2016
comment
Кстати, если это неправильно, то это не должно работать здесь. Я следил за документацией и демо GWTMD, чтобы реализовать свое решение, хотя в ситуации PermanentSlot нет рендеринга NestedSlot. - person Stefan Falk; 21.06.2016

Вы должны попробовать clean и install все ваше приложение и перезапустить SuperDevMode и ваш сервер.

person masterdany88    schedule 21.06.2016

Я воссоздал описанную функциональность. Оно работает. Я основываюсь на этой статье Пример макета Пример макета. Надеюсь, это поможет.

package pl.korbeldaniel.cms.client.place.app;
public class AppModule extends AbstractPresenterModule {
    @Override
    protected void configure() {
    install(new UiModule());

    bindPresenter(AppPresenter.class, AppPresenter.MyView.class, AppView.class, AppPresenter.MyProxy.class);
    bindPresenter(HomePresenter.class, HomePresenter.MyView.class, HomeView.class, HomePresenter.MyProxy.class);
    bindPresenter(ErrorPresenter.class, ErrorPresenter.MyView.class, 
    bindPresenter(TesttPresenter.class, TesttPresenter.MyView.class, TesttView.class, TesttPresenter.MyProxy.class);

    }
}

package pl.korbeldaniel.cms.client.place.app;

public class AppPresenter extends TabContainerPresenter<AppPresenter.MyView, AppPresenter.MyProxy> implements AppUiHandlers, CurrentUserChangedHandler, AsyncCallStartHandler, AsyncCallFailHandler, AsyncCallSucceedHandler {
    @ProxyStandard
    public interface MyProxy extends Proxy<AppPresenter> {}
    public interface MyView extends TabView, HasUiHandlers<AppUiHandlers> {}

    public static final NestedSlot SLOT_NavBar = new NestedSlot();
    private final TesttPresenter testtPresenter;

    @Inject
    AppPresenter(EventBus eventBus, MyView view, MyProxy proxy, TesttPresenter testtPresenter) {
        super(eventBus, view, proxy, SLOT_TAB_CONTENT, SLOT_REQUEST_TABS, SLOT_CHANGE_TAB, RevealType.Root);
        this.testtPresenter = testtPresenter;
        getView().setUiHandlers(this);
    }
    @Override
    protected void onBind() {
        super.onBind();
        setInSlot(SLOT_NavBar, testtPresenter);
    }
}

package pl.korbeldaniel.cms.client.place.app;

public class AppView extends ViewWithUiHandlers<AppUiHandlers> implements AppPresenter.MyView {
    public interface Binder extends UiBinder<Widget, AppView> {}

    @UiField MaterialRow navBarPanel;

    @Inject
    AppView(Binder uiBinder) {
        initWidget(uiBinder.createAndBindUi(this));
        bindSlot(AppPresenter.SLOT_NavBar, navBarPanel);
    }
}

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:m="urn:import:gwt.material.design.client.ui"

    <m:MaterialPanel>
      <m:MaterialRow ui:field="navBarPanel" />                        
    </m:MaterialPanel>
</ui:UiBinder>

package pl.korbeldaniel.cms.client.playground.test.testt;

import pl.korbeldaniel.cms.client.place.app.AppPresenter;

public class TesttPresenter extends Presenter<TesttPresenter.MyView, TesttPresenter.MyProxy> {
    public interface MyView extends View {}
    @ProxyStandard
    public interface MyProxy extends Proxy<TesttPresenter> {}
    @Inject
    public TesttPresenter(EventBus eventBus, MyView view, MyProxy proxy) {
        super(eventBus, view, proxy, AppPresenter.SLOT_NavBar);
    }
}

package pl.korbeldaniel.cms.client.playground.test.testt;

import pl.korbeldaniel.cms.client.place.app.AppPresenter;

public class TesttView extends ViewImpl implements TesttPresenter.MyView {
    public interface Binder extends UiBinder<Widget, TesttView> {}
    @UiField
    SimplePanel main;
    @Inject
    public TesttView(Binder uiBinder) {
        initWidget(uiBinder.createAndBindUi(this));
        main.add(new Label("____________________________________________________________________________________________________________________>TEST "));
        Window.alert("TESTT");
        this.bindSlot(AppPresenter.SLOT_NavBar, this.main);
    }
}

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
             xmlns:g="urn:import:com.google.gwt.user.client.ui">
    <g:SimplePanel ui:field="main"></g:SimplePanel>
</ui:UiBinder>
person masterdany88    schedule 21.06.2016
comment
Извините, но это не похоже на мою ситуацию. Я верю вам, что это работает. Это примерно то же самое, как если бы я заменил super(eventBus, view, proxy, MenuPresenter.SLOT_NavBar); на super(eventBus, view, proxy, MenuPresenter.SLOT_NavBar); super(eventBus, view, proxy, AdminToolPresenter.SLOT_AdminToolMainContent);`, который у меня тоже отлично работает. Я все еще следил за другими вашими предложениями, такими как изменение SLOT_Menu с PermanentSlot на NestedSlot. Также MenuPresenter теперь Presenter вместо PresenterWidget. Тем не менее, это все то же самое. - person supernickname; 21.06.2016
comment
Я не могу рендерить в SLOT_NavBar и по-моему делаю все как надо. - person supernickname; 21.06.2016