Announcement

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

    #16
    Smart GWT / MVP

    Originally posted by Isomorphic
    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.
    Hi,

    I'm facing exactly this problem. The goal is to write an application on which view issues are completely decoupled from the other parts of the system. However, to use Smart GWT widgets, it's required to define a datasource that use smart-gwt defined protocols (JSON, XML, etc), and the views communicate directly with the server using these datasources.

    I'd like to use the GWT RPC mechanism and object serialization mechanism, having no need to provide server side XML / JSON service implementations; but there's no datasource.set(datacollection) method...

    At this point, I'm in doubt if I really understood the "Smart GWT way", and if it's appropriate to me. The rich widget library fits very very nice, but data integration gets me confused.

    Any insights to help me choose an appropriate solution?
    Thanks,
    Fábio.

    Comment


      #17
      @fabiolnm Since you are talking about GWT-RPC, which is a GWT-specific technology, this seems to mean that you want to create a Java API that could be shared by another front-end (say, a Swing-based installable Java app using RMI).

      If so, the best approach is to use the DMI of SmartGWT Pro to declaratively map SmartClient DataSource operations to your UI-agnostic Java APIs.

      Note that if the SmartGWT Pro/EE SQL or Hibernate DataSources are useful to you, you can use them with another UI technology. Server-side, you would just use the server-side DataSource APIs. Client-side, if your other UI is browser-based, you could possibly use SmartClient's JavaScript DataSource and ResultSet APIs to integrate SmartClient's data services with other UI libraries.

      Comment


        #18
        Cannot bind presenter to view if view is in TabPanel

        SmartGWT version:2.0 / 2.1
        GWT version: 2.0.3
        Browser: FireFox 3.5/Win Vista
        Error/log: none

        I am using the MVP architecture for my application which is recommended by google. It works fine with smartgwt. However, if i implement my views in smartgwt tabs, the presenter is unable to bind the functions to the views. As a testcase, i have converted the CompoundEditor of smartgwt showcase to a view, and implemented the business logic in a presenter. This works when i bind the presenter to the rootpanel, but fails when the view is set in a tabset.

        The view code for the compound editor is as follows
        Code:
        public class CompoundEditor extends HLayout implements TestCEPresenter.Display {
        	private DataSource	datasource;
        	private DynamicForm	form;
        	private ListGrid	grid;
        	private IButton		saveButton;
        
        	public CompoundEditor(DataSource datasource) {
        		this.datasource = datasource;
        		this.form = new DynamicForm();
        		saveButton = new IButton("Save");
        		grid = new ListGrid();
        
        	}
        
        	@Override
        	protected void onInit() {
        		super.onInit();
        		this.form = new DynamicForm();
        
        		form.setDataSource(datasource);
        
        		saveButton = new IButton("Save");
        		saveButton.setLayoutAlign(Alignment.CENTER);
        
        		VLayout editorLayout = new VLayout(5);
        		editorLayout.addMember(form);
        		editorLayout.addMember(saveButton);
        		editorLayout.setWidth(280);
        
        		grid = new ListGrid();
        		grid.setWidth(500);
        		grid.setHeight(350);
        		grid.setDataSource(datasource);
        		grid.setAutoFetchData(true);
        		grid.setCanEdit(true);
        		grid.setEditEvent(ListGridEditEvent.CLICK);
        		grid.setAutoSaveEdits(true);
        		addMember(grid);
        		addMember(editorLayout);
        	}
        
        	public DataSource getDatasource() {
        		return datasource;
        	}
        
        	public void setDatasource(DataSource datasource) {
        		this.datasource = datasource;
        		grid.setDataSource(datasource);
        		form.setDataSource(datasource);
        		saveButton.disable();
        		grid.fetchData();
        	}
        
        	@Override
        	public Widget asWidget() {
        		// TODO Auto-generated method stub
        		return this;
        	}
        
        	@Override
        	public HasRecordClickHandlers getGrid() {
        		// TODO Auto-generated method stub
        		return this.grid;
        	}
        
        	@Override
        	public HasClickHandlers getSaveButton() {
        		// TODO Auto-generated method stub
        		return this.saveButton;
        	}
        }
        The presenter for the same is -

        Code:
        public class TestCEPresenter implements Presenter {
        	public interface Display {
        		HasClickHandlers getSaveButton();
        
        		HasRecordClickHandlers getGrid();
        
        		Widget asWidget();
        	}
        
        	private Display	display;
        
        	public TestCEPresenter(Display display) {
        		this.display = display;
        	}
        
        	private void bind() {
        		display.getSaveButton().addClickHandler(new ClickHandler() {
        
        			@Override
        			public void onClick(ClickEvent event) {
        				Window.alert("Clicked");
        
        			}
        		});
        		System.out.println("Bounded!!!!!!!!!!!!!!!!!!!!");
        	}
        
        	@Override
        	public void go(HasWidgets container) {
        		bind();
        		container.clear();
        		container.add(display.asWidget());
        
        	}
        
        	@Override
        	public Widget goAsWidget() {
        		bind();
        		return display.asWidget();
        	}
        
        	@Override
        	public void remove() {
        		// TODO Auto-generated method stub
        
        	}
        
        }
        The onmodule load code -
        Code:
        		TestCEPresenter presT = new TestCEPresenter(new CompoundEditor(	new DataSource()));
        
        		Canvas hpane = new Canvas();
        
        		hpane.addChild(presT.goAsWidget());
        		Tab t = new Tab();
        		t.setPane(hpane);
        		TabSet tt = new TabSet();
        		tt.addTab(t);
        		tt.setWidth("100%");
        		tt.setHeight("100%");
        		tt.draw();

        Comment


          #19
          Update

          Any Update on this issue?

          Comment


            #20
            Hi,

            You might want to check out gwt-platform (GWTP). Try searching for "gwt-platform and smartGWT" and it should return several good blog postings (e.g. http://uptick.com.au/blog).

            Good luck
            Mark

            Comment


              #21
              I'm having an issue with binding an IButton, and I wanted to know if this still seems to be a problem:

              Code:
              display.getTestButton().addClickHandler(new ClickHandler()
                      {
                          public void onClick(ClickEvent clickEvent)
                          {
                              //dispatch the event that will create the module on the main application
                              eventBus.fireEvent(new CreateLogModuleEvent());
                              SC.say("a new log module should be created");
                          }
                      });
              This is from the bind() method of the presenter, and I know it's getting called because the SC.say displays.

              However no event is ever fired when the button is clicked

              Comment


                #22
                Just to reiterate what's been said in this thread, don't use MVP unless you've really figured out a compelling reason why it must be used. Otherwise you're just creating unnecessary code.

                There's no known problem with adding a click handler to a button on the fly. If you think this might be a framework bug, try to simplify your code down to a runnable test case. As other users have reported, MVP can make this very hard..

                Comment


                  #23
                  Thanks for the reply. I see that the forum admins have noted that using mvp is not a good idea here. Is there something that we can do using SmartGWT to achieve similar benefits of the MVP pattern? For example is there a way to keep the user interface dumb and have something like a presenter manipulate it for you? Is there a way to keep application logic out of the view code? Does the framework have a similar implementation of Places in the appController? Is there a way to have something like a presenter bind to controls (like buttons) in the view so that non-databound controls can make calls to the server outside of the view?

                  Thanks
                  Last edited by ls3674; 22 Dec 2011, 12:37.

                  Comment


                    #24
                    MVP was introduced by Google for Google's GWT widgets because they have no data binding capabilities or data awareness. SmartGWT widgets have data binding built in.

                    Adding a Presenter to something like a ListGrid is redundant - there is already an extremely sophisticated system in place for handling the complex problem of a grid bound to a paged, remote dataset and providing filtering, sorting, editing etc capabilities.

                    When you try to "add a Presenter" to this you start down the road of completely replicating all these built-in capabilities - you don't want to do this.

                    If you like, the Presenter is built into the ListGrid and voila - you're using MVP. Now, let's talk about what you're trying to achieve without using MVP terminology. What *specific* function are you trying to build, and/or, what specific encapsulation or separate in the code are you trying to achieve, and critically, what's the point of that encapsulation? What scenario of future changes, pluggability, etc are you trying to accommodate?

                    Comment


                      #25
                      I want to make it clear, that I understand that MVP can complicate the databound controls scenario. I/we have no intention of using any pattern outside of what SmartGWT already provides with respect to that.

                      The first scenario I want to consider is performing an action on the server that is initiated by the client. This scenario does not involve any databound countrols. For example, startSomeProcess();. This method would be invoked via a dmi with custom operation bindings.

                      At present a button defined in the view would add a clickhandler and preform an action from there. Upon the result, an object/objects in the view would need to be updated, e.g. icon set to green check due to success.

                      In my experience, something like that would be better handed off to something like a presenter/controller- allowing the the view to be void of the logic needed to process the logic on the successful result of the DMI call.

                      In this scenario, I would imagine a presenter/controller like object binding to the view and handling its non-databound logic.

                      To flesh out the scenario --> I have a FooView and a FooController. FooView has an IButton whose purpose is to call a method on the server that sshs to another machine and shuts it down. My previous experience tells me that I should only declare the button in the view, and that I should bind that button to FooController. FooController can then regerister clickHandlers for when that button is pressed. Once the button is pressed, it can pick up on that, make the DMI call, handle the result, and change the icon (setIconState(String someState));

                      I see this being separate from any data bindings. For example, I would use the standard fetch, add, update, remove methods for, say, a datagrid.

                      I hope this makes sense. What I'm trying to figure out is how to best implement logic outside of the view. If this overcomplicates the use of SmartGWT, do you recommend, simply handling this type of logic inside the view class, e.g. FooView, and ditching the presenter/controller concept FooController?

                      I'm looking for the best way to keep the view dumb, is that a paradigm that works here?.... I suppose there are also testing concerns, but we can get to that later. Another consideration is how something like this might tie into the use of Places where I would want to keep state of where the application is, again the above scenario doesn't tie into this but a similar use case could be ellaborated.

                      Thanks,
                      Last edited by ls3674; 22 Dec 2011, 14:51.

                      Comment


                        #26
                        At present a button defined in the view would add a clickhandler and preform an action from there. Upon the result, an object/objects in the view would need to be updated, e.g. icon set to green check due to success.

                        In my experience, something like that would be better handed off to something like a presenter/controller- allowing the the view to be void of the logic needed to process the logic on the successful result of the DMI call.
                        It's appropriate to get logic like out of a button *in some systems* and *for some specific purposes*. What you need to analyze is the *reason* for moving this logic elsewhere, or you are potentially just creating structure for nothing.

                        For example, this sample shows master-detail captured as a reusable component. If we wanted to make it possible for someone to subclass this component and do something additional on save, we would need to make the Save button call up to the CompoundEditor component so we could provide an override point for the save functionality. It would be even more important to do this if there were more than one way to trigger saving and we wanted a central override point for saving regardless of which control does it.

                        That's a valid and specific reason to move code out of a button click handler and into something else, and the place where it goes is not a Presenter but a widget that encapsulates a reusable master-detail interaction.

                        This is the kind of reasoning we recommend doing around your code and where you need to encapsulate things.

                        As far as MVP, consider that users just using core GWT have been complaining about MVP's complexity and MVP is especially dangerous with SmartGWT where many of its recommendations would lead to reinventing the wheel. So ignore MVP unless you discover a specific problem that MVP appears to actually solve.

                        Comment


                          #27
                          This is the answer or very to close the answer that I'm looking for. Where does using something like Gin fit into this equation as well? I get the feeling that using it may also complicate the intended SmartGWT-best-practice-way of things as well.

                          I can start another thread on the topic, since this is specifically related to MVP.

                          Thanks,

                          Comment


                            #28
                            A separate thread is probably good. But in a nutshell, this is another question coming from the wrong direction. The question should not be "where would I use Gin in SmartGWT" but "how do I solve X" - in solving X, we may recommend Gin (almost certainly not :). But we need to start with a problem statement that doesn't assume Gin is part of the solution.

                            Comment


                              #29
                              Understood. Great thread.

                              Thanks!

                              Comment

                              Working...
                              X