How to assign variable as class in Flash Builder 4 Hero SDK - apache-flex

I am trying to assign a variable to a view navigation as follows:
protected function list_clickHandler(event:MouseEvent):void
{
var name1:String = list.selectedItem.vPage;
var name2:Object = list.selectedItem.vPage.valueOf();
navigator.pushView(list.selectedItem.vPage.valueOf(), list.selectedItem);
}
The variable is supposed to be the view for instance it works fine as follows:
navigator.pushView(IM, list.selectedItem);
As the View is presented as a static and not a variable. When you try to submit it as a variable in any format (String, Object) an error occurs.
Error #1034: Type Coercion failed: cannot convert "IM" to Class.
So if anyone has any ideas on how I can send the (View)Class as a variable or if this is a bug in the SDK

No, this is not a bug in the SDK. You pass in a class, and the viewNavigator will construct it for you. If you want to get the the Class of an instance of an object, you can do it like this:
var viewClass = Class(getDefinitionByName(getQualifiedClassName(IM)));
Then, you can pass viewClass into pushView() where it will create a NEW view for you.

Related

Firebase binding in AngularJs

I am having issues binding to an object in firebase. I am using AngularFire and the code in my Angular controller looks like this:
var firebaseCourse = new Firebase("https://torid-fire-1683.firebaseio.com/course-header/course-1");
$scope.course = $firebase(firebaseCourse);
This does successfully connect to firebase and return my data. However, when the object is returned, it is embedded in another object like this:
{"-JDlZpk38i9YsSRoH0ce":{"description":"Course Description","name":"Course One"}}
Thus, when I bind to {{course.name}} in my view, it doesn't work, because the properties are embedded inside another object in the object that $scope.course is bound to.
How do I get around this?
What you are seeing is exactly what firebase sends back. So your code is actually working. I believe that all you have to add is :
$scope.course = $firebase(firebaseCourse).$asArray();
If $asArray() still doesn't give you what you want, you can iterate over the object and create and array. So in your view you can do this:
In your view(html) - instead of - {{courses}} ----> {{getCourses(courses)}}
& in you controller
$scope.getCourses = function(courses) {
var array = [];
for(var key in courses) {
array.push(courses[key]);
}
return array;
}
This way you will have an array or courses instead of a nested object. This will not effect the 3 way binding that is provided by angularFire
Hope this helps! Thanks

Passing data between views and models in Flex MVC framework

I have never used Flex/Actionscript before so excuse me if I'm asking anything obvious but I have been working on this for 3 days (includes searching google and stackoverflow) before writing this post.
I have been asked to modify a game written in Flex 4 made with a mini-IoC-based MVC framework. Two mods I have been asked to make is a game over screen, which displays the final score and a difficulty selection on the introduction screen. I have made the game over screen, and successfully managed to get the controller to bring it up when the game timer runs out.
So for now, the game structure goes:
Intro View -> Game View -> Game Over View
^ |
|__________ (retry?) ________|
The first problem is getting the score to be passed from the mainGame ActionScript file to the game over screen.
Things I have tried:
Importing mainGame in the gameOverViewBase and calling the mainGame.score variable in the gameOverView mxml file.
-EDIT!!! = the above method works if I change the score variable in mainGame to a constant, but if it remains a variable, the controller won't load the gameOverView and the game sits at an empty mainGame view.
Making a function that adds to a new score variable in the gameOverViewBase whenever the player scores during the game.
Passing the score as a parameter to the GameOverView when the MainGame ends
controller.loadGameOver(score);
This seemed like the most logical way to go about it. So I followed the function through the other components of the game setting the loadGameOver to take an integer as a parameter until I got to the main game actionscript file:
public function loadGameOver(score:int) : void
{
loadView(GameOverView);
}
The loadView function (shown below) is where I get stuck because I can't see where to pass the 'score' parameter. It looks like this:
private function loadView(viewClass:Class, modelClass:Class = null) : void
{
var view:View = new viewClass();
if(!view) throw new Error("Could not load view");
viewContainer.removeAllElements();
viewContainer.addElement(view);
view.controller = this;
}
The second problem is the difficulty selection on the introduction screen. I have done this with 3 buttons (easy, normal, hard) in the mxml file and for every button in the ActionScript:
protected function onEasyButtonClick() : void
{
set = "easy"
controller.loadMainGame(set);
}
Once again, I end up at the above loadView function.
To sum up: I need to know how to pass the data between the views and models. If that's not the ideal method, I am open to any other methods that you think are better.
Thank You!
Ben
P.S. I can send my source code to anyone who would like to help :)
You don't specify which MVC framework you're using which would be helpful. However, score should definitely be a property of a model and the model data should be accessible to the view either directly, perhaps via binding (thanks weltraumpirat), or via some intermediary class.
I would suggest you have a look at some of the existing view classes and try to figure out how they are fed the model data. You can use this approach to get the data you need for your view.
[EDIT]:
The mainGame property is not being set on your GameOverView instance so you're unable to access its score property either through binding or through trace. The loadView method of your controller class accepts a Model class reference which it uses to construct a new Model instance to be used by the new View. Unfortunately this is no use to you as your GameOverView needs the instance of MainGame which was created for the MainGameView (and which contains the current score).
I don't know if the following fits into the philosophy of the framework you're using. However, I would change the loadView method to accept an instance of a Model rather than a class reference, and create and cache a reference to an instance of MainGame when your controller is instantiated. That way you can pass the same Model reference to both the MainGameView and GameOverView when these are created.
public class WhackAMoleBase extends Application implements IGameController
{
public var viewContainer:Group;
private var mainGame:MainGame
public function WhackAMoleBase() : void
{
super();
// Create and cache an instance of the main game Model
mainGame = new MainGame();
addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
}
public function loadIntroduction() : void
{
loadView(IntroductionView);
}
public function loadMainGame() : void
{
loadView(MainGameView, mainGame);
}
public function loadGameOver() : void
{
// Use the same instance of MainGame which the MainGameView
// has been using as the Model for the GameOverView
loadView(GameOverView, mainGame);
}
// Accept a Model instance rather than a class Reference
private function loadView(viewClass:Class, model:Model = null) : void
{
//Create a new instance of the supplied view
var view:View = new viewClass();
if(!view) throw new Error("Could not load view");
//Clear any previous views in the container and add
viewContainer.removeAllElements();
viewContainer.addElement(view);
//Property based dependency injection
view.controller = this;
//There may or may not be a model required for the
//requested view; check and instantiate appropriately
if(model)
{
//Give model reference to the controller
//and link the view up to the model
model.controller = this;
view.model = model;
}
}
private function onCreationComplete(event:FlexEvent) : void
{
//When the application is first created, we want to show the introductory view
loadView(IntroductionView);
}
}

Data binding across multiple objects in Flex 3

I am new to Flex (got assigned to maintain an old project at work) and am having some trouble getting data binding to work correctly. I have a popup form class, AddOffer.mxml which uses a model AddOfferModel.as. On my popup form, I have the following component:
<mx:FormItem label="{getResource('addOffer.form.OFFER_DATE')}:"
labelWidth="90">
<views:OfferWindowDatesFragment
id="offerWindowField"
start="{model.offerStartDate}"
stop="{model.offerStopDate}" />
</mx:FormItem>
My AddForm.mxml file also has some embedded actionscript where I define my 'model' variable:
[Bindable]
public var model:AddOfferModel;
The model variables I am trying to bind to are standard getters/setters and look like this inside AddOfferModel.as:
[Bindable]
public function set offerStartDate(val:EditableInstant):void
{
_offerStartDate = val;
}
public function get offerStartDate():EditableInstant
{
return _offerStartDate;
}
private var _offerStartDate:EditableInstant;
[Bindable]
public function set offerStopDate(val:EditableInstant):void
{
_offerStopDate = val;
}
public function get offerStopDate():EditableInstant
{
return _offerStopDate;
}
private var _offerStopDate:EditableInstant;
Inside the OfferWindowDatesFragment component class, the start and stop variables look like this:
[Bindable]
public function set start(val:EditableInstant):void
{
_start = val;
}
public function get start():EditableInstant
{
return _start;
}
private var _start:EditableInstant;
[Bindable]
public function set stop(val:EditableInstant):void
{
_stop = val;
}
public function get stop():EditableInstant
{
return _stop;
}
private var _stop:EditableInstant;
Basically, I just want to bind the start and stop variables in my OfferWindowDatesFragment class to the offerStartDate and offerStopDate variables in the AddOfferModel.as file. Whenever I access the start/stop variables in functions inside the OfferWindowDatesFragment class, they are null.
I have an event listener function that gets triggered in OfferWindowDatesFragment anytime a user selects a new date, it looks like this:
private function changeOfferDate():void
{
start.currentValue = offerDateEditor.start;
stop.currentValue = offerDateEditor.stop;
}
Every time I reach this function, it throws up an error because 'start' and 'stop' are both null ... but should have been initialized and bound already. If I look at the variables in the debugger, I can confirm that values on the right side of the assignment expression are valid, and not what is causing the error.
I am not real familiar with how initialization works in Flex, and I assumed as long as I instantiated the component as seen in the first code snippet at the top of my post, it would initialize all the class variables, and setup the bindings. Am I missing something? Perhaps I am not properly initializing the model or class data for AddForm.mxml or AddFormModel.as, thereby binding null references to the start/stop fields in my OfferWindowDatesFragment class?
Any help would be greatly appreciated. Thanks!
EDIT:
I looked into this further and tried using Mate to inject the 'model' variable inside AddOffer.mxml with a valid AddOfferModel object:
<Injectors target="{AddOffer}" debug="{debug}">
<ObjectBuilder generator="{AddOfferModel}" constructorArguments="{scope.dispatcher}" cache="local"/>
<PropertyInjector targetKey="model" source="{lastReturn}" />
</Injectors>
I load the AddOffer.mxml dialog as the result of a button click event on another form. The function that pops it up looks like this:
public function addOffer():void
{
var addOfferDialog:AddOffer = new AddOffer();
addOfferDialog.addEventListener("addOffer", addOfferFromDialog);
modalUtil.popup(addOfferDialog);
}
It doesn't seem to be assigning anything to the 'model' variable in AddOffer.mxml. Does loading a view/dialog this way not trigger an injection from Mate by chance? (I realize this last part might belong in the Mate forums, but I'm hoping somebody here might have some insight on all of this).
In AddOffer.mxml, you have this code:
[Bindable]
public var model:AddOfferModel;
Is there something outside AddOffer.mxml that is setting this to a valid AddOfferModel? There should be. The nature of how the Flex component life cycle means that you can expect that things may be null at times as a View builds. So you should build your components to be able to "right themselves" after receiving bad data, if the data eventually comes good.
Data binding is one way to do this, but it may not paper over everything depending on what else is going on.
Have you verified that the model value you're getting is not null at the point where the user selects the date and that its offerStartDate and offerEndDate properties have been populated with valid EditableInstants? If both of those are correct, I'd start looking for pieces of the Views that expect to have stuff at a given instant and then don't recover if it is provided later.

How to set an empty Object's properties programatically?

I'm doing some Actionscript work right now and I'd like to know whether there's a way to initiate an empty object's value programatically like this:
var myObj:Object = new Object;
myObj.add("aKey","aValue");
To add a property called aKey whose value is aValue
I need to create a "Dumb" (data-only) object to use as a parameter to send via POST. So I don't know offhand how long and/or how many attributes it's gonna have.
Or something like that.
Thanks
ActionScript 3 allows you to create new Objects using an expressive Object Literal syntax similar to the one found in JavaScript:
const myObj : Object = {
aKey: "aValue",
};
trace(myObj.aKey); // "aValue"
If you want to assign properties after the object has been constructed then you can use either dot notation or square bracket notation, eg:
const myObj : Object = {}; // create an empty object.
myObj.aKey = "aValue";
myObj["anotherKey"] = "anotherValue";
If you plan on sending the data over HTTP, you may wish to consider looking at the URLVariables class which will take care of URL encoding the data for you.

TypeError: Error #1034: Type Coercion failed: cannot convert Object#1456c7b9 to mx.messaging.messages.IMessage

Im trying to connect a Flash client to BlazeDS. There has been some success with this from others using the vanilla BlazeDS setup. However I'm using the new Spring BlazeDS Integration from springsource and running aground.
The flash client actually seems to be working in that I can see the correct data in the body of the returned object, but for some reason unknown it fails casting as an IMessage. It fails in PollingChannel.as on this line with the subject line error
var messageList:Array = msg.body as Array;
for each (var message:IMessage in messageList) <--
On application load I register a whole bunch of classes like so
registerClassAlias( "flex.messaging.messages.RemotingMessage", RemotingMessage );
registerClassAlias("mx.messaging.messages.IMessage", IMessage);
etc..
my code is basically
var channelSet:mx.messaging.ChannelSet = new mx.messaging.ChannelSet();
var channel:mx.messaging.channels.AMFChannel = new AMFChannel("my-amf", "http://localhost:8400/SpringA/messagebroker/amf");
channelSet.addChannel(channel);
var consumer:mx.messaging.Consumer = new Consumer();
consumer.channelSet = channelSet;
consumer.destination = "simple-feed";
consumer.subscribe();
consumer.addEventListener(MessageEvent.MESSAGE, test);
private function test(event:IMessage)
{
trace("msg..");
// breakpoint never makes it here
}
I have a flex client which works 100% with same destination/channel.
The error in the title means that you, for some reason, got an object that is not implementing or extending the IMessage interface, therefore the loop can not cast it in this part:
for each (var message:IMessage in messageList){
Either you should somehow make sure that you don't add anything that is not extending or implementing IMessage, or check if the variable IS actually ext./imp. it. Also - if you want to do that, you will have to change the for each like this:
for each (var obj in messageList){
if (obj is IMessage){
var message:IMessage = obj as IMessage;
// DO STUFF HERE
}
}
Add this Object mapping:
registerClassAlias("flex.messaging.io.ObjectProxy", ObjectProxy);
If on your Java VO objects you have overridden the hashcode() method, this situation could happen.
Remove the hashcode() override (if you are able to).
See my blog for the backstory on how I discovered this. http://squaredi.blogspot.com/2013/12/remoting-landmine-without-stack-trace.html
I had the same error when trying to send an actionscript object to the backend. My problem was that my c# equivalent object was missing an public parameterless constructor.

Resources