Flex DataGrid: Programmatically Highlighting Rows - apache-flex

This seems like something that should be painfully simple, but I can't even find how to loop through rows in a Flex DataGrid.
Basically what I'm trying to accomplish is something like this pseudo-code:
for each(var row:Row in myDataGrid.Rows)
{
if(row.DataObject.Number == 1)
{
row.Color = Red;
}
}
I'm trying to have a Save button that upon being clicked either processes the save, or highlights the invalid rows and pops up a message telling the user why the rows are invalid. Because of some other complexities, I am not able to validate each row as it is entered. Any help is appreciated! Thanks.

Data grids are intended to be driven by their data rather than manipulated directly. One way to accomplish what you are trying to do is to add some sort of property, say "valid", to the data objects in your provider and add code to the renderer to alter its appearance based on the state of "valid". In that way you could loop through the objects in your data provider and set the "valid" property based on your validation check, which would cause the rows in the data grid to change their appearance automatically.
Hope that helps.

Try something like this:
for each(var o:Object in myDataGrid.dataProvider)
{
if(o.Number == 1) {
myDataGrid.selectedItems.push(o);
}
}
In your mxml you can set the selectionColor of the datagrid to red. See: http://blog.flexexamples.com/2008/02/19/setting-the-selection-color-and-selection-disabled-color-for-a-row-in-the-flex-datagrid-control/
Let me know if this works for you!

I am not sure you can do it on the data grid itself, but if you have an item renderer for each of the items, you can have your highlighting logic there.
basically, you define your datagrid's item renderer class:
<mx:DataGrid itemRenderer="ItemRendererClass"(...) ></mx:DataGrid>
and then you define the class "ItemRendererClass" as implementing IDataRenderer:
implements="mx.core.IDataRenderer"
This is a simplistic explanation, assuming you can figure out how to do this on yourself :)

I achieved this by overriding the set data. I have provided the sample code below.
override public function set data(value:Object):void
{
super.data=value;
if(value!=null && value.hasOwnProperty("state") && value.state == "Final State"){
setStyle("color", 0xb7babc);
}else{
setStyle("color", 0x000000);
}
this.selectable=false;
super.invalidateDisplayList();
}

Related

how to hide a row without deleting item from dataprovidor in DataGrid...AS3,Flex?

How we can hide a row at specific index of DataGrid in AS3 ?
If dataProvider of your DataGrid is ArrayCollection you can specify filterFunction property for it, something like that
dataProvider.filterFunction =
function (item:Object):Boolean{
if (dataProvider.getItemIndex(item)==indexOfRowYouWantToHide){
return false;
}
return true;
};
The item will still be in ArrayCollection but will be made invisible by the filter. Not the most efficient solution but it works. You need to call
dataProvider.refresh();
to apply the filter.
UPDATE: To access raw, unfiltered data of ArrayCollection you should use list property, so if you hid item at index 0 and still want to be able to access it you do that like this:
dataProvider.list.getItemAt(0);
No (easy) way. You can try to subclass DataGrid to add this functionality, but this will be really heavy task.

How can I hide a list component when it contains no items?

I have a List of items which is based on the contents of the "category" that a user selects
When the user changes selection, I change the dataProvider of the list be be the contents of the current category.
Sometimes the list contains items, sometimes it does not
Is there a way of hiding the list when it has no items?
I know that I could do this when setting the dataProvider, but it seems like there should be an event or something else that I could be using.
You could try
visible="{myList.dataProvider.length>0}"
includeInLayout="{myList.dataProvider.length>0}"
where "myList" is the id of your List component.
My first solution to this was to override set dataProvider:
override public function set dataProvider(value:IList):void {
super.dataProvider = value;
this.setVisible(value.length > 0);
}
This did work, however Robusto's solution works also and is preferable IMO.

Number of items in a combobox in Flex

HI,
How do i retreive the total number of items (count) of a combo box in Flex?
random idea for you:
var dp : Object = combobox.dataProvider ;
if(dp is Array)
{
//do something cool
}
else if(dp is ArrayCollection){
//do something equally as cool
}
etc...
I've confirmed that this will work:
(comboBox.dataProvider as ArrayCollection).length
Try using:
combobox.collection.length
where combobox is the combobox you are using
I'm not sure this will work though. You may need to subclass the control because collection is a protected member :(
The dataprovider of combobox is an arraycollection. You can use the length property to count the number.

Adobe Flex3: Keyboard shortcuts when a view is visible?

I have a quite large Flex application with a large set of views and I ceratain views I'd like to add shortcuts.
And i'm looking for something like:
<mx:Vbox>
<foo:Shortcut keys="ctrl+s" action="{bar();}"/>
....
</mx:VBox>
Is there any framwork or component already done that does something like this? I guess it should be too difficult to build? When building this I only want the shortcuts to be active when the view is visible. How do I detect this? What base class is best to inherit from when working with non visual components?
I don't know of any framework component that does that already, but the examples above should get you started if you try to build your own.
There's no need to inherit from any component for a non-visual component like the one you've described here (your "foo" class needs no parents.) There's nothing in the Flex framework you need to inherit from for this.
However you architect it, your foo class is going to have to take in and parse keyboard codes to listen for and accept one or more methods to call. All you have to do is figure out when to add and remove the event listeners that will call the passed-in methods.
To handle turning your keyboard events on and off based on visibility, just have your foo component bind to the "visible" property of it's parent and add/remove event listeners accordingly.
You might also consider having the listeners added when the component that foo is nested in is on the display list rather than just visible. To do this, simply added and remove your event listeners in one of the component lifecycle methods - probably commitProperties is the most appropriate.
I don't think this solution answer your question directly but anyway, to help solve your problem here is an example.
For instance, I've extended the TextArea component like so. This is the best I can do so far, it can definitely be improved upon. Like, I don't know how to make the cursor go to the end after the next shortcut is pressed.
public class TextArea extends mx.controls.TextArea
{
// the keysmap is an example dictionary holding keycodes
private var keysmap:*={
112 = "some text for F1"
,113 = "the text for F2!"
//etc, etc
}
public var handleKeyDown:Boolean =false;
public function TextArea(){
if(handleKeyDown ==true){
this.addEventListener(KeyboardEvent.KEY_DOWN,this.keydownHandler);
}
}
public function keydownHandler(e:KeyboardEvent):void{
if(e.keyCode >= 112 && e.keyCode <= 123){
e.currentTarget["text"] += String(keysmap[e.keyCode]) +" ";
}//focusManager.setFocus(this);
}
}
I can't give you a solution using MXML, however my first thought would involve a singleton static class with a Dictionary that contains a list of objects as its keys and dynamically created dictionaries as the value pairing that contain keys denoting the desired key press with a function reference as the value.
So, say you had a Sprite and you wanted to capture ctrl+s for save when focus is on that object, I would get the instance of that Singleton, and call a function such as registerKeyBinding passing in the Sprite, the keyCode you want, and your pre-defined callback:
private var registeredObjects:Dictionary = new Dictionary(true);
public function registerKeyBinding(targetObject:Object, keyCode:int, callback:Function) {
if (registeredObjects[targetObject]) {
Dictionary(registeredObjects[targetObject])[keyCode] = callback;
}
else {
registeredObjects[targetObject] = new Dictionary();
Dictionary(registeredObjects[targetObject])[keyCode] = callback;
targetObject.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
}
}
private function keyDownListener(e:KeyboardEvent):void {
if (e.ctrlKey == true) {
//calls the function if that key exists.
Dictionary(registeredObjects[e.target])[e.keyCode];
}
}
Can't say I've tested this, but it was just the first thing that popped into my head. You could then setup functions to deregister and delete keys from the dictionaries, check states of the objects in addition to the keyCodes, remove old listeners, and delete entire dictionaries when there is no longer a need for them. Hopefully this is at least a tiny bit helpful.

Flex ComboBox, default value and dataproviders

I have a Flex ComboBox that gets populated by a dataprovider all is well...
I would now like to add a default " -- select a item --" option at the 0 index, how can I do this and still use a dataprovider? I have not seen any examples of such, but I can't imagine this being hard...
If you don't need the default item to be selectable you can use the prompt property of ComboBox and set the selectedIndex to -1. That will show the string you set propmt to as the selected value until the user chooses another. It will not appear in the list of options, however.
I came across this problem today and wanted to share my solution.
I have a ComboBox that has an ArrayCollection containing Objects as it's dataprovider. When the application runs, it uses a RemoteObject to go out and get the ArrayCollection/Objects. In my event handler for that call I just have it append another object to the beginning of the ArrayCollection and select it:
var defaultOption:Object = {MyLabelField: "Select One"};
myDataProvider.addItemAt(defaultOption, 0);
myComboBox.selectedIndex = 0;
This is what my ComboBox looks like for reference:
<mx:ComboBox id="myComboBox" dataProvider="{myDataProvider}" labelField="MyLabelField" />
The way I've dealt with this in the past is to create a new collection to serve as the data provider for the combobox, and then I listen for changes to the original source (using an mx.BindingUtils.ChangeWatcher). When I get such a notification, I recreate my custom data provider.
I wish I knew a better way to approach this; I'll monitor this question just in case.
This can be used following code for selected default value of combobox
var index:String = "foo";
for(var objIndex:int = 0; objIndex < comboBox.dataProvider.length; objIndex++) {
if(comboBox.dataProvider[objIndex].label == index)
{
comboBox.selectedIndex = objIndex;
break;
}
}
<mx:ComboBox id="comboBox" dataProvider="{_pageIndexArray}" />

Resources