PDA

View Full Version : Flex 3: Multiple data views with single control


MattJohnson
01-08-2009, 06:58 PM
Hya!
I am VERY new to Flex (using FlexBuilder3).
Trying to make a sample project to help me get aquainted with it, but hitting a snag. This seems like it should be simple, but the solution is eluding me.


Idea:
I want to have a single combobox containing names from an array.
when you select a name, extra data associated with that name appears in both a panel of textboxes and a datagrid at the same time.
Selected another name will update the data, and if NO NAME is selected (empty) it should clear everything out.

Problems:
I am not sure how to access or refer to each individual element of an array.
(thus cannot fill the combobox with names)
I am not sure if the structure of the DataArray is correct. (id="foo").
I am not sure TextBoxes have have DataProvidors that will auto-update when using the combobox or if I should just set the value manually from something like a Fill() function. (I would like to be able to do ti either way just for learning sake, but not sure if one way is better or more correct or easier or more efficient than the other, of if doing it automatically via a dataprovider is even possible)

Any help would be greatly appreciated.

Here is the code I have :

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

<mx:Script>
<![CDATA[

import mx.collections.ArrayCollection;

[Bindable] private var DataArray:ArrayCollection ;

<mx:Array id="DataArray">
<mx:List id="Person">
<mx:String id="ID" value="1"/>
<mx:String id="Name" value="Bob Smith"/>
<mx:String id="City" value="Town1"/>
</mx:List>

<mx:List id="Person">
<mx:String id="ID" value="1"/>
<mx:String id="Name" value="Jon Doe"/>
<mx:String id="City" value="Town2"/>
</mx:List>
</mx:Array>

public function Fill():void
{
DataPanel.title = NamesComboBox.selectedLabel ;

// Fill Panel
// next 3 lines get errors. I am note sure how to access
// things like the DataArray.Name element
NameTextBox.text = lastResult.DataArray.Name ;
IDTextBox.text = lastResult.DataArray.ID ;
CityTextBox.text = lastResult.DataArray.City ;
// instead of the above, ahould I add something like
// dataProvider="{DataArray.Name}"
// to each of the TextBoxes?

// Fill DataGrid
// this should be automatic as we have
// DataProvider="{DataArray}"
// set for the DataGrid, right?
}

]]>
</mx:Script>

<!-- ComboBox with list of Names from DataArray.Name -->
<mx:ComboBox id="NamesComboBox" labelField="Name" dataProvider="{DataArray}" change="Fill();" x="10" y="10"></mx:ComboBox>

<!-- Panels Title gets set to selected Name, TexBoxes are filled with appropriate data -->
<mx:Panel id="DataPanel" title="Name" x="10" y="40" width="343" height="321" layout="absolute">
<mx:Label id="NameLabel" text="Name:" x="0" y="52" />
<mx:Text id="NameTextBox" x="66" y="52" width="47"/>

<mx:Label id="IDNumberLabel" text="IDNumber:" x="0" y="24"/>
<mx:Text id="IDNumberTextBox" x="66" y="24" width="47"/>

<mx:Label id="CityLabel" text="City:" x="0" y="78" />
<mx:Text id="CityTextBox" x="66" y="78" width="47"/>
</mx:Panel>

<!-- DaraGrid shows appropriate Data -->
<mx:DataGrid id="DataGrid" dataProvider="{DataArray}" x="361" y="40" width="368" height="321">
<mx:columns>
<mx:DataGridColumn headerText="ID" dataField="ID"/>
<mx:DataGridColumn headerText="Name" dataField="Name"/>
<mx:DataGridColumn headerText="City" dataField="City"/>
</mx:columns>
</mx:DataGrid>

</mx:Application>

ljuwaidah
01-09-2009, 05:31 AM
You can use binding like how you did here:
<mx:DataGrid id="DataGrid" dataProvider="{DataArray}" x="361" y="40" width="368" height="321">

binding changes the value automatically on change.

I'm also not sure about using list.

You might wanna replace Array with ArrayCollection, read the docmuentation about it here: http://livedocs.adobe.com/flex/2/langref/mx/collections/ArrayCollection.html.

This should suffice.

MattJohnson
01-09-2009, 03:05 PM
I already had the binding to DataArray in the dataGrid as posted in the code.
Changing mx:Array to mx:ArrayCollection did not fix the problem.

The combobox is not filling up with the names from DataArray in the code I posted.
(that is the entire code)

Is there anything else I should do?
Thanks

drkstr
01-10-2009, 10:03 PM
<mx:Array id="DataArray">
<mx:List id="Person">
<mx:String id="ID" value="1"/>
<mx:String id="Name" value="Bob Smith"/>
<mx:String id="City" value="Town1"/>
</mx:List>

<mx:List id="Person">
<mx:String id="ID" value="1"/>
<mx:String id="Name" value="Jon Doe"/>
<mx:String id="City" value="Town2"/>
</mx:List>
</mx:Array>

This is all sorts of wrong.

<mx:Array id="DataArray">
<mx:Object Name="Bob Smith" City="Town1" />
<mx:Object Name="Jon Doe" City="Town2" />
</mx:Array>

Or even better:

package pkg
{
import flash.events.EventDispatcher;

[Bindable]
public class DataModel extends EventDispatcher
{
public function DataModel(memento:Object=null)
{
if( memento != null ) {
this.id = memento.id;
this.name = memento.name;
this.city = memento.city;
}
}

public var id:uint;

public var name:String;

public var city:String;

}
}

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" >

<mx:Script>
<![CDATA[
import pkg.DataModel;

import mx.collections.ArrayCollection;

[Bindable]
private var _dataCollection:ArrayCollection = new ArrayCollection([
new DataModel({id:1, name:"Bob Smith", city:"Town1"}),
new DataModel({id:2, name:"Jon Doe", city:"Town2"})
]);

]]>
</mx:Script>

<!-- ComboBox with list of Names from DataArray.Name -->
<mx:ComboBox id="idNamesCombo" labelField="name" prompt="Select a Name"
dataProvider="{_dataCollection}" x="10" y="10"></mx:ComboBox>

<!-- Panels Title gets set to selected Name, TexBoxes are filled with appropriate data -->
<mx:Panel id="DataPanel" x="10" y="40" width="343" height="321" layout="absolute"
title="{(idNamesCombo.selectedItem == null)? 'Name' : DataModel(idNamesCombo.selectedItem).name}">
<mx:Label text="Name:" x="0" y="52" />
<mx:Text x="66" y="52" width="47" text="{DataModel(idNamesCombo.selectedItem).name}"/>

<mx:Label text="IDNumber:" x="0" y="24"/>
<mx:Text x="66" y="24" width="47" text="{DataModel(idNamesCombo.selectedItem).id}"/>

<mx:Label text="City:" x="0" y="78" />
<mx:Text x="66" y="78" width="47" text="{DataModel(idNamesCombo.selectedItem).city}"/>
</mx:Panel>

<!-- DaraGrid shows appropriate Data -->
<mx:DataGrid id="DataGrid" dataProvider="{_dataCollection}" x="361" y="40" width="368" height="321">
<mx:columns>
<mx:DataGridColumn headerText="ID" dataField="id"/>
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="City" dataField="city"/>
</mx:columns>
</mx:DataGrid>

</mx:Application>

By filling your data provider with strongly typed data model classes, you can bind directly to the values (among other benefits). FYI, You don't need data models to bind to the values like this, but it's much more efficient at run time and will not detect changes to the data unless they are in strongly typed classes.


Best Regards,
~Aaron

MattJohnson
01-10-2009, 11:13 PM
I am not to the point of understanding where to put in packages or any of that stuff yet.
Another post was able to give me the infomation I needed to move forward though.
That post is here:
http://www.actionscript.org/forums/showthread.php3?p=830808&posted=1#post830808

Once I get to the point where I am learning about classes and packages and stuff I will give this one a shot.

Thanks!!

ljuwaidah
01-11-2009, 04:58 AM
A simpler, less effective solution that you can use for now would be this:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[

import mx.collections.ArrayCollection;

[Bindable] private var dataArray:ArrayCollection = new ArrayCollection([{id: '1', name: 'Bob Smith', city: 'Town1'}, {id: '2', name: 'Jon Doe', city: 'Town2'}]);

[Bindable] private var selectedItem:Object;
]]>
</mx:Script>

<!-- ComboBox with list of Names from DataArray.Name -->
<mx:ComboBox id="namesComboBox" labelField="name" change="{selectedItem = namesComboBox.selectedItem}" dataProvider="{dataArray}" x="10" y="10"/>

<!-- Panels Title gets set to selected Name, TexBoxes are filled with appropriate data -->
<mx:Panel id="dataPanel" title="Name" x="10" y="40" width="343" height="321" layout="absolute">
<mx:Label id="nameLabel" text="Name:" x="0" y="52" />
<mx:Text id="nameTextBox" text="{selectedItem.name}" x="66" y="52" width="47"/>

<mx:Label id="idNumberLabel" text="IDNumber:" x="0" y="24"/>
<mx:Text id="idNumberTextBox" text="{selectedItem.id}" x="66" y="24" width="47"/>

<mx:Label id="cityLabel" text="City:" x="0" y="78" />
<mx:Text id="cityTextBox" text="{selectedItem.city}" x="66" y="78" width="47"/>
</mx:Panel>

<!-- DaraGrid shows appropriate Data -->
<mx:DataGrid id="dataGrid" change="{selectedItem = dataGrid.selectedItem}" dataProvider="{dataArray}" x="361" y="40" width="368" height="321">
<mx:columns>
<mx:DataGridColumn headerText="ID" dataField="id"/>
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="City" dataField="city"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>

MattJohnson
01-11-2009, 06:30 AM
Very useful alternative. Thank you!
Once I work on learning this part a bit more, I plan to attempt to get the dataArray information from an external PHP script first, and then after that, try to get that data via query from a MySQL table.
I have a feeling that if I use HTTPService and form the XML generated by PHP like your example, it might be a little faster and possible more useful than my current xml structure. (but as I understand it, I might want to use ex4. Not sure exactly what that is yet, but I supposed I will find out when I get to that point.

Thanks again!