Overview:
I have an advancedDataGrid that I am using a GroupingCollection on and I want to be able to change the individual DefaultLeafIcons (no children icon) based upon a value I get from the dataProvider. Can anyone shed some light on how this is done.
Details:
In the data that I receive there is an isShared value that is either 1 or 0 if the value is 1 I want to be able to display abc.png if the value is 0 display xyz.png.
I am using Flex 3.6 SDK.
I believe you should implement an iconFunction for the datagrid.
a sample iconFunction implementation would look like the following.
[Embed("abc.png")]
private var abcIcon:Class;
[Embed("xyz.png")]
private var xyzIcon:Class;
private function iconFunc(item:Object):Class {
var iconClass:Class;
var itemType:int = item.isShared; //TypeCast item accordingly.
switch(itemType)
{ case 1: iconClass = abcIcon;
break;
case 0: iconClass = xyzIcon;
break;
}
return iconClass;
}
Remember to link the iconFunc with the datagrid by adding the following attribute.
iconFunction="iconFunc"
Related
Is there a way to make sure the selected item is visible in the Spark DataGrid?
.
Context
I have a data grid bound to an array collection. I receive remotely a service that gives me a ID (string) of an object that is in the collection. Using just the string I loop through the collection to find the item that matches the string. I find the object by it's ID. Now I have the object I want to select in the datagrid. I can set the
dataGrid.selectedItem = object;
Now I need to make sure it's visible. I do not have the row or column index.
.
Update
Using the answer below I've complimented it with this function:
/**
* Ensures the item is visible (for spark data grid)
**/
public function ensureItemIsVisibleInSparkDataGrid(datagrid:spark.components.DataGrid, item:Object):void {
var list:IList = datagrid.dataProvider;
var length:int = list.length;
var itemFound:Boolean;
var object:Object;
var index:int;
for (var i:int;i<length;i++) {
object = list.getItemAt(i);
if (object==item) {
itemFound = true;
index = i;
break;
}
}
if (itemFound) {
datagrid.ensureCellIsVisible(index);
}
}
Yes, it's called ensureCellIsVisible(). You need to know that row and column of the item in question. To get this to work you'd need to listen for the selectionChange event then calculate the row and column of the currently selected item.
I have created one dojo datagrid. Every column has a formatter attached to it. When grid is generated the formatter is called. Now I want it so that if a user selects any row the formatter will be called and some strings should be attached to the selected row's column element.
Like grid is like this :
COLUMN
-------
a
b
c
and now user selects the 2nd row, the grid should change to :
COLUMN
-------
a
b SELECTED
c
Currently I implemented it like this :
if(this.grid.selection.selectedIndex !== -1){
retrun value + "SELECTED";
}else{
return value;
}
Can you please suggest a some good way of doing this? Please note that "SELECTED" string should not be added to the grid store.
The formatted is not hooked into clicking / selection of rows. It is solely performed when the contents (value) of a cell is set. Instead you'd want to move focus over to onRowClicked - an event on the grid component. It works like this:
grid.onRowClick = onRowClickHandler;
I wouldnt know which of following samples would put you closest to your goal but onRowClickHandler could be setup as such:
function onRowClickHandler(evt) {
var rows = this.selection.getSelected();
// perform cell rendering here
dojo.forEach(rows, function(row) {
// this row is an item though.. you will have row._O as its index
});
}
OR
function onRowClickHandler(e) {
var cellClicked = this.focus.cell
cellClicked.formatter();
}
However you may find that there are not much references to the viewable data anywhere in the grid component.. You could use following query selectors to find cell data and update the viewed html by calling formatter on each value. You would need to capture a previous selection for 'teardown' of your custom setting of values though.
var prevSelectedRows = [];
function onRowClickHandler(evt) {
var idx = this.selection.selectedIndex,
rawRow = dojo.query(".dojoxGridRow:nth-child("+(idx+1)+")", this.domNode)[0],
self = this;
// perform resetting of viewable values
dojo.forEach(prevSelectedRows, function(raw) {
dojo.query('.dojoxGridCell', raw).forEach(function(cellDOM, i) {
cellDOM.innerHTML = cellDOM.innerHTML.replace("SELECTED", "");
});
});
prevSelectedRows = []; // reset prev selection
// look into grid.view.content for methods on this
// perform setting of viewable values (SELECTED)
dojo.query('.dojoxGridCell', rawRow).forEach(function(cellDOM, i) {
// this function might be of interest, lets see how it looks in console
console.log(self.layout.cells[i].formatter);
cellDOM.innerHTML = cellDOM.innerHTML + "SELECTED"
});
prevSelectedRows.push(rawRow);
}
My question is simple. Let's say I have 2 List Controls. 1 of Users and 1 of Tickets. (The 2 Sources)
And I have a DataGrid (the target). Is possible to select 1 user and 1 ticket in the 2 list mentioned before and drag & drop them at the same time to the DataGrid?
I know it's not as simple as they are going to get automatically mixed.. If it is possible... I would have to use the DragEnter Event of the Datagrid or something to mix them and create my dataProvider. But I don't know how you can drag & drop 2 items at the same time from different sources. It is possible with one source.. But no idea of how to do it with 2 sources.
Any Help would be really appreciated.
Thanks in advance
Yes, I think that would still be possible.
Your option would be:
(click) select the item on the Users and click (select) the item on the Tickets.
From whichever list you started the drag, you would still be able to populate the datagrid with the items from dragEvent and the selected item on the list.
//
boolUsers:Boolean;
On your datagrid:
private function dataGrid_dragDrop(evt:DragEvent) :void
{
// This will get the items from the list where you initiated the drag.
var objDrag:Object;
objDrag = evt.dragSource.dataForFormat("items");
// Depending on where the drag was initiated, get the items from the list.
var objList:Object;
if(boolUsers)
{
objList = listTickets.selectedItem;
}
else
{
objList = listUsers.selectedItem;
}
boolUsers = false;
}
And you would need to define a dragstart event for both your list
private function listUsers_dragStart(evt:DragEvent) :void
{
boolUsers = true;
}
I need to push real time data to a Flex GUI (Data grid), but each time new data is pushed to the grid, it's losing its previous state.
Example:
if I scrolled to the right, after the next update scrolls come back to the default position, that is, left
if I am selecting any row, it's getting unselected just after update.
Is there a way to maintain the state?
I am using Flex 3. I can move to Flex 4 if it helps.
How do you set the data? Do you change the DataGrid dataProvider with a new collection of objects ? Because, from the behavior described by you this may be the case.
The solution would be instead changing the dataProvider of the DG. Each time, you should just update the values in the collection which is assigned as data provider.
For example,
[Bindable]
var myDataCollection:ArrayCollection = new ArrayCollection([0,1,2,3,4]);
// Handle creation complete.
private function onCreationComplete():void
{
initDG();
}
// Init DG data provider just once.
private function initDG(data:ArraCollection):void
{
myDG.dataProvider = data;
}
private function updateDG_Method_1(row:int, value:int):void
{
var data:ArrayCollection = myDG.dataProvider as ArrayCollection;
if(data && data.length > row)
{
data[row] = value;
}
// We can force refresh if not not done automatically.
myDG.invalidateList();
myDG.validateNow();
}
private function updateDG_Method_2(row:int, value:int):void
{
if(myDataCollection && myDataCollection.length > row)
{
myDataCollection[row] = value;
}
// We can force refresh if not not done automatically.
myDG.invalidateList();
myDG.validateNow();
}
Please ignore/correct any typo .. since I did not test this :))
Good luck!
I've gotten a checkbox header renderer to work well with flat DPs, but a
hierarchical collection view is another story. On click, I want it to select all
checkboxes in a given column. Here is my code:
var dp:HierarchicalCollectionView = _dataGrid.dataProvider as
HierarchicalCollectionView;
var testDp:GroupingCollection = dp.source as GroupingCollection;
var rawDp:ArrayCollection = testDp.source as ArrayCollection;
for(var i:int=0 ; i < rawDp.length ; i++){
rawDp[i][_dataField] = cb.selected;
}
It selects all checkboxes on the 2nd level of data, but doesn't select the top
level of data. What am I missing here? I can't seem to find it.
Any tips are greatly appreciated. Thank you.
For hierarchical data you have to use a cursor which iterates over all levels of the hierarchical data.
var dp:IHierarchicalCollectionView = _dataGrid.hierarchicalCollectionView;
var cursor:IViewCursor= dp.createCursor();
while (!cursor.afterLast)
{
cursor.current[_dataField] = cb.selected;
cursor.moveNext();
}
Howerver, this works only with nodes that have previously been opened. So either expand all nodes with _dataGrid.expandAll() (you can collapse them afterwards since the nodes only have to be opened once) or iterate your hierarchical data manually:
function setCheckBoxValue(children:ArrayCollection, value:Boolean):void
{
for each (var child:Object in children)
{
if (child.hasOwnProperty("children") && child["children"])
setCheckBoxValue(child["children"], value);
child[_dataField] = value;
}
}
var myDataProvider:HierarchicalData = /* your data provider */;
// Call it like this...
setCheckBoxValue(myDataProvider.source, cb.selected);
Update: To answer your second question...
Create a new CheckBoxColumn which extends AdvancedDataGridColumn. You can use it to preconfigure your headerRenderer and itemRenderer.
In your custom item renderer you get hold of your column like this:grid = AdvancedDataGrid(listData.owner);
column = grid.columns[listData.columnIndex] as CheckBoxColumn;
Do the same in your header renderer.
Whenever the CheckBox value in one of your item renderers changes dispatch a event through your column. Something like: column.dispatchEvent(new Event("checkBoxValueChanged"));
Your header render should add an event listener to the column for the "checkBoxValueChanged" event (or whatever you call it). Whenever that event is fired loop through your data provider and update the headers CheckBox accordingly.
In theory that should work. HTH