Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    smartGWT vs. MVP pattern

    Hello,

    the model view presenter pattern in combination with gwt, which was presented on the google i/o (http://code.google.com/intl/de-DE/ev...ractices.html), doesn't seem to work with Interfaces of smartgwt.

    if I try to add a Listener on a smartgwt specific handler (eg a cellclickhandler for a listgrid) in the presenter, it seems to be completely ignored.

    a sample application of how to use mvp in gwt can be found here: http://code.google.com/p/gwt-mvp-sample/

    a concrete example:

    in the presenter I define an interface:
    Code:
    public class Presenter {
    	
    interface Display {
    HasCellClickHandlers getFoo();
    }
    }
    in the view I implement this interface:
    Code:
    public HasCellClickHandlers getFoo() {
    	return thelistgrid;
    }
    back in the presenter again I bind the view and add the cellclickhandler:
    Code:
    public void bindView(final Display view){
    		this.view = view;
    		
    view.getFoo().addCellClickHandler(new CellClickHandler() {
    			public void onCellClick(CellClickEvent event) {
    				// do something
    				
    			}
    		});
    in this example the onCellClick event is ignored..

    does anyone know how to fix this? Are those interfaces not supported in smartGWT? will they be supported in future?

    best regards and thank you for your help,
    mat
    Last edited by mat.dinister; 12 Aug 2009, 01:17.

    #2
    There's nothing special required to support MVP. The SmartGWT ListGrid cell handlers work just fine and the MVP simply making the appropriate calls to SmartGWT.

    Have a look at this Cell Click sample.

    If you're still having issues, post a simplified standalone testcase that demonstrates the issue.

    Sanjiv

    Comment


      #3
      thanks for your answer, but I still have issues with smartgwt and mvp (I am already working with smartgwt 1.2).

      I prepared a simple demonstration:

      MvpView.java
      Code:
      import com.google.gwt.event.dom.client.HasClickHandlers;
      import com.google.gwt.user.client.ui.Button;
      import com.google.gwt.user.client.ui.Composite;
      import com.google.gwt.user.client.ui.RootPanel;
      import com.smartgwt.client.widgets.grid.ListGrid;
      import com.smartgwt.client.widgets.grid.ListGridField;
      import com.smartgwt.client.widgets.grid.events.HasCellClickHandlers;
      
      
      public class MvpView extends Composite implements MvpPresenter.Display {
      	
      	private final ListGrid countryGrid = new ListGrid();
      	private Button myButton = new Button("save");
      
      	public MvpView() {
              countryGrid.setAlternateRecordStyles(true);  
              countryGrid.setShowAllRecords(true);  
              ListGridField nameField = new ListGridField("countryName", "Country");  
              ListGridField capitalField = new ListGridField("capital", "Capital");  
              ListGridField continentField = new ListGridField("continent", "Continent");  
              countryGrid.setFields(nameField, capitalField, continentField);  
              countryGrid.setData(CountryData.getRecords());
      
      //       works here but has to be in the presenter (mvp pattern)        
      //        countryGrid.addCellClickHandler(new CellClickHandler() {  
      //			public void onCellClick(CellClickEvent event) {
      //				GWT.log("oncellclick listgrid sucessful here but should be in the presenter!", null);
      //			}
      //	    });
              
      		RootPanel.get().add(countryGrid);
      		RootPanel.get().add(myButton);
      	}
      
      	public HasCellClickHandlers getListGridCellClick() {
      		return countryGrid;
      	}
      
      	public HasClickHandlers getMyButton() {
      		return myButton;
      	}
      }
      MvpPresenter:
      Code:
      import com.google.gwt.core.client.GWT;
      import com.google.gwt.event.dom.client.ClickEvent;
      import com.google.gwt.event.dom.client.ClickHandler;
      import com.google.gwt.event.dom.client.HasClickHandlers;
      import com.smartgwt.client.widgets.grid.events.CellClickEvent;
      import com.smartgwt.client.widgets.grid.events.CellClickHandler;
      import com.smartgwt.client.widgets.grid.events.HasCellClickHandlers;
      
      public class MvpPresenter {
      	interface Display {
      		HasClickHandlers getMyButton();
      		HasCellClickHandlers getListGridCellClick();
      	}
      	
      	private Display view;
      
      	public void bindView(final Display view) {
      		this.view=view;
      		
      		view.getMyButton().addClickHandler(new ClickHandler() {
      			public void onClick(ClickEvent event) {
      				GWT.log("onclick button sucessful", null);
      			}
      		});
      		
      		view.getListGridCellClick().addCellClickHandler(new CellClickHandler() {  
      			public void onCellClick(CellClickEvent event) {
      				GWT.log("oncellclick listgrid sucessful", null);
      			}
      	    });
      	}
      }
      and the entry point binds the view:
      Code:
      public void onModuleLoad() {
      		presenter.bindView(view);	
      	}
      CountryRecord and CountryData as shown in the smartgwt showcase.

      The problem is, still, that the CellClickHandler is ignored in the presenter, but would work in the view directly.

      any suggestions?

      Comment


        #4
        the related ticket on the issue tracker can be found here:
        http://code.google.com/p/smartgwt/is...ary%20Reporter

        Comment


          #5
          Hi All
          For mvp concepts i created some several classes which are implemented HasClickHandlers

          This is stub for IButton

          Code:
          import ClickHandlerImpl;
          
          import com.google.gwt.event.dom.client.ClickHandler;
          import com.google.gwt.event.dom.client.HasClickHandlers;
          import com.google.gwt.event.shared.HandlerRegistration;
          
          public class IButton extends com.smartgwt.client.widgets.IButton implements HasClickHandlers {
          
            public HandlerRegistration addClickHandler(ClickHandler clickHandler) {
              return super.addClickHandler(new ClickHandlerImpl(clickHandler));
            }
            
          }
          Here ClickHandlerImpl is some implementation of GWT ClickHandler like

          Code:
          public class ClickEventImpl extends ClickEvent {
          }
          After this You can use IButton as GWT HasClickHandler component in your Presenter class

          Code:
          import com.google.gwt.event.dom.client.ClickEvent;
          import com.google.gwt.event.dom.client.ClickHandler;
          import com.google.gwt.event.dom.client.HasClickHandlers;
          
          public class Presenter {
          
            public interface Display {
              HasClickHandlers getTestButton();
            }
            
            public void bindDisplay(Display d) {
              d.getTestButton().addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                  // do something
                }
              });
            }
            
          }
          and below some Display implementation
          Code:
          import com.google.gwt.event.dom.client.HasClickHandlers;
          import com.google.gwt.user.client.ui.RootPanel;
          
          
          public class View implements Presenter.Display {
            
            private IButton testButton;
            
            public View() {
              testButton = new IButton("Test");
              RootPanel.get().add(testButton);
            }
          
            public HasClickHandlers getTestButton() {
              return testButton;
            }
            
          }
          I implemented several components such IButton, ImgButton, TreeGrid, ListGrid, ect.
          Likely you can implement HasValue<T>, HasSelectionHandlers<T>, ect.

          I hope GmartGWT team will implement GWT Has... interfaces in their components.
          Thanks

          Comment


            #6
            gavrikvetal,
            I'm not sure what you're trying to do here? The SmartGWT components do implement various handlers and there's absolutely no need to adapt the IButton's HasClickHandlers with com.google.gwt.event.dom.client.HasClickHandlers.

            You can implement MVP with any *Handler as illustrated in mat.dinister's sample.

            Sanjiv

            Comment


              #7
              mvp

              Hi Sjivan,
              I'm currently working on a gwt app that we are porting over to smartgwt and I'm experiencing the same problems when trying to use the MVP pattern with an itemButton.
              if I add a listener directly to the button an event is fired but if i had a listener in my presenter class it is ignored. I've read above that you have fixed this problem and was wondering if you could direct me to the fix or the patch.

              regards Naim

              Comment


                #8
                The issue mat.dinister posted was resolved in SVN. Can you try running using the latest build from SVN from here : http://www.smartclient.com/smartgwt/builds/

                If you're still having issues, please post a standalone testcase. Note that I'm planning on releasing SmartGWT 1.2.1 which incorporates some minor bugfixes and module refactoring pretty soon (perhaps this weekend).

                Sanjiv

                Comment


                  #9
                  Hi Sjivan,
                  Thanks for the quick response I'm now currently using the latest build and the issue seems to be resolved thanks again .

                  Comment


                    #10
                    MVP pattern and GWT Interfaces

                    I checked 1.3 and I do not see a way to represent a DynamicForm, a Grid, a TextItem, etc., as a single interface in the Presenter. It seems to be that you still need to create custom interfaces - and derived types of these SmartGWT componentes that implement these interfaces -.

                    Has anybody using the MVP pattern found a better way?

                    To clarify, in MVP you do not want the implementation classes (such as DynamicForm) to appear in the Presenter - they should just be present on the View -. O/w you cannot create standard JUnit cases (you have to use GWTTestCase). Thus, you need interfaces that can be used to replace these components in the Presenter.

                    I would go further and state that SmartGWT - as a project based on GWT -should try to follow/implement as much as possible the same interfaces that GWT defines. That way, we can be sure that in the future any changes/improvements to GWT will not imply a huge refactoring for SmartGWT....nor for our projects based on SmartGWT.

                    Thanks
                    Last edited by netname; 28 Sep 2009, 08:38.

                    Comment


                      #11
                      Hi netname,

                      It looks like you first need to get further into SmartGWT and understand it's recommended architecture. A DynamicForm and TextItem are the same thing; a Grid is different in kind in that it works with multiple items (Records) whereas a DynamicForm works with a single item (single Record).

                      You should also first indicate your goals in using MVP, for example, a swappable presentation layer? To other GWT toolkits or more fundamentally to entirely foreign presentation systems (eg WinForms)? Only by answering these questions can you pick the right way to integrate with SmartGWT (or anything else).

                      Comment


                        #12
                        Why use MVP?

                        Isomorphic:

                        >> You should also first indicate your goals in using MVP...

                        How about:
                        - Make the client code testable
                        - Use a recognized pattern to organize the client code in discrete parts
                        - be able to use frameworks like gwt-presenter

                        >> ... A DynamicForm and TextItem are the same thing....

                        Yes, but the way I want to represent them (and use them) on the Presenter side is different. For a TextItem I am just interested in being able to have access to methods SetText and GetText, while for a DynamicForm I need a lot more methods (some unique to the Form like the ones in HasFormSubmitFailedHandlers) so the correct way is to have different interfaces showing only our intentions.

                        As of now, I have to bundle a lot of SmartGWT interfaces in a single abstract interface and have a custom component inherit from it since SmartGWT's components implement a bunch of interfaces, like DynamicForm, instead of just implementing a single interface that implies the "formness" of the object. (In MVP I just want to define a field as HasValue, HasForm, etc., I do not want the implementation to appear).

                        In summary, following the MVP pattern is doable with SmartGWT as of now. You just have to create and inherit from additional components. A bunch of extra stuff. Is that the best way? I am suggesting that it seems worthwhile to evaluate this and see if SmartGWT should follow GWT's lead on this.

                        Thanks,

                        Comment


                          #13
                          The client code is already testable, and the samples achieve far, far more than any MVP sample that we've ever reviewed, with far, far, less code.

                          The "formness" of an object is only useful if you *assume first* that you will be writing reams and reams of code to manually bind each UI component to the model. But SmartGWT already exposes a much richer concept - the DataSource and the awareness of DataSources that all DataBoundComponents have. Think of our UI components as having default Presenter logic that already understands a standardized and pluggable Model. At that point, you are starting further along, and your code consists of declarations and overrides of Presenter built-in logic.

                          For this reason, we would only recommend the MVP pattern for someone who has a special goal, such as a completely plug-replaceable UI. And even in that case, the integration point is probably not the UI components themselves, but again the DataSources.

                          Comment


                            #14
                            Example of using SmartGWT with MVP

                            Has anyone used the Gin and Guice? Can you provide an example using SmartGWT with MVP? Thanks! -M

                            Comment


                              #15
                              Never mind.

                              After reading the whole thread, I was able to make my own example works with MVP and gin and guice. Thanks!

                              Comment

                              Working...
                              X