In Vaadin 8, given the following Grid definition:
grid = new Grid<>();
grid.getEditor().setEnabled(true);
carBinder = grid.getEditor().getBinder();
with:
grid.getEditor().addSaveListener(event -> {
try {
Binder<Car> binder = event.getSource().getBinder();
grid.getDataProvider().refreshAll();
} catch(Exception e)
ExceptionNotification.show(e);
}
});
The problem I have, I currently cannot access the modified value from the Grid Editor, neither over event.getSource() nor over the binder, defined locally or in class scope.
In the debugger, I see in the Vaadin class com.vaadin.ui.components.grid.EditorImpl a property edited, containing the values, but is private, so not accessible.
The binder.bean value is NULL, in the debug. This would be the value retrieved by: binder.getBean().
So I tried many ways, but currently I could not get the edited value with the save listener, for working with it, and search some help or inspiration for solving the problem.
To get the values use:
binder.writeBean(aCarObject);
According to the documentation it writes the values of the fields into the given object, but throws an exception if any of the fields is invalid.
I ran into the same issue. After investigating, I've been informed it will be fixed in Vaadin 8.0.3, which is about to be released.
https://github.com/vaadin/framework/issues/8658
Related
I've created a lookup with two columns, first one containing and integer which works just fine but the second one has a long name and this is where the problem arises. Users should horizontally scroll in order to check the entire string and even in that case, the column's width is not big enough to display the whole data.
I've found this :
Adjusting column width on form control lookup
But i don't understand exactly where and what to add.
I am not sure but maybe I have to add the fact that this lookup is used on a menu item which points to an SSRS report, in the parameters section.
Update 1:
I got it working with a lookup form called like this :
Args args;
FormRun formRun;
;
args = new Args();
args.name(formstr(LookupOMOperatingUnit));
args.caller(_control);
formRun = classfactory.formRunClass(args);
formRun.init();
_control.performFormLookup(formRun);
and in the init method of this form i added:
public void init()
{
super();
element.selectMode(OMOperatingUnit_OMOperatingUnitNumber);
}
meaning the field i really need.
I am not sure i understand the mechanism completely but it seems it knows how to return this exact field to the DialogField from where it really started.
In order to make it look like a lookup, i have kept the style of the Design as Auto but changed the WindowType to Popup, HideToolBar to Yes and Frame to Border.
Probably the best route is do a custom lookup and change the extended data type of the key field to reflect that. In this way the change is reflected in all places. See form FiscalCalendarYearLookup and EDT FiscalYearName as an example of that.
If you only need to change a single place, the easy option is to override performFormLookup on the calling form. You should also override the DisplayLength property of the extended data type of the long field.
public void performFormLookup(FormRun _form, FormStringControl _formControl)
{
FormGridControl grid = _form.control(_form.controlId('grid'));
grid.autoSizeColumns(false);
super(_form,_formControl);
}
This will not help you unless you have a form, which may not be the case in this report scenario.
Starting in AX 2009 the kernel by default auto-updates the control sizes based on actual record content. This was a cause of much frustration as the sizes was small when there was no records and these sizes were saved! Also the performance of the auto-update was initially bad in some situations. As an afterthought the grid control autoSizeColumns method was provided but it was unfortunately never exposed as a property.
you can extends the sysTableLookup class and override the buildFromGridDesign method to set the grid control width.
protected void buildFormGridDesign(FormBuildGridControl _formBuildGridControl)
{
if (gridWidth > 0)
{
_formBuildGridControl.allowEdit(true);
_formBuildGridControl.showRowLabels(false);
_formBuildGridControl.widthMode(2);
_formBuildGridControl.width(gridWidth);
}
else
{
super(_formBuildGridControl);
}
}
I need to add an additional field to InventJournalTrans, that after posting will show up in the InventTrans table. The field is a reference column to a record in another table. What method(s) do I need to modify to make this behavior happen?
Currently, I have already added the fields to both tables and modified the Form to allow the user to enter and save the new field. I just can't seem to find the bottom of the rabbit hole on where the actual posting to InventTrans is occurring.
Ideally, it should just be a:
inventTrans.ReasonRefRecId = inventJournalTrans.ReasonRefRecId;
assignment statement before the
inventTrans.insert();
call. Anybody have a clue on where this is at?
The link above does contain the solution -- I have included the code from that page in case that page disappears or no longer becomes available. Thanks to gl00mie for answering on that site and providing this answer.
You should create a new InventMovement method like this:
public MyNewFieldType myNewField()
{
return MyNewFieldType::DefaultValue; // suppose your new field is an enum
}
Then modify \Classes\InventMovement\initInventTransFromBuffer
void initInventTransFromBuffer(InventTrans _inventTrans, InventMovement _movement_orig)
{
// ... append this line to the end of whatever else is already in this method
_inventTrans.MyNewField = this.myNewField();
}
And finally overload the new method in the InventMov_Journal class:
public MyNewFieldType myNewField()
{
return inventJournalTrans.MyNewField;
}
I am working on an indent and outdent for the advanced datagrid. I have a set of functions which work when operating on the underlying data fine, but which throw "Error: Bookmark no longer valid" when operating on the selected items of the datagrid.
When I run this code it runs fine:
indentLeaf(l5)
outdentLeaf(l4)
But this code fails:
adg.selectedItem = l5
indentLeaf(adg.selectedItem as Leaf)
adg.selectedItem = l4
outdentLeaf(adg.selectedItem as Leaf)
The code does not fail in all instances, only for some configurations of the data grid data tree.
The code needs to be run in the debugger version of the flash player if you want to see the error thrown. I have cut and pasted the error I get into the text area for reference as well as below.
The code in the toy app seems to recover ok when the exception is thrown, but in my larger app it leads to hard crashes.
Example code can be found here with view source turned on: http://www.crcarlson.com/adg/ADGArrayCollectionUpdate.swf
To create the error, reset the tree and then click "indent/outdent2"
I would appreciate any suggestions on how to get around this.
The full stack trace looks like this:
Error: Bookmark no longer valid.
at ListCollectionViewCursor/seek()[E:\dev\4.x\frameworks\projects\framework\src\mx\collections\ListCollectionView.as:2417]
at mx.collections::HierarchicalCollectionViewCursor/get current()[E:\dev\4.x\frameworks\projects\datavisualization\src\mx\collections\HierarchicalCollectionViewCursor.as:220]
at mx.collections::HierarchicalCollectionViewCursor/collectionChangeHandler()[E:\dev\4.x\frameworks\projects\datavisualization\src\mx\collections\HierarchicalCollectionViewCursor.as:1143]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.collections::HierarchicalCollectionView/nestedCollectionChangeHandler()[E:\dev\4.x\frameworks\projects\datavisualization\src\mx\collections\HierarchicalCollectionView.as:1595]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.collections::ListCollectionView/dispatchEvent()[E:\dev\4.x\frameworks\projects\framework\src\mx\collections\ListCollectionView.as:1024]
at mx.collections::ListCollectionView/handlePropertyChangeEvents()[E:\dev\4.x\frameworks\projects\framework\src\mx\collections\ListCollectionView.as:1433]
at mx.collections::ListCollectionView/listChangeHandler()[E:\dev\4.x\frameworks\projects\framework\src\mx\collections\ListCollectionView.as:1300]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.collections::ArrayList/internalDispatchEvent()[E:\dev\4.x\frameworks\projects\framework\src\mx\collections\ArrayList.as:673]
at mx.collections::ArrayList/itemUpdateHandler()[E:\dev\4.x\frameworks\projects\framework\src\mx\collections\ArrayList.as:704]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at Leaf/dispatchChildrenChanged()[C:\adobeFlexTraining\_workspace\ADGArrayCollectionUpdate\src\Leaf.as:119]
at Leaf/addChildAt()[C:\adobeFlexTraining\_workspace\ADGArrayCollectionUpdate\src\Leaf.as:63]
at Leaf/move()[C:\adobeFlexTraining\_workspace\ADGArrayCollectionUpdate\src\Leaf.as:96]
at ADGArrayCollectionUpdate/outdentLeaf()[C:\adobeFlexTraining\_workspace\ADGArrayCollectionUpdate\src\ADGArrayCollectionUpdate.mxml:86]
at ADGArrayCollectionUpdate/IO2_clickHandler()[C:\adobeFlexTraining\_workspace\ADGArrayCollectionUpdate\src\ADGArrayCollectionUpdate.mxml:113]
at ADGArrayCollectionUpdate/__IO2_click()[C:\adobeFlexTraining\_workspace\ADGArrayCollectionUpdate\src\ADGArrayCollectionUpdate.mxml:183]
I just found a workaround for this bug (I am using SDK 3.5 but I guess a 4.1 fix would be very much the same). The problem lies within the "current()" getter of the HierarchicalCollectionViewCursor class.
It doesn't catch the CursorError that's caused by an invalid bookmark.
Step 1 is to create a better cursor class:
public class HierarchicalCollectionViewCursor2 extends HierarchicalCollectionViewCursor
{
public function HierarchicalCollectionViewCursor2(collection:HierarchicalCollectionView, model:ICollectionView, hierarchicalData:IHierarchicalData)
{
super(collection, model, hierarchicalData);
}
override public function get current() : Object
{
// original HierarchicalCollectionViewCursor class fails to catch the "bookmark no
// longer valid" Error, which is thrown as a CollectionViewError instance in ListCollectionView,
// but transformed to a CursorError within the same class
try {
var result:Object = super.current;
}
catch (e:CursorError) {
result = null;
}
// done
return result;
}
}
Step 2 is to create a HierarchicalCollectionView class, which returns that new cursor:
use namespace mx_internal;
public class HierarchicalCollectionView2 extends HierarchicalCollectionView
{
public function HierarchicalCollectionView2(hierarchicalData:IHierarchicalData=null, argOpenNodes:Object=null)
{
super(hierarchicalData, argOpenNodes);
}
override public function createCursor() : IViewCursor
{
return new HierarchicalCollectionViewCursor2(this, treeData, this.source);
}
}
Step 3 is to actually use that new HierarchicalCollectionView2 class as your data-provider.
var itemsAC:ArrayCollection = new ArrayCollection();
// add items etc
this.adgDataProvider = new HierarchicalCollectionView2(new HierarchicalData(itemsAC));
Now you would think that all is well BUT the drama wouldn't be complete without another annoying Flex-SDK bug. In this case its:
https://bugs.adobe.com/jira/browse/FLEXDMV-1846
So, Step 4 is to subclass the AdvancedDataGrid component as described in the bug issue.
That's it -- works for me!
This Exeption may hapen in Flex AdvancedDatagrid with HierarchicalData.
When items are added to Dataprovider it notifies the datagrid . the datagrid receives colection change events each time items are added to it.then some Datagrid internal can be messed up .
You could disable the automatic ArayCollecion refresh :
dataprovider.disableAutoUpdate();
and when you datagrid is ready to use refresh datagrid rendering :
if (advancedDataGrid) {
advancedDataGrid.invalidateList();
advancedDataGrid.invalidateDisplayList();
advancedDataGrid.expandAll();
}
I hope this will help.
Sami was right about the internals (of HierarchicalCollectionViewCursor) getting messed up. This was one of the most long-standing bugs in the Flex framework. It was recently documented - and fixed - at FLEX-34119 and all its linked tickets. It should be available in Flex SDK 4.14, which means that no workaround will be needed from that point onward.
THIS QUESTION IS NOT ABOUT HOW TO SET DEFAULT VALUE OF A WIDGET
Hello Symfonians!
I had a fundamental doubt about forms, Im putting 2 scenarios below.
I have a customModelForm that extends a modelForm.
1> If I do not specify a default value for a form field
new: field is empty
edit: field shows the value in the object
2> If I specify a default value for a field,
new: field shows default value
edit: field shows default value
I am trying to avoid the EDIT mode behaviour in scenario 2.
The default value should only be displayed when the value in the object is not set.
I am calling parent::configure after setting the default value. Do we have any control on the 'bind' event?
Thanks
This shouldn't be happening, at least in Doctrine. The part of the code where this is happening is in updateDefaultsFromObject in sfFormDoctrine. The relevant lines are:
if ($this->isNew())
{
$defaults = $defaults + $this->getObject()->toArray(false);
}
else
{
$defaults = $this->getObject()->toArray(false) + $defaults;
}
updateDefaultsFromObject does net get called until the entire configure chain is done, so something else must be going on here.
Are you using Doctrine? Are you using the most current version of Symfony (there was a bug here a while ago)? Are you sure the default is getting set in the configure method of your form?
The isNew check richsage is recommending should be avoided. There is a larger issue here as the proper behavior is for default value to get overwritten by an existing object's values.
First of all, call parent::configure() first in your configure() method. That way you don't run the risk of your configuration being overwritten by the parent configuration.
You can set defaults based on the model's status by doing something like the following in your configure() method:
if ($this->getObject()->isNew())
{
// do something here but only if the object is new
}
else
{
// the object is being edited
}
I'm updating one object, and trying to update any child objects along with it.
Basically I'm handling the OnUpdating event of a LinqDataSource.
In the DataContext class I have the ObjectUpdate function (where right now I've just got a breakpoint so I can see the values...)
In the LinqDataSource.OnUpdating event e.NewObject.Child is null, which makes no sense whatsoever. I set that to a new value, but by the time I get to DataContext.ObjectUpdate NewObject.Child has been overwritten with the OLD value...
So somewhere between LinqDataSource.Updating and DataContext.UpdateObject it's populating the object with the old values... but I need the new ones.
Is there a way to fix that, or am I going to have a nervous breakdown?
I think I figured out the problem. After running LinqDataSource through .NET Reflector I noticed that:
1) It's the LinkDataSourceUpdateEventArguments.OriginalObject which is actually attached to the data context
2) values are copied from the NewObject into OriginalObject after OriginalObject is attached to the data context
What I don't understand is why the association properties are not copied. Maybe for the same reasons you can't serialize them?
The workaround is/was to handle the Updating event myself and do the actual submit instead of letting LinqDataSource handle that part.
void FormDataSource_Updating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newObj = e.NewObject;
var table = FormContext.GetTable(e.NewObject.GetType());
if (BuildingObject != null)
BuildingObject(sender, new HeirarchicalBuildObjectEventArgs(newObj));
table.Attach(newObj, e.OriginalObject);
FormContext.SubmitChanges();
e.Cancel = true;
}