I am stuck in a problem working on Flex datagrid, in an AIR application.
How can I access a specific row in datagrid in Flex. Please note that i am not talking about the selectedItem or any particular record of dataProvider of datagrid.
What exactly I want to do is I am showing some files data (name, description etc.) on a datagrid, and the data of these files comes from an array which is the dataProvider of the datagrid.
Now when these files are being uploaded one by one to the server (using a webservice), I want to show a ProgressBar on, say, "Progress" column in the datagrid. How can I access this column for a particular row in datagrid i.e. current file being uploaded.
Please refer to image to better understand my query.
Please guide me.
Thanks
Preface, I use the Swiz Framework, so you will just have to adapt what I am saying to Native Flex or another framewok.
I would attack this by having an event that would be fired when you started the upload. This event would have a property that signified which filename is being uploaded.
var e:DataGridEvent = new DataGridEvent(DataGridEvent.START_FILE_UPLOAD);
e.fileName = uploadFileName;
dispatcher.dispatch(e);
Each row in the DataGrid is a new instance of an itemRenderer(there are no other ways to make it have a progressbar or anything fancy). So after setting the itemRenderer to your MXML component, just have it monitor the event being dispatched.
[EventHandler(event="DataGridEvent.START_FILE_UPLOAD", properties="fileName")]
public function startFileUpload(fileName:String):void
{
if(fileName == dataGride.fileName)
........//Show progress bar or whatever
In this manor, all of the rows will respond to the given event, and show the progress bar ONLY if it has the same filename as the file being uploaded. If filename isn't unique(I think it would be), you will have to have some sort of unique ID.
The same general process will be done with the status progress. Just fire a different event being FILE_UPLOAD_STATUS_UPDATE with the percentage and filename. Then handle the event properly.
The simplest way to meet your needs is to create custom item renderer with progress bar for progress column and add 3 additional fields to the file data (an element of your data provider):
public var inProgress:Boolean
public var bytesLoaded:int
public var bytesTotal:int
The progress bar in the item renderer can use data binding for switching visibility depending on inProgress flag value. And you can update progress using the same data binding with bytesLoaded and bytesTotal values.
You can read more about custom item renderers in official documentation.
Related
Actually in my Flex Application i'm getting values from Database and Stored into a ArrayCollection...
[Bindable]public var data : ArrayCollection;
....
....
Actually ArrayCollection data contain values like...java,flex,dotnet,php.....
So now i'm adding this ArrayCollection into textbox for getting Dynamic value just like Auto-Suggestion
but it is giving all data once but i want when we type 'J' dynamically 'J' related words will be display....
Please help me....
The type of component you're looking for is called AutoComplete. There are quite a few implementations out there, but my favorite is the Flextras AutoCompleteComboBox, because I built it. It is available free for production use; but you'll have to register to download the SWC.
I am using a command pattern, so any changes to object state need to happen within a command execution. A normal itemeditor in a DataGrid would just make its changes on the underlying bound object, but I need to intercept that change and make it use a command.
I'm pretty new to flex, so I'm looking for ideas of how to implement this. A basic example is that I have an object with a "date" field. In the datagrid I am using a flex "DateField" component as the itemeditor. When I select a new date, I don't want it to update the datasource, I want it to call a different method where I can access the newly selected value and pass it to a command to execute. Any tips would be greatly appreciated. Thanks in advance.
Use the itemEditBegin and/or itemEditEnd events on the DataGrid and build your command in the handler. This page has a few examples of capturing the edit operation with those events.
In my opinion, you're over-engineering this to hell, to the point that it becomes unusable. Why would you need a command to just change data on the fly? I've been doing Flex for 3 years and I yet to see it done this way. The only time commands are used is for receiving information from the server.
Either way, if you really want to implement it (against my recommendation), you would probably want to do event bubbling with a controller listening higher up the display list for the event, then from there trigger a command. From within the item renderer:
this.dispatchEvent(new Event('someEvent', true));
And then higher up the display list:
dataGrid.addEventListener('someEvent', someEventHandler);
And within the handler you can run the command.
i've searched for several hours, and didn't find an answer for my problem.
i'm trying to place comboboxes in a datagrid filled with DYNAMIC data. (the number and the content of these comboboxes always change. i don't know in advance how many columns there are, where i need to use comboboxes. so every single combobox gets a unique dataprovider, which comes from an external source, WHEN the program runs.)
-i found MANY threads discussing this problem, but solving via crappy mxml files, filling the comboboxes inside the sourcecode by hand. i want to point out, that isn't good for me.
-i found a better solution, in which they used some sort of custom itemrenderer to get the data from the internet. (kind of a country chooser thing) but sadly that wasn't good enough, because the number and name of the countries in the world are static more or less, they don't change. so their renderer class didn't depend on any parameters from the main algorithm.
but in my program i calculate the data in my own actionscript objects, then fill an arraylist with that. so at the beginning i load the desired data from the net, and when i get the response of the urlrequest, AFTER that i start to populate the datagrid/combobox.
i can fill any datagrid or combobox without trouble, but to put that combobox inside a datagrid cell seems to be impossible.
could anyone please help? it drives me crazy. i managed to do this in several languages before, c#, java, even php+html, but in flex it looks way too complicated then it should be.
EDIT:
i'm aware, that this amount of network activity could mean some load on the server. i didn't design the philosophy behind it, i just need to wrote a client which meets the expectations. my program looks something like this:
(i'm willing to rewrite any part of it, just to make those nasty comboboxes work)
=========
main.mxml file
this is the main program, i handle some login related stuff here, and set basic design properties for the datagrids. (for example: maxwidth, maxheight, layout constraints etc.)
nothing interesting, except the command when i instantiate the actionscript class, which i wrote to fill the datagrid.
"..<fx:Script>
<![CDATA[
private var myGrid1:MyGridType;
..
somefunction {
myGrid1 = new MyGridType(theDatagridDefinedBefore, "argumentNeededToFillDataGridsWithUniqueData");
}
]]>
</fx:Script>.."
=========
MyGridType.as file
in the constructor i call a urlrequest with the help of the second argument, then add an eventlistener to it. when the data arrives, the eventlistener fires the filler function: i read the results into an arraycollection, then make it the dataprovider for the the datagrid in the first argument.
so far so good.
here comes the trouble with the comboboxes. for a specific number columns, i instantiate my combobox class. let's call that class "MyComboBoxType".
"..
blablabla = new MyComboBoxType(theDatagridDefinedBefore, param1, param2, param3);"
=========
MyComboBoxType.as file
i do nearly exactly the same, what i did in the MyGridType class. call for help from the net with param1-2-3. when i receive the data, fill an arraycollection. maybe set that arraycollection to be the dataprovider for a combobox. AAAAAAAND now i want that arraycollection or combobox to be on the datagrid "theDatagridDefinedBefore".
I know it's not exactly what you're trying to accomplish, but I had a somewhat similar issue in the past. Take a look at How to get the value of a ComboBox within a DataGrid to see if it helps.
If it were me, I would populate the entire ArrayCollection set before binding them to the datagrid if at all possible.
You should build up your custom [Bindable] data structure - say MyGridData class - for the rows in the grid (if you haven't done it yet);
the dataProvider of your grid should
be an Array / ArrayCollection /..
of MyGridData objects.
this step clearly works already, but
for the integrity: override the
getItemEditor function, or specify
it explicitly using mxml, to return
the combobox when needed.
as for the dataProvider of the
combobox, you should specify the
data.comboArray from inside the
renderer class, where data is the
MyGridData instance used by the row
you are processing. (overriding the
set data(value: Object):void
function, you can pre-process it.)
this way, you are working with the
reference of your original instances,
and by the binding you can detect /
show any changes to them directly.
working with flex 4 and implementing filtering using ITreeDataDescriptor.
Filtering worked as expected like the following code snippet
however, i am trying to create a on-demand type of filter where user would type in the search clause in a TextInput, and as the user types, the tree nodes would be filtered on the fly.
my implementation now is have user click on the search button and then reapply the dataDescriptor then reload the data. A big problem is that the whole tree collapses after setting the dataProvider again.
any suggestion on how the on-demand filter can be achieved?
var dataFilter:ServicePricingFilter = new MyFilter();
dataFilter.searchString = this.txtSearchKeyword.text;
this.treeService.dataDescriptor = new MyDataDescriptor(dataFilter);
this.treeService.dataProvider = getTreeData();
I think you shouldn't set the dataprovider every time but use insted the filterFunction property available for ListCollectionView classes (ArrayCollection, XMLListCollection,...)
looked at the post Florian mentioned.
on-demand filtering is done by using ITreeDataDescriptor and a filterFunction.
on keyup event of the search TextInput, call invalidateList() function on the tree.
see the source code provided for the following post
http://www.davidarno.org/2009/04/01/how-to-filter-all-nodes-of-a-flex-tree-component/
I have a DataGrid.
It's ItemsSource is bound to the ModelView's CompositeCollection through the ViewModel.
The CompositeCollection consists of 2 ObservableCollections.
The display on the grid is fine. I am able to see the collection.
However, when I try to edit one of the rows, I get a crash (NotSupportedException) of:
"'EditItem' is not allowed for this view"
How do I make the rows editable? I need to be able to edit the ModelViews representing each row in the Grid.
Here is the CompositeCollection Property code that I use to bind to the itemssource:
this isn't the exact code since I am not allowed to post the exact code but it is the same logic on how I make the collection
public CompositeCollection ModelViewsCollection
{
get
{
CollectionContainer modelViewContainer;
CompositeCollection modelViewCollection = new CompositeCollection();
modelViewContainer= new CollectionContainer();
modelViewContainer.Collection= this.ModelViewCollection;
modelViewCollection .Add(modelViewContainer);
modelViewContainer= new CollectionContainer();
modelViewContainer.Collection= this.ModelViewCollection2;
modelViewCollection .Add(modelViewContainer);
return modelViewCollection;
}
}
CompositeCollection does not implement IEditableCollectionView which is used by the datagrid to edit.
I have had the same issues, and ended up doing my own fake composite collection on the view model, similiar to what you have, if all you are putting in your collection is two observable collections, its not to hard to track the changes listening to collection changed on both of them. and make your viewmodels collection consist of both of them
You could even do the dirty hack that i did, of rebuilding the ObservableCollection that the grid binds to every time one of the collections change (not elegant i know, but ill go back and optimise when i get time.. i.e. never) With a linq query this stuff is really easy.
Otherwise maybe you could derive from CompositeCollection and try and add the IEditableCollectionView, if you get that working be sure to let me know.
here is the same question on the datagrid forum