SmartGWT - Update ListGridRecord dynamically - java

I am using SmartGWT and I have a ListGrid populated with an array of ListGridRecords using the setData() call. I am trying to update a progress property of a single record (on a timer for testing) and have it update in the browser. I have tried various combinations of draw(), redraw(), markForRedraw() etc. to no avail.
I also tried overriding the updateRecordComponent() method in my table class, but it only gets called when the records are first created (after createRecordComponent()).
I should note that I do NOT want to accomplish this by binding to a DataSource. I just want to be able to update the attribute on the client-side.
ArrayList<SegmentSortRecord> mRecords;
mRecords.add(new SegmentSortRecord("03312010_M001_S004"));
mRecords.add(new SegmentSortRecord("03312010_M001_S005"));
mRecords.add(new SegmentSortRecord("03312010_M001_S006"));
mRecords.add(new SegmentSortRecord("03312010_M001_S007"));
SegmentSortRecord[] records = new SegmentSortRecord[mRecords.size()];
mRecords.toArray(records);
mSortProgressTable.setData(records);
.
.
.
mTestTimer = new Timer()
{
public void run()
{
mTestPercent += 5;
if (mTestPercent <= 100)
{
mSortProgressTable.getRecord(2).setAttribute(Constants.PROGRESS_COL_NAME, mTestPercent);
//mSortProgressTable.markForRedraw();
//mSortProgressTable.redraw();
}
else
{
mTestPercent = 0;
}
}
};
...
#Override
protected Canvas createRecordComponent(final ListGridRecord aRecord, Integer aColumn)
{
String fieldName = getFieldName(aColumn);
// Want to override the behavior for rendering the "progress" field
if (fieldName.equals(Constants.PROGRESS_COL_NAME))
{
Progressbar bar = new Progressbar();
bar.setBreadth(10);
bar.setLength(100);
// The JavaScript record object contains attributes that we can
// access via 'getAttribute' functions.
bar.setPercentDone(aRecord.getAttributeAsInt(Constants.PROGRESS_COL_NAME));
return bar;
}
Thanks in advance for any help.

I solved the dynamic update with:
grid.getRecord(i).setAttribute(name, value);
grid.refreshRow(i);
resp.
grid.refreshCell(i, j);

ListGrid has an updateData method, where you can pass a record. Have you tried it?

a blunt and not very high-performance way is simply setting your records array again with setData or setRecords
grid.setData(recordArr);
I use that in my app, but only because all records are updated anyway.
BTW: you could set up a clientside datasource
dataSource.setClientOnly(true);
dataSource.setTestData(...);

Related

Getting all return values of LOV programmatically

I'm currently working on a CRUD application and I have defined a LOV like this:
My question is how can I get all these return values in for example a ValueChangeListener defined like this:
public void onValueChanged(ValueChangeEvent ev){
BindingContext bctx = BindingContext.getCurrent();
oracle.binding.BindingContainer bindings = bctx.getCurrentBindingsEntry();
DCIteratorBinding iterBind = (DCIteratorBinding)bindings.get("MpStavkeulazaView5Iterator");
System.out.println("Vrijednost je" + ev.getNewValue());
}
This code only gives me the value of the list attribute, but I want the other values too.
Any other info please tell me.
First of all - using backing bean's value change listener is not ideal for such use case:
Try instead the setter on your Row Impl for the same purpose.
Remember: if you can't test your use case from BC tester, your ADF design is flawed.
Second of all: your LOV can return multiple values:
http://adfbugs.blogspot.co.uk/2009/11/returning-multiple-values-from-lov-in.html
You can bind row attributes and then get values of this bindings or just get this attributes from iterator. If you going to handle it in valueChangeListener you'll have to process updates, before getting this values:
public void onValueChanged(ValueChangeEvent ev){
BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding iterBind = (DCIteratorBinding)bindings.get("MpStavkeulazaView5Iterator");
System.out.println("Vrijednost je" + ev.getNewValue());
ev.processUpdates(FacesContext.getCurrentInstance());
Row row = iterBind.getCurrentRow();
System.out.println("Proizvod: " + row.getAttribute("Proizvod"));
System.out.println("Jmjere: " + row.getAttribute("Jmjere"));
}
However its may be better to use Transient attribute in your ViewObject and do calculations there?

Null error when attempting to add custom row to CellTable in gwt

I have a Cell Table that I am using to output some search results. The cell table uses a list data provider to update info. I want to separate different sections so I am attempting to add a custom row in between different sections that has one cell that spans all of the columns. I am extending AbstractCellTableBuilder to do this, but my issue comes when I use TableRowBuilder and startRow(), calling startRow() returns a null pointer exception, to AbstractCellTableBuilder.java:243, which refers to tbody. So this is leading me to believe that my cell table is not getting passed into AbstractCellTableBuilder properly. My understanding of gwt and java is pretty basic, so I might just not be understanding how exactly this is supposed to work, and the showcase example is pretty complicated for me to understand. If anyone can tell where I'm messing up or has any simpler examples of this that might help me I would appreciate it!
I had found a similar answer and tried to implement it, and that is how I came up with what I have, but it answer wasn't quite detailed enough for me to fully understand how it works. Here is what I referenced:
Building a custom row on demand with GWT CellTableBuilder
EDITED:
Basic format of how I add normal rows to the cell table
searchProvider = new ListDataProvider<SearchColumn>();
cellTable_2 = new CellTable<SearchColumn>();
//Add columns to the cellTable
searchProvider.addDataDisplay(cellTable_2);
//What I call when adding a row to the cellTable using the ListDataProvider
searchProvider.getList().add(new SearchColumn("",label,"","","","","","",""));
Adding the CustomCellTableBuilder to the cell table:
//Passing the CustomCellTableBuilder to the cell table
CustomCellTableBuilder buildRow = new CustomCellTableBuilder();
cellTable_2.setTableBuilder(buildRow);
The CustomCellTableBuilder for adding custom rows:
public class CustomCellTableBuilder extends AbstractCellTableBuilder<SearchColumn>{
public CustomCellTableBuilder() {
super(cellTable_2);
}
#Override
protected void buildRowImpl(SearchColumn rowValue, int absRowIndex){
//building main rows logic
if (labelrow == 1){
System.out.println("Going to build extra row if");
buildExtraRow(absRowIndex, rowValue);
}
else {
System.out.println("Getting into normal buildRow");
buildRow(rowValue,absRowIndex);
}
}
private void buildExtraRow(int absRowIndex, SearchColumn rowValue){
start(true);
TableRowBuilder row = startRow();
TableCellBuilder td = row.startTD().colSpan(getColumns().size());
td.text("Testing this out").endTD();
row.endTR();
}}
I think you should call start(true) before calling startRow() because tbody is initialized to null. Start() call will initialize tbody to HtmlBuilderFactory.get().createTBodyBuilder().
The source doesn't lie.
Just like that:
private void buildExtraRow(int absRowIndex, SearchColumn rowValue) {
start(true); // true makes builder to rebuild all rows
TableRowBuilder row = startRow();
// whatever
}

How to force combobox to render autocomplete options?

This is my zul code:
<combobox id="digitalPublisherCombobox" value="#load(ivm.inventory.digitalPublisherName)"
onOK="#command('setDigitalPublisher', digitalPublisherBox = self)"
onSelect="#command('setDigitalPublisher', digitalPublisherBox = self)"
onChanging="#command('setupQuicksearchByEvent', searchlayout = event, prefix = 'PUB', tags = 'PublisherName, PublisherNameTranslit')"
mold="rounded" hflex="1" buttonVisible="false" autodrop="true">
<comboitem self="#{each=entry}" value="#{entry.key}" label="#{entry.value}"/>
</combobox>
And this is QuickSearch implementations:
#Command
public void setupQuicksearchByEvent(#BindingParam("searchlayout")Event event, #BindingParam("prefix") String prefix, #BindingParam("tags") String tags) throws WrongValueException, SearchException, IOException
{
if(event instanceof InputEvent)
{
InputEvent inputEvent = (InputEvent) event;
String inputText = inputEvent.getValue();
List<String> searchFields = Arrays.asList(tags.split(","));
ListModel model = new ListModelMap(ZKLogic.findDocsStartingWith(prefix, searchFields, "proxy", inputText), true);
ListModel subModel = ListModels.toListSubModel(model, Autocompleter.MAP_VALUE_CONTAINS_COMPARATOR, 10);
Combobox searchBox = (Combobox) event.getTarget();
searchBox.setModel(subModel);
searchBox.setItemRenderer(new ComboitemRenderer()
{
#Override
public void render( Comboitem item, Object data, int pos ) throws Exception
{
String publisherString = data.toString();
UID key = getUidFromPublisherString(publisherString);
int startIndex = publisherString.indexOf('=') + 1;
String publisher = publisherString.substring(startIndex);
item.setLabel(publisher);
item.setValue(key);
}
});
}
}
ZKLogic.findDocsStartingWith return map with UID-key and String-value.
With code above I achieved to get dropdown list when I switch to another window. I need to type something, then select another browser or notepad window - and comboitems will be displayed immediately.
So, my question still need answer, is there are any techniques to reproduce this windows switching in code? Or maybe I should do something with autocomplete, because I've got some ac working with preloaded lists, but this thing should return only 10 records from db, instead of all 70000 entries, every time when user type something in the field.
Edit 20/09/2013: Problem still exist. Rename question a bit, because thing that I need is to call render option by force in code. Is there is any way to do it? Code hasn't changed a lot, but print option in render method said, that method can miss two or more onChange events and suddenly render text for one variant.
Maybe you know another autocomplete options in zk framework where database participating? I'm ready to change implementation, if there is a guide with working implementation of it.
Ok I see two problems, you should solve first.
Setting the Renderer in every call of setupQuicksearchByEvent(...).
that is not logical, cos it is the same every time.
Add to the zul combobox tag something like
itemRenderer="#load(ivm.myRenderer)" ....
If you want just 10 items, do not let the db-request return more then 10.
If you use JPA klick here or for sql here or just google a bit.
After you fixed this two issues, we can exclude these as a reason of the unexpected behavior and fix it, if it is still present.
Edit
Ok, I have two possible ways to fix it.
Call Combobox#invalidate()
This schould force zk to rerender the Combobox, but could
lead to low performance and I would not prefer this.
Use Listbox with the select mold instead of Combobox.
To force the rerender, use Listbox#renderAll()
Try setting the selected item on your combobox or throw its related event
Solution is simple. Really. Nothing is better then brute-force, but I think I tried to avoid it and use it in despair.
#Command
public void setupQuicksearchByEvent(#BindingParam("searchlayout")Event event, #BindingParam("prefix") String prefix, #BindingParam("tags") String tags) throws WrongValueException, SearchException, IOException
{
if(event instanceof InputEvent)
{
InputEvent inputEvent = (InputEvent) event;
String inputText = inputEvent.getValue();
List<String> searchFields = Arrays.asList(tags.split(","));
Map<UID, String> publishers = ZKLogic.findDocsStartingWith(prefix, searchFields, "proxy", inputText);
Combobox searchBox = (Combobox) event.getTarget();
searchBox.getChildren().clear();
for (Map.Entry<UID, String > entry : publishers.entrySet())
{
Comboitem item = new Comboitem();
item.setLabel(entry.getValue());
item.setValue(entry.getKey());
searchBox.appendChild(item);
}
}
}

How can I (un)hide a SWT TableItem?

I am trying to allow my user to search through a table of information, dynamically hiding/showing results that contain the search. I have the hiding part down, and it works well, but I'm having trouble showing the table item again once the search criteria is changed.
Here is my hide code:
searchField.addModifyListener(new ModifyListener() {
#Override
public void modifyText(ModifyEvent arg0) {
modified = true;
for (int i = 0; i < table.getItems().length; i++) {
if (!(table.getItem(i).getText(2)
.contains(searchField.getText()))) {
table.getItem(i).dispose();
}
}
if ("".equals(searchField.getText())) {
modified = false;
//where I would want to un-hide items
}
}
});
Looking at your code, it seems you try to hide the item by calling dispose(). If you dispose a widget, it is gone for good. You cannot get it back.
If you want to unhide it again, will have to create a new item at the position of the previously hidden one with the same content.
Isn't it better to actually operate with some kind of a table model and JFace bindings, rather, then do it like that? And yes, disposing is not hiding. You should probably remove the item from the table.
You have probably to save the data from TableItem into collection before you call dispose. Then when you search again you could check that collection and if matches are found, then insert back into Table by creating new TableItem.

Problems with asynchronous methods

I'm working with Flex 4 invoking webservices from JVM 1.6
I'm trying to make asynchronous calls to java to populate three comboboxes that will display country, states and cities, these three are related (master-slave relationship) but sometimes the calls are not met, or they are not completed, and I think this is because they are asynchronous, how can I be sure that I'm making the call to fill the next combobox when the master combobox (country) is filled?
protected function comboCountry_changeHandler(idCombo:String):void
{
selectedComboCountry= idCombo;
var countryId:String;
if(selectedComboCountry == comboCountry.id){
countryId = String(comboCountry.selectedItem.countryId);
}else if(selectedCombocountry == combocountrySuc.id){
countryId = String(comboCountrySuc.selectedItem.countryId);
}
obtainStatesResult.token = wsfacturas.obtainStates(countryId);
}
protected function obtainStatesResult_resultHandler(event:ResultEvent):void
{
var StateListVo:ArrayCollection = obtainStatesResult.token.result as ArrayCollection;
if(selectedComboCountry == "comboCountrySuc"){
StateListsSuc.removeAll();
CityListsSuc.removeAll();
for (var d:int = 0; d < StateListVo.length; d++){
var estSuc:State = StateListVo[d];
StateListsSuc.addItem(estSuc);
}
comboStateSuc.dataProvider = StateListsSuc;
}
else if(selectedCombocountry == "combocountry"){
StateListsEmp.removeAll();
CityListsEmp.removeAll();
for (var i:int = 0; i < StateListVo.length; i++){
var estEmp:State = StateListVo[i];
StateListsEmp.addItem(estEmp);
}
comboState.dataProvider = StateListsEmp;
} else {
for (var f:int = 0; f < StateListVo.length; f++){
var est:State = StateListVo[f];
StateListsSuc.addItem(est);
StateListsEmp.addItem(est);
}
comboState.dataProvider = StateListsEmp;
comboStateSuc.dataProvider = StateListsSuc;
}
}
Wouldn't it mean that you probably need to load the country and wait for change event on the country combobox to update state and so on? If you do that, you dont have to worry about asynchronicity of your requests? Otherwise, you might be able to use DataProviders and they might provide Event:Complete..
I am not sure though, I definitely am not an expert.. :)
You might want to give slightly more details in your question. But I am just playing with whatever details you have provided.
1_ First asynchronous calls never caused me any problem with dynamic data binding. Sometimes
a SOAP call can take reasonable amount of time, in that case, make sure to show a busy cursor till the web service call returns.
2_Combobox has always had problem with dynamic data binding. You can create a custom combobox that extends a combobox and override the setValue method Or Else you have to iterate over the dataProvider of the combobox and look for a match in the data field and then sets the combo box to that item.
So in summary, the problem mostly have to do with binding of the new data to the rendered combobox not asynchronous calls or any latency.

Categories

Resources