Why am I not able to update my navigation bar (PermanentSlot)?

459 Views Asked by At

Short summary:

I try to update a navigation bar after a place change event. To do so I created a GWTP Test*.java that I try to render in a SLOT_NavBar. However, this is not working. In order to see if I did something wrong I just made itself render in my SLOT_AdminToolMainContent slot which is working perfectly fine. The question is why I can render TestView in one slot but not in the other. GWTP is not giving me any clues about what I'm doing wrong here and I can't find anything in the documention that would help me out here.

I'm sure the problem must be either a misunderstanding from my side or something really stupid that I'm doing but I just fail to see the reason why this is not working.


I'm having here a "root" presenter:

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()");
    }
}

and its view:

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);
    }
}

Everything I'm doing with this is working just fine for example:

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));
    }
}

No problem at all! However, if I try to bind this to another slot:

The issue

@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);
}

Then it's simply doing nothing! I only changed the slot - so why is this not working? Here is the MenuPresenter and related code:

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>

Please explain to me why this is not working - it is driving me nuts. I'm not getting anything from GWTP like "dude, you're trying to do something strange here". No warning, error or info. Just nothing and I don't see what I do wrong here!


To give you an idea how this looks like: The blue bar is the <g:SimplePanel ui:field="navBarPanel"/> which you see in MenuView:

enter image description here

4

There are 4 best solutions below

4
masterdany88 On

Did You tried to replace PernamentSlot with SingleSlot? I am not sure that you can update PernamentSlot.


Did You tried to replace PresenterWidget with Presenter in class extension in MenuPresenter class?

MenuView is widget, no place, So it seems that You did not add this view anywhere, so it simply doesn't display it self. Try to put some static content to this view and see is it even reveal itself.

Try in main view add in constructor widget.add(new MenuView());. where widget is initialized(using java or uibinder) view element.

To display regular Presenter (which is a place)You have to have a url for it (f.e.: localhost:8080/myApp | localhost:8080/myApp#MenuPresenter).

To display PresenterWidget You have to call it somewhere!

5
masterdany88 On

According to documentation here:

NestedSlot: Same as SingleSlot, but can only take Presenters that have Proxies (no PresenterWidget).

and You try to put there a PresenterWidget- WHICH IS WRONG, try to:

  1. replace NestedSlot with Slot or SingleSlot(accepts PresenterWidget),
  2. or change MenuPresenter to extend regular Presenter instead of PresenterWidget.

Try do this and give me feedback.

0
masterdany88 On

You should try to clean and install Your whole application and restart SuperDevMode and Your server.

2
masterdany88 On

I've recreate described functionality. It works. I've base on this article Layout example Layout example. Hope this will help.

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>