3

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

Community
  • 1
  • 1
  • Why do You need: `@NameToken(AdminNameTokens.test)` in `TestPresenter`? – masterdany88 Jun 21 '16 at 09:06
  • @masterdany88 The reason is because the NavBar is supposed to depend on the place. E.g. if you visit `#item` or anything "below" that place as in `localhost:8080/#items/expensiveItems` then I want the `NavBarPresenter` to update itself on this place change event. The advantage would be that 1) It renders itself dynamically and 2) I have the `prepareFromRequest` option if I need it at the navigation bar. Yes, I've tested if this is working. Behind the scenes `prepareFromRequest is getting called but the view is not displayed. – supernickname Jun 21 '16 at 17:09
  • @masterdany88 Okay I might be talking garbage on that one right now. If two places are pointing to the same place only one is getting called on `prepareFromRequest` or I broke another thing now O_o – supernickname Jun 21 '16 at 17:14

4 Answers4

0

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!

masterdany88
  • 5,041
  • 11
  • 58
  • 132
  • Hi! I just tried to replace `PemanentSlot` with `SingleSlot` but the outcome is the same. Yep, the `MenuView` is not a place but it's getting displayed correctly. I have a side nav and a nav bar that gets drawn correctly - the only thing not working is that the nav bar is not being updated. The `Menu*.java` isn't the problem. It gets added in `AdminToolPresenter#onBind` (see above). Everything is working as I'd expect it except from that one thing with the nav bar :/ – supernickname Jun 20 '16 at 06:57
  • How do You bind `PresenterWidget`? Can You post all `Test`* related complete files? – masterdany88 Jun 20 '16 at 07:26
  • I've added `TestView` - do you need the `.ui.xml` and the module as well? There's nothing too exciting about that and like stated in the question.. the whole `Test*.java` thing is working if I render it in `SLOT_AdminToolMainContent`. So this cannot be the issue. – supernickname Jun 20 '16 at 17:38
  • IMHO everything can be an issue :D I will try to recreate Your situation so I need as much information/code as possible. – masterdany88 Jun 21 '16 at 05:43
0

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.

masterdany88
  • 5,041
  • 11
  • 58
  • 132
  • But I have `TestPresenter extends Presenter<>` and not `TestPresenter extends PresenterWidget<>`. I don't understand .. except that.. `Slot` or `SingleSlot` are generic. That means I'd need a "base" `TestBasePresenter` that's "just there" without any additional functionality. I don't see the point in doing that - this would feel wrong to me. Except that.. it does not make sens because it works if I draw it in `SLOT_AdminToolMainContent` which is a `NestedSlot` like `SLOT_NavBar` – supernickname Jun 20 '16 at 17:35
  • I know that both are `NestedSlot` and it work for one and not for the other, but I think it is not the case of Your problem. I think also that You should use for this `breadcrumps` a `widget`. Please read again this artice: http://dev.arcbees.com/gwtp/core/presenters/ maybe You are missing something. Try to recreate Yours code basing on this example. – masterdany88 Jun 21 '16 at 05:58
  • `MenuPresenter` extends `PresenterWidget` which is wrong. `AdminToolPresenter` extends `Presenter` which is correct You have to change it! – masterdany88 Jun 21 '16 at 08:20
  • Okay I've re-implemented the menu into a `Presenter` but so far it didn't change anything yet .. I'll read through your other suggestions! Thank you very much for putting so much effort into helping me! – supernickname Jun 21 '16 at 16:40
  • Btw if it's wrong then it should not work [here](https://github.com/GwtMaterialDesign/gwt-material-demo/blob/master/src/main/java/gwt/material/design/demo/client/application/menu/MenuPresenter.java) as well. I've been following the documentation *and* the GWTMD demo to implement my solution - although there is no "*render `NestedSlot` inside `PermanentSlot`*" situtation. – Stefan Falk Jun 21 '16 at 16:55
0

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

masterdany88
  • 5,041
  • 11
  • 58
  • 132
0

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>
masterdany88
  • 5,041
  • 11
  • 58
  • 132
  • I'm sorry but this does not resemble my situation. I believe you that this is working. This is somewhat the same as if I replace `super(eventBus, view, proxy, MenuPresenter.SLOT_NavBar);` by `super(eventBus, view, proxy, MenuPresenter.SLOT_NavBar);` super(eventBus, view, proxy, AdminToolPresenter.SLOT_AdminToolMainContent);` which is also working for me perfectly fine. I've still now followed your other suggestions like changing `SLOT_Menu` from `PermanentSlot` to `NestedSlot`. Also the `MenuPresenter` is now a `Presenter` instead of a `PresenterWidget`. However, it's still the same. – supernickname Jun 21 '16 at 16:50
  • I cannot render in `SLOT_NavBar` and in my opinion I am doing everything as it should be. – supernickname Jun 21 '16 at 16:50