I'm currently working on a ZK screen with a Listbox that contains groups. Since you can't (as far as I know) use DataBinder to set the model with a GroupsModel, I'm manually creating one and calling setModel. To configure the Listgroups and Listitems I need to create a ListitemRenderer, which I've done.
The problem is that whenever you open or close a group on the screen, it communicates with the server to set the group as being open, and calls the ListitemRenderer again for every visible row. This results in a laggy interface for the user.
Is it possible to get ZK to cache the contents of the Listgroups and Listitems on the client such that opening/closing groups will not talk to the server and doesn't render every row again? With this system, the contents of the rows will not change until the user performs another search, or if they drag/drop items.
Edit:
I ended up just building the Listgroups and Listitems myself and adding them with appendChild. No need for a model or renderer, so everything is done on the client meaning it's very snappy. It'd still be nice to know how it could be done with a model/renderer though.
I suggest you can use renderall() method.
e,g
myListbox.getItemRenderer().renderAll()
IMO, if your model contains a lot of data, this action will maybe slower than default action.
Related
So the issue is that I'm getting a runtime error about checkboxes generated inside a file tree needing to be inside a form element. Thing is, it is inside a form element but the form element is wrapped around the tree like so:
<t:Form t:id="form>
<t:Tree t:id="tree" model="model" node="node">
<p:label>
${node.label}
<t:Checkbox value="checkboxNode.selected" />
</p:label>
</t:Tree>
</t:Form>
The root level of nodes generate the checkboxes without issue. However, when I select the plus to expand the tree branch it throws the error for the branch checkboxes. This goes away if I refresh the page and it remembers which branches are expanded. If I go to expand more, then it throws the error again. The same thing happens if I minimize a branch and then expand it again.
I suspect this has to do with how expanding the tree generates its fields using an AJAX call and it not being able to detect the form wrapped on the outside. Two possible work around I've thought of are:
Default the nodes as expanded and disable the minimizing functionality. I lose out on one of the interaction and organization advantages of a file tree doing this though.
Put a form inside the label. This creates a lot of unnecessary extra forms though and I'm not quite sure how to consolidate this into the end goal of creating a list of groups to send emails out to based on the selected labels.
Anyone here have any insight about a better work around for this issue or maybe a way to tell the generated checkboxes to recognize the outer form without needing to reload the page?
Ended up using a different route. The issue I ran into with the checkboxes that was a deal breaker was I couldn't think of a way to tell the booleans on the server side to update based on the client side's checkboxes.
The reason for that was that the booleans were generated based on need instead of being a fixed set on the Java side of the page. Tried a work around by linking unique IDs to the booleans on the server side, but even then I could not determine a way to associate those IDs to the checkboxes on the client side.
So instead I went with eventlinks, which can take a context. I just passed in the generated tree node IDs as a context, which could search for the node in the eventlink and be added to a "selected" list on the server.
As JavaDoc for the Tree component states:
Tree is not a form control component...
Have a look at the source code of AjaxFormLoop and the way it handles AJAX form updates, I believe you need to build a custom component for your needs.
If I understand correctly :
an Activity is a User action on widgets
This activity moves the application state in another Place
The url moves along, thanks to anchors (thought modern browsers have an api)
When we share the url, it define a Place, and it's enough to rebuild the State
(As I'm also a javascript guy, this looks much like Backbone's router and other modern JSFrameworks)
But to rebuild the State, we need to fetch some data to the Server. Is there anything in the P&A api to do this ? With RPC, this role is clearly done by GreetingServiceImpl that extends the RemoteServlet. With Backbone, we have the Sync object.
But I never see such code such when I look at A&P tutorials. Where is the Server ? Do we need RPC there ? Does it mix with RequestFactory ?
First, a small note about terminology:
A Place represents where you are in the app. When you look at that screen, it's generally composed of different "blocks", each dedicated to a specific activity, e.g.: a header (let's say with search box and logout link), a navigation menu, the "master" in a master-details view, the "details" in a master-details view. All these can be activities (though not necessarily, things that are never swapped to anything else won't gain anything being activities).
Because activities are by definition displayed on screen, you can interact with them, possibly triggering a move to another place (PlaceController#goTo).
The place is optionally synchronized with the URL (both ways) and generate browser history items; by default using the hash, but you can swap the implementation to use HTML5.
(places are similar to Backbone's router except they're type-checked, activities are a light layer on top with no equivalent in Backbone AFAICT)
Now to answer your question:
GWT is a toolkit, not a framework. That means most building blocks don't force you into using any other building block (places can work without activities, editors can work without widgets, etc.)
Activities start asynchronously, which is where you'd generally get the data from wherever it is. In the spirit of a toolkit, you're free to use whatever fits your needs: GWT-RPC, RequestFactory, RequestBuilder, Errai JAX-RS, Errai Bus, XMLHttpRequest, WebSockets, AppEngine Channels, etc. Some people also post events to their event bus to decouple the activity from how they get their data.
MVP describes the Client-architecture.
M_odel:
The business objects handled by you app.
V_iew:
UI elements, showing a representation of your model.
P_resenter:
A class which handles all userinteractions and modification to your model.
Lets assume you have an application which shows and stores Notes.
You have some Places:
a Place is like an good old HTML page in older days. In MVP it can be described a a set of running Presenter. In our simple application there are two places. Every Place does only have one running Presenter
NotesListPlace -> shows all stored notes
NotesEditPlace -> Creates / Edit a Note
The NotesEditPlace:
There is a View and a Presenter.
The View has an TextArea (for the Note) and a save button.
The presenter has a clickHandler for the save-button (there may be more, but as example it should be enough)
The User select a Note from the NoteList
PlaceChange from NoteListPlace -> NoteEditPlace
The Presenter starts and registers the click-handler at the view. If the button is pressed, the presenter reads the input from the textarea and update the Model (A new Notes-onject)
Now comes the server interaction. You can use every (GWT) transportlayer you want.
The success callback fires a PlaceChange event to the NoteListPlace.
All starts again. The presenter starts, a new server interacction to load the MOdel ( A List of Notes). The view is updated by the presenter...
Update 1
There is no need of a server. The presenter may persist the Model to the localStorage of the browser.
Update 2
You can use every transport mechanism you want. RequestFactory, GWT-RPC. I use RequestBuilder and GWT AutoBeans.
We are trying to build a GUI framework using GWT. We are finding it hard to implement the cancel functionality in the framework.
Required feature is this:
We have CRUD screens which have pop-ups, grids and so on. When the user changes anything in the GUI and then clicks on cancel() he should be given a notification message saying that something has changed.
Approach that we have tried:
Currently we are trying to keep a hashmap of key vs value of the entire pojo object and trying to compare it against the model which gets updated as and when user changes something. But this is adding lot of unwanted code in every pojo and not working as expected when user adds data directly from the backend.
Is there any elegant way in achieving this functionality? Kindly note that *we are not using Editor framework of GWT *(https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors) in our application.
Example:
Suppose I have a pojo like this:
public class Person {
List<Address> address;
PhoneNumber phoneData;
// and so on along with getters and setters
}
How will I write a generic clone method for this? And even if I manage to do that somehow that will lead to lot of code in every pojo (our application has hundreds of them) which doesn't seem right.
Please note that, our pojo gets updated as soon as something is changed in GUI to achieve live binding.
So you have "Save" and "Cancel" buttons in your form?
I would recommend you to change the concept. Update your object properties immediately as user edit them (as in GMail, JIRA and many other modern applications) in an OnChange event handler.
Save all updates to the session stack as UpdateAction objects and let the user undo every single property modification calling UpdateAction.undo() method.
The benefits are:
this design is much more user friendly than "Click "Edit" - update - click "Save"" scenario.
You don't need separate view/edit forms/popup dialogs - just a single form for both viewing and editing.
I'm building a page that has a search box that will populate a grid on the same page. There is also a button the user can select to bring up a "window" (JQuery UI "pop-up" in the same page) that lets the user configure said grid.
These are two separate forms but I don't want what was submitted as part of one to undo the other (so when the user submits to change the grid layout the search needs to re-run as well.
I'd rather not store things in session for this since that brings with it its own issues (search results may be large, shouldn't be saved when the page is re-entered later, etc.).
I've considered doing "one large form" (i.e. surrounding all the inputs) for the entire page that is backed by a form backing bean. I would then use which button is clicked to determine the action to take. There will eventually be other buttons on the page as well to add more functionality. This would be similar to how .NET (non-MVC) handles things.
I'm interested in how others may have solved similar challenges. Are there potential issues with my approach that I'm not seeing? Better ways that work with the framework?
What do you mean with:
but I don't want what was submitted as part of one to undo the other
. Are you referring to posting the form and loading the whole page, which in turn will "reset" the other form?
If that is the case I would still keep one page with two forms and make the posts using Ajax (as you may know jQuery makes this a breeze). Upon receiving a response for either call you will need to update the other form accordingly.
Note that you may still have your forms in two separate views if it helps keeping the code clean and then pull their html with Ajax calls into another view. But my point is that at the end I would still keep both in one page since it sounds like they depend on each other so updating one when the other changes may be easier this way,
Let me know if I misunderstood your question.
I'm helping to build a GWT application for a client and rewrote most of the stuff to work better, shorter code, faster, etc. However in all the GUI application I've worked on (not so many really) there comes a flexing point where you just have to put a lot of rules and move logic from the listeners to some common mediator. Then some times this could get an ugly mess so you whatever small think you need to do in the listener.
Let's take an example:
form with 10-20 fields
two exclusive radio control about half of the state of the other fields (enabling, validation, input limits)
three exclusive radio controls control again almost the same fields, but in a different way (affecting calculations, enabling); they are also controlled by the above
4 or so number fields are validated on the fly depending on the previous selections and some real-time data object; they can have upper/lower limits, be enabled/disabled
one drop-down box controls the next 6 or so controls - displaying/hiding them, modifying validators
some checkboxes (shown by the above combo) activate some input fields and also determine their validation algorithm
While everything is up an running, without known bugs, there are a few coding gotchas that really bother me:
code is spread among listeners and some mediator methods.
loading the form with some preset values presents its own challenges: like data objects that might be available or not, data objects that might alter their state and subsequent field behaviour
some fields are having a default value set and this should not be overwritten by automatic filling, but if the data objects are not there (yet) then they will need to be filled eventually when the later become available
form cannot be submitted if any of the fields are not validated
My approach:
identify which fields share a common afair and move code into one place
each radio group shares a single listener implementation between its radios
default form filling is deferred until the live data is available (as much as possible) and as a result it gets called multiple times
each action has a call to a common validator method
the validator runs through all the fields in the form, calls their validators (which highlight all errors) and returns a single boolean
each relevant keypress or mouse action, data change it gets deferred to be called after 250ms from the last call; this means first call just places the validator as a delayed action, subsequent calls reset the timer
Ok, it doesn't make any sense to dwelve into more details but I'm more upset about the fact that there is no clear separation between visual actions (enabling), data actions (setting form field values), field listeners, retrieving form values and live data listeners.
What would be a good approach/pattern (next time maybe) to make sure that MVC get separated and lends itself better to maintenance? I know this is not a typical question but I've read every documentation I could get my hands on and still did not find some helpful answer.
I'd move closer towards MVP than MVC. It's clearly the way Google intends to go, so adopting it will probably mean that you're able to go with the flow rather than fight the current.
How does this affect you? Well, I believe you should accept that a tidier implementation may involve more code: not the 'shorter code' you were hoping for. But, if it's logically structured, efficient code the Google compiler should be able to trim lots out in the compiler optimisation phase.
So, move as much of the logic as you can into the model layer. Test this thoroughly, and verify that the correct level of page reset/tidying happens (all of this can be done with plain JUnit, without any UI). Next, use your Presenter (Activity) to tie the View to the Model: handling the interactions, populating the fields, etc.
you can divide a Huge class in different classes bu dividing the GUI in different JPanels. All the panels are implemented in different classes extending JPanel. Guess that would help you.