PDA

View Full Version : OOP and AS3 in flex - httpService class?


nathank000
06-20-2007, 04:57 PM
First, thanks for reading...

OK - I am totally new to OOP and relatively new to flex. I am designing an admin area for our web app, and I am having issues with my first class. What I am tring to do is develop a class that will tack on the appropriate $_GET arguments for a php file that returns all of the users movies for use in a dataGrid. I have a list of categories on the left, and I want to limit the list of movies to a specific category when the user clicks it. I think i am just missing a point in OOP that is obvious, but I have worked on this for 2 days and I am now asking for help.

in my FLEX app I have the following code and componenents (all abbreviated...):


<mx:Script>
<![CDATA[
//create a class to make all the data calls CAN DO!!!

//import necessary classes
import mx.controls.Alert;
import mx.events.CloseEvent;
import jp.select.MovieSelect;


//create a new instance of the selectService
var selectService:MovieSelect = new MovieSelect();
]]>
</mx:Script>

<mx:Accordion x="0" y="182" width="100%" height="100%">
<mx:Canvas label="View All" width="100%" height="100%">
</mx:Canvas>
<mx:Canvas label="Categories" width="100%" height="100%">
<mx:DataGrid dropEnabled="true" x="0" y="0" id="categorySort" width="100%" height="100%" editable="false" dataProvider="{divisionalData.lastResult.divisions.category}" change="selectService.limitToCategory(categorySort.selecte dItem.recno);" >
<mx:columns>
<mx:DataGridColumn headerText="Title" dataField="title"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
<mx:Canvas label="Styles" width="100%" height="100%">
<mx:DataGrid x="0" y="0" width="100%" height="100%" editable="false" dataProvider="{divisionalData.lastResult.divisions.styles}">
<mx:columns>
<mx:DataGridColumn headerText="Title" dataField="col1"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
<mx:Canvas label="Playlists" width="100%" height="100%">
<mx:DataGrid x="0" y="0" width="100%" height="100%" editable="false" dataProvider="{divisionalData.lastResult.divisions.playlist}">
<mx:columns>
<mx:DataGridColumn headerText="Title" dataField="title"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
</mx:Accordion>

<mx:DataGrid dragEnabled="true" doubleClickEnabled="true" click="stopPlayback(); enableMovieOptions();" id="movieGrid" x="0" y="0" width="100%" height="100%" rowHeight="30">
<mx:columns>
<mx:DataGridColumn headerText="Preview" dataField="thumbnail" paddingLeft="10" itemRenderer="mx.controls.Image"/>
<mx:DataGridColumn headerText="Status" dataField="status" editable="true"/>
<mx:DataGridColumn headerText="Title" dataField="title"/>
<mx:DataGridColumn headerText="Filesize" dataField="filesize"/>
<mx:DataGridColumn headerText="Size" dataField="width"/>
<mx:DataGridColumn headerText="Duration" dataField="duration"/>
<mx:DataGridColumn headerText="Category" dataField="category"/>
<mx:DataGridColumn headerText="Style" dataField="style"/>
</mx:columns>
</mx:DataGrid>




in my class file I have the following code:

package jp.select {


//import stuff
import mx.rpc.http.HTTPService;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import flash.events.Event;

public class MovieSelect
{
//create a new instance (?) of the httpservice obj
private var _movieSelectService:HTTPService;

//create the first function which initializes the class (?)
//below is a constructor
//it should have the same name as the class
//it SHOULD NOT declare a return type or return value.
public function MovieSelect(){
_movieSelectService = new HTTPService();
_movieSelectService.send();
//for local testing
//_movieSelectService.url = "http://localhost/jetpac/userMoviesSelectLocal.php";

//for remote testing
//_movieSelectService.url = "http://jetpac.tv/iv_anager/adminData/userMoviesSelect.php";

}

public function limitToCategory(catRecno:String):void{
//set the url to the url limiter
_movieSelectService.url = "http://jetpac.tv/iv_manager/adminData/userMoviesSelect.php?limit=" +catRecno +"&limitType=category";

//alert to see if it's working
//var qicklert:Alert = Alert.show("You have invoked the limt to cat method");

//show the busy cursor while working
//_movieSelectService.showBusyCursor = true;

//add an event listner(?)
_movieSelectService.addEventListener(ResultEvent.R ESULT, updateMovieList);

//do it
_movieSelectService.send();

}

/* public function limitTopPlaylist(plRecno:String){

}

public function limitToStyle(styleRecno:String){

} */

//create an updater function to update the movie list
private function updateMovieList(event:ResultEvent):void {
var qicklert:Alert = Alert.show("You have invoked the limt to cat method");
movieGrid.dataProvider = _movieSelectService.lastResult.movies.movie;
//var movieGridData = _movieSelectService.lastResult.movies.movie;

}

}
}


so when the user clicks a category - I want the class to get the file with the appropriate arguments tacked on and then bind those results to the movie grid. Where am I going wrong?

drkstr
06-20-2007, 06:18 PM
Well I didn't go through the code in detail so this may not be the only problem, but I did notice you were trying to access variables in your class (for instance movieGrid) without passing a reference to that object first. Alternatively, you can access objects defined in the application or parent scope by using the Application object, but it is much better OOP to pass a reference to your class instead.

Passing a reference is as easy as adding to your class

private var myMovieGrid:DataGrid;

then you can either add a function that takes a movie grid as a parameter to assign the reference, or wait to instantiate your class until creationComplete, and pass the reference in the constructor.

Hope this helps,
...aaron

nathank000
06-20-2007, 08:10 PM
I am so over my head - but that's how we learn to swim...

am I close to being on the right track?

I have altered my class code to:




package jp.select {


//import stuff
import mx.rpc.http.HTTPService;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import flash.events.Event;
import mx.collections.ArrayCollection;



public class MovieSelect
{
//create a new instance (?) of the httpservice obj
public var movieGridData:Object;
private var _movieSelectService:HTTPService;

//create the first function which initializes the class (?)
//below is a constructor
//it should have the same name as the class
//it SHOULD NOT declare a return type or return value.
public function MovieSelect(){
_movieSelectService = new HTTPService();
_movieSelectService.send();
//for local testing
//_movieSelectService.url = "http://localhost/jetpac/userMoviesSelectLocal.php";

//for remote testing
//_movieSelectService.url = "http://jetpac.tv/iv_anager/adminData/userMoviesSelect.php";
movieGridData = _movieSelectService.lastResult;
}

public function limitToCategory(catRecno:String):void{
//set the url to the url limiter
_movieSelectService.url = "http://jetpac.tv/iv_manager/adminData/userMoviesSelect.php?limit=" +catRecno +"&limitType=category";

//alert to see if it's working
//var qicklert:Alert = Alert.show("You have invoked the limt to cat method");

//show the busy cursor while working
//_movieSelectService.showBusyCursor = true;

//add an event listner(?)
_movieSelectService.addEventListener(ResultEvent.R ESULT, updateMovieList);

//do it
_movieSelectService.send();

}

/* public function limitTopPlaylist(plRecno:String){

}

public function limitToStyle(styleRecno:String){

} */

//create an updater function to update the movie list
private function updateMovieList(event:ResultEvent):Object {
var qicklert:Alert = Alert.show("You have invoked the limt to cat method");
//movieGrid.dataProvider = _movieSelectService.lastResult.movies.movie;
movieGridData = _movieSelectService.lastResult.movies.movie;
return movieGridData;

}

}
}

and now I am trying to assign that returned data to the dataGrid using:

<mx:DataGrid dragEnabled="true" doubleClickEnabled="true" click="stopPlayback(); enableMovieOptions();" id="movieGrid" x="0" y="0" width="100%" height="100%" rowHeight="30" dataProvider="{selectService.movieGridData}">

when I click on a category it invokes the limitToCategory methoid properly, and the data returned from the file is like so:

<movies>
<movie>
<recno>303</recno>
<status>active</status>
<title>msg to paul @ enthios</title>
<filename>REC_14_01092007371.flv</filename>
<width>320</width>
<height>240</height>
<duration>46.172</duration>
<filesize>1853168</filesize>
<thumbnail>http://www.jetpac.tv/thumbs/REC_14_01092007371.flv.jpg</thumbnail>
<previewURL>http://www.jetpac.tv/converted/REC_14_01092007371.flv</previewURL>
<category>messages</category>
<style></style>
</movie>
</movies>

drkstr
06-20-2007, 09:35 PM
It's hard to say if you're on the right track or not because I still don't really understand what you're trying to do, or what it's not doing right now.

I'm going to take a stab in the dark and assume you are trying to get some kind of XML data from your class, then have your data grid update the display with the new information.

To update a display object every time the data changes, you will need to create a bindable var of type XMLListCollection, or ArrayCollection. Luckly, I am board, so I wrote a brief example of how to update a display object from data in a class w/ proper (in my opinion at least) OOP practices.

--==DataGridExample.mxml==--
<?xml version="1.0"?>
<!-- DataGrid control example. -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script>
<![CDATA[
import mx.collections.XMLListCollection;
import pkg.DataSelecter;

[Bindable]
private var myDataProvider:XMLListCollection;

private var myDataSelector:DataSelecter = new DataSelecter();

]]>
</mx:Script>

<mx:Panel title="DataGrid Control Example" height="100%" width="100%"
paddingTop="10" paddingLeft="10" paddingRight="10">

<mx:DataGrid id="dg" width="100%" height="100%" rowCount="5" dataProvider="{myDataProvider}">
<mx:columns>
<mx:DataGridColumn dataField="name" headerText="Name"/>
<mx:DataGridColumn dataField="phone" headerText="Phone"/>
<mx:DataGridColumn dataField="email" headerText="Email"/>
</mx:columns>
</mx:DataGrid>
<mx:Button label="Get Data" click="myDataProvider = myDataSelector.getData();" />

</mx:Panel>
</mx:Application>

--==pkg/DataSelecter.as==--
package pkg
{
import mx.collections.XMLListCollection;


public class DataSelecter
{
private var myData:XML =
<data>
<employee>
<name>Christina Coenraets</name>
<phone>555-219-2270</phone>
<email>[email protected]</email>
<active>true</active>
</employee>
<employee>
<name>Joanne Wall</name>
<phone>555-219-2012</phone>
<email>[email protected]</email>
<active>true</active>
</employee>
<employee>
<name>Maurice Smith</name>
<phone>555-219-2012</phone>
<email>[email protected]</email>
<active>false</active>
</employee>
<employee>
<name>Mary Jones</name>
<phone>555-219-2000</phone>
<email>[email protected]</email>
<active>true</active>
</employee>
</data>;

public function getData():XMLListCollection {
return new XMLListCollection(myData.elements());
}
}
}

When you click the button, it will get the data from the class and update the DataGrid with it.

hope this helps,
...aaron

nathank000
06-21-2007, 02:46 PM
reading your post I realized some of what I was doing and I was WAYYY off--- Thanks for pointing me in the right direction!

Here is where I ended up, after reading a good chapter in O'reilly's "programming flex 2"

in my flex app:
----------------------------------------------------

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
horizontalAlign="left" verticalAlign="top" paddingBottom="5"
paddingTop="0" paddingLeft="5" paddingRight="5"
creationComplete="creationCompleteHandler(event)">
<!-- set the data source -->

<mx:HTTPService id="divisionalData"
url="userDivisionSelect.php"
useProxy="false"/>
<mx:HTTPService id="actionDo"
url="actionLocal.php"
useProxy="false"/>

<!-- set the functions for initial state -->

<!-- move to category-->
<!-- move to playlist-->
<!-- add style to movie-->

<mx:Script>
<![CDATA[
//create a class to make all the data calls CAN DO!!!

//import necessary classes
import mx.controls.Alert;
import mx.events.CloseEvent;
import jp.select.ApplicationDataModel;
import jp.select.MovieService;
import mx.rpc.http.HTTPService;
import mx.rpc.events.ResultEvent;

private var _MovieService:MovieService;

private function creationCompleteHandler(event:Event):void{
_MovieService = new MovieService();
_MovieService.getMovies();

divisionalData.send()
}
]]>
</mx:Script>


<!-- -->
<mx:ApplicationControlBar width="100%">
<mx:Button label="admin main" fillColors="[#e6f025, #969b26]"
fillAlphas="[0.61, 0.87]" color="#ffffff"/>
<mx:VRule width="3" height="10"/>
<mx:Button label="record a movie"/>
<mx:Button label="upload a movie"/>
<mx:VRule height="10" width="3"/>
<mx:Button label="movies"/>
<mx:Button label="categories"/>
<mx:Button label="styles"/>
<mx:Button label="playlists"/>
<mx:Button label="assets"/>
<mx:Button label="xml"/>
<mx:Button label="widgets"/>
<mx:VRule width="3" height="10"/>
<mx:Button label="stats"/>
</mx:ApplicationControlBar>

<mx:TitleWindow width="100%" height="100%" layout="absolute"
title="Movies" horizontalScrollPolicy="off">
<mx:Canvas x="0" y="0" width="200" height="100%">
<mx:Accordion x="0" y="182" width="100%" height="100%">
<mx:Canvas label="View All" width="100%" height="100%">
</mx:Canvas>
<mx:Canvas label="Categories" width="100%" height="100%">
<mx:DataGrid dropEnabled="true" x="0" y="0" id="categorySort"
width="100%" height="100%" editable="false"
dataProvider="{divisionalData.lastResult.divisions.category}"
change="_MovieService.getMoviesByCategory(categorySort.sel ectedItem.recno);">
<mx:columns>
<mx:DataGridColumn headerText="Title" dataField="title"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
<mx:Canvas label="Styles" width="100%" height="100%">
<mx:DataGrid x="0" y="0" width="100%" height="100%"
editable="false"
dataProvider="{divisionalData.lastResult.divisions.styles}">
<mx:columns>
<mx:DataGridColumn headerText="Title" dataField="col1"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
<mx:Canvas label="Playlists" width="100%" height="100%">
<mx:DataGrid x="0" y="0" width="100%" height="100%"
editable="false"
dataProvider="{divisionalData.lastResult.divisions.playlist}">
<mx:columns>
<mx:DataGridColumn headerText="Title" dataField="title"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
</mx:Accordion>
<mx:TitleWindow width="200" height="182" layout="absolute"
title="preview" x="0" y="0">
<mx:VideoDisplay x="0" y="0" width="180" height="142" id="vDisplay"/>
</mx:TitleWindow>
</mx:Canvas>
<mx:Canvas x="208" width="100%" height="100%" y="0">
<!-- what happens on double click? preview or edit te movie? -->
<mx:DataGrid dragEnabled="true" doubleClickEnabled="true"
click="stopPlayback(); enableMovieOptions();" id="movieGrid" x="0"
y="0" width="100%" height="100%" rowHeight="30"
dataProvider="{ApplicationDataModel.getInstance().Movies}">
<mx:columns>
<mx:DataGridColumn headerText="Preview" dataField="thumbnail"
paddingLeft="10" itemRenderer="mx.controls.Image"/>
<mx:DataGridColumn headerText="Status" dataField="status"
editable="true"/>
<mx:DataGridColumn headerText="Title" dataField="title"/>
<mx:DataGridColumn headerText="Filesize" dataField="filesize"/>
<mx:DataGridColumn headerText="Size" dataField="width"/>
<mx:DataGridColumn headerText="Duration" dataField="duration"/>
<mx:DataGridColumn headerText="Category" dataField="category"/>
<mx:DataGridColumn headerText="Style" dataField="style"/>
</mx:columns>
</mx:DataGrid>


</mx:Canvas>

</mx:TitleWindow>
</mx:Application>
----------------------------------------------------
class ApplicatrionDataModel
----------------------------------------------------

package jp.select
{
import mx.collections.ListCollectionView;


public class ApplicationDataModel
{
private static var _instance:ApplicationDataModel;

private var _movies:ListCollectionView;

[Bindable]
public function set Movies(value:ListCollectionView):void{
_movies = value;
}

public function get Movies():ListCollectionView{
return _movies
}

public function ApplicationDataModel(){}

public static function getInstance():ApplicationDataModel{
if(_instance == null){
_instance = new ApplicationDataModel();
}
trace ("instance returned");
return _instance;
}

}
}

----------------------------------------------------
class MovieService
----------------------------------------------------

package jp.select
{

import mx.rpc.http.HTTPService;
import mx.rpc.events.ResultEvent;
import mx.collections.XMLListCollection;
import jp.select.ApplicationDataModel;

public class MovieService {
private var _service:HTTPService;

public function MovieService(){
_service = new HTTPService();
_service.resultFormat = "e4x";
}

public function getMovies():void{
_service.addEventListener(ResultEvent.RESULT, moviesResultHandler);
_service.url =
"userMoviesSelect.php";
_service.send();
}

public function getMoviesByCategory(category:int):void{
_service.addEventListener(ResultEvent.RESULT, moviesResultHandler);
_service.url =
"http://jetpac.tv/iv_manager/adminData/userMoviesSelect.php?limitType=category&l\
imit="
+ category;
_service.send();
}

public function moviesResultHandler(event:ResultEvent):void{
_service.removeEventListener(ResultEvent.RESULT, moviesResultHandler);
ApplicationDataModel.getInstance().Movies = new
XMLListCollection(_service.lastResult.children() as XMLList);

}

}
}