in my current project i need to realize questionnaire (survey) constructor functionality (kind of google forms).
In my case there is list of questionnaires, every questionnaire has list of question groups, every question group has list of questions and every question can have some number of answers. It should be possible to add/edit/delete such composite object inline.
To present such nested (kind of tree) data structure I thought of using CellTable, containing CompositeCells but I have come to necessity of doing second and third level composition (e.g. every CompositeCell will contain another CompositeCell etc.)
So finally it turned out to be a bit tricky to populate/update such a table using CellTable and ListDataProvider.
With one nesting (Questionnaire->Criterias) it was simple but not with second and third level composition Questionnaire->Criterias->Questions->Answers.
I thought maybe you have some ready tips regarding presenting such data structure? What is better to use FlexTable or CellTable?
Thanks in advance
If you want to (or have to) use Widgets go with FlexTable, otherwise go with CellTable.
CellTable will have better performance, and you get a lot out of the box.
Widgets in a FlexTable can offer a better (richer) user experience in some cases (DND, etc).
Related
My apologies if this has been asked before. I'm looking for a way to group fields in a flexible way. Much like a repeatable field, but each new row would have the option of being a different pre-defined group of fields.
This is critical with any site I build as it allows the content creators flexibility to re-use components on different "pages" in different orders.
I've been pouring over all the field types and the pagemanager add on trying to figure out a way that I could come up with this type of functionality.
Perhaps I could create a "template" field in the repeatable field that hides/shows certain fields in the group, but the number of fields would stack up and that would have to have javascript to hide/show fields and handle validation. Seems a bit hacky.
Am I missing a solution? Thank you for your time.
I have a case where my DataGrid might contain thousands of rows of data. My page size is only 50. So I want to get only so much data onto the client from server and load rows of data as and when required. Is there a default support from GWT to do that?
I tried using PageSizePager but then realized that the data is already sent to the client and that defeats what am trying to achieve.
Thanks.
Indeed. The aim (among others) of DataGrid, as well as of any other cell widget, is to display large data sets as fast as possible by using pagination and cells.
I suggest you to start with the official docs about CellTable (same applies to DataGrid), and pagination/data retrieval.
You'll probably need an AsyncDataProvider to asynchronously fetch data and an AbstractPager (say, SimplePager) to force retrieval of more data.
You can also decide to extend the current range of rows (say, infinite scroll), instead having multiple pages (by using KeyboardPagingPolicy.INCREASE_RANGE).
In general, the question is too general and can be hardly answered in few lines (or without specify more). The bits are all in the links above, and don't forget to have a look at the cell widgets samples in the showcase, as they cover almost everything you will need.
Hope to get you started.
I'm currently writing automated tests for a GWT application using Selenium and Java. For page elements that are Widgets, this is relatively straightforward, given that unique IDs can be set using the ensureDebugIds() method.
However, some types on the pages I work with are not widgets, but other types, possibly container types (such as Cells or grid rows that are essential HTML tables). Is there a similar method to ensureDebugIds() for this? Or is there a way to create custom IDs for these elements that acts in a similar way compatible with ensureDebugId()?
You would need to closely collaborate with you dev team to set Id's on any element which GWT does not handle in its ensureDebugId. Its straightforward to id as all UIObjects have setId api. If any HTML code is being is injected then ids need to be determined by a simple convention and set up for Selenese test case writing to be easier.
What are some possible designs to deal with frequently changing data forms?
I have a basic CRUD web application where the main data entry form changes yearly. So each record should be tied to a specific version of the form. This requirement is kind of new, so the existing application was not built with this in mind.
I'm looking for different ways of handling this, hoping to avoid future technical debt. Here are some options I've come up with:
Create a new object, UI and set of tables for each version. This is obviously the most naive approach.
Keep adding all the fields to the same object and DB tables, but show/hide them based on the form version. This will become a mess after a few changes.
Build form definitions, then dynamically build the UI and store the data as some dictionary like format (e.g. JSON/XML or maybe an document oriented database) I think this is going to be too complex for the scope of this app, especially for the UI.
What other possibilities are there? Does anyone have experience doing this? I'm looking for some design patterns to help deal with the complexity.
First, I will speak to your solutions above and then I will give my answer.
Creating a new table for each
version is going to require new
programming every year since you will
not be able to dynamically join to
the new table and include the new
columns easily. That seems pretty obvious and really makes this a bad choice.
The issues you mentioned with adding
the columns to the same form are
correct. Also, whatever database you
are using has a max on how many
columns it can handle and how many
bytes it can have in a row. That could become another concern.
The third option I think is the
closest to what you want. I would
not store the new column data in a
JSON/XML unless it is for duplication
to increase speed. I think this is
your best option
The only option you didn't mention
was storing all of the data in 1
database field and using XML to
parse. This option would make it
tough to query and write reports
against.
If I had to do this:
The first table would have the
columns ID (seeded), Name,
InputType, CreateDate,
ExpirationDate, and CssClass. I
would call it tbInputs.
The second table would have the have
5 columns, ID, Input_ID (with FK to
tbInputs.ID), Entry_ID (with FK to
the main/original table) value, and
CreateDate. The FK to the
main/original table would allow you
to find what items were attached to
what form entry. I would call this
table tbInputValues.
If you don't
plan on having that base table then
I would use a simply table that tracks the creation date, creator ID,
and the form_id.
Once you have those you will just need to create a dynamic form that pulls back all of the inputs that are currently active and display them. I would put all of the dynamic controls inside of some kind of container like a <div> since it will allow you to loop through them without knowing the name of every element. Then insert into tbInputValues the ID of the input and its value.
Create a form to add or remove an
input. This would mean you would
not have much if any maintenance
work to do each year.
I think this solution may not seem like the most eloquent but if executed correctly I do think it is your most flexible solution that requires the least amount of technical debt.
I think the third approach (XML) is the most flexible. A simple XML structure is generated very fast and can be easily versioned and validated against an XSD.
You'd have a table holding the XML in one column and the year/version this xml applies to.
Generating UI code based on the schema is basically a bad idea. If you do not require extensive validation, you can opt for a simple editable table.
If you need a custom form every year, I'd look at it as kind of a job guarantee :-) It's important to make the versioning mechanism and extension transparent and explicit though.
For this particular app, we decided to deal with the problem as if there was one form that continuously grows. Due to the nature of the form this seemed more natural than more explicit separation. We will have a mapping of year->field for parts of the application that do need to know which data is for which year.
For the UI, we will be creating a new page for each year's form. Dynamic form creation is far too complex in this situation.
I have actually two questions but they are kind of related so here they go as one...
How to ensure garbage collection of tree nodes that are not currently displayed using TreeViewer(SWT.VIRTUAL) and ILazeTreeContentProvider?
If a node has 5000 children, once they are displayed by the viewer they are never let go,
hence Out of Memory Error if your tree has great number of nodes and leafs and not big enough heap size.
Is there some kind of a best practice how to avoid memory leakages, caused by never closed view holding a treeviewer with great amounts of data (hundreds of thousands objects or even millions)?
Perhaps maybe there is some callback interface which allow greater flexibility with viewer/content provider elements?
Is it possible to combine deffered (DeferredTreeContentManager) AND lazy (ILazyTreeContentProvider) loading for a single TreeViewer(SWT.VIRTUAL)?
As much as I understand by looking at examples and APIs, it is only possible to use either one at a given time but not both in conjunction, e.g. ,
fetch ONLY the visible children for a given node AND fetch them in a separate thread using Job API. What bothers me is that Deferred approach
loads ALL children. Although in a different thread, you It still load all elements
even though only a minimal subset are displayed at once.
I can provide code examples to my questions if required...
I am currently struggling with those myself so If I manage to come up with something in the meantime I will gladly share it here.
Thanks!
Regards,
Svilen
I find the Eclipse framework sometimes schizophrenic. I suspect that the DeferredTreeContentManager as it relates to the ILazyTreeContentProvider is one of these cases.
In another example, at EclipseCon this past year they recommended that you use adapter factories (IAdapterFactory) to adapt your models to the binding context needed at the time. For example, if you want your model to show up in a tree, do it this way.
treeViewer = new TreeViewer(parent, SWT.BORDER);
IAdapterFactory adapterFactory = new AdapterFactory();
Platform.getAdapterManager().registerAdapters(adapterFactory, SomePojo.class);
treeViewer.setLabelProvider(new WorkbenchLabelProvider());
treeViewer.setContentProvider(new BaseWorkbenchContentProvider());
Register your adapter and the BaseWorkbenchContentProvider will find the adaption in the factory. Wonderful. Sounds like a plan.
"Oh by-the-way, when you have large datasets, please do it this way", they say:
TableViewertableViewer = new TableViewer(parent, SWT.VIRTUAL);
// skipping the noise
tableViewer.setItemCount(100000);
tableViewer.setContentProvider(new LazyContentProvider());
tableViewer.setLabelProvider(new TableLabelProvider());
tableViewer.setUseHashlookup(true);
tableViewer.setInput(null);
It turns out that first and second examples are not only incompatible, but they're mutually exclusive. These two approaches where probably implemented by different teams that didn't have a common plan or maybe the API is in the middle of a transition to a common framework. Nevertheless you're on your own.