Get dispatchEvent data as a result - actionscript-3

Here i am working on native extension in which i send/dispatch data in the dataevent like:
public static const PASSING_VIDEO_URL : String = "PASSING_URL";
dispatchEvent( new DataEvent( PASSING_URL,true,false,level) );
Now on eventlistener
cd.addEventListener( CD.PASSING_URL, onURL );
protected function onURL(event:Event):void
{
txtUrl.text = event.data;
txtUrl.text = event.text;
}
I got that data on event.data when i watch. but i write as above. event.data; Or event.text; then i am getting error.
So, my question is how can i get event.data or event.text ?

The .data property is defined in DataEvent, not Event. But your parameter of the method is of type Event.
Change the type of the parameter to DataEvent.

Related

In AS3/AIR how can I execute the result method of a responder object?

We are creating an extension for the NetConnection object. When we get an error we will retry “n” times. After “n” times we want to call the responder result method returning an error. The responder object contains two properties, both functions, however we cannot seem to see how to access those functions. Is it possible to execute the “result” function of Responder object?
An example might be;
_rspResponder:Responder = new Responder(someFunction);
// lots of code...
_rspResponder.result("Error: Connection timeout failure.\n A network connection error occurred, if needed please try to save work and restart the application.\n Otherwise just restart the application.\n");
Edit:
Based on comments below I created an extended responder like;
package com.fluorinefx
{
import flash.net.Responder;
public class PublicResponder extends Responder
{
/**
* result - Result handler function
*
* #return result
*/
private var _result:Function = null;
public function get result():Function
{
return this._result;
}
public function set result(value:Function):void
{
this._result = value;
}
/**
* status - Status (error) handler function
*
* #return status
*/
private var _status:Function = null;
public function get status():Function
{
return this._status;
}
public function set status(value:Function):void
{
this._status = value;
}
public function PublicResponder(result:Function, status:Function=null)
{
_result = _result;
_status = status;
super(result, status);
}
}
}
When I attempt to use it in my extended NetConnection like;
import com.fluorinefx.PublicResponder;
private var _rspResponder:PublicResponder;
public override function call(strCommand:String, rspResponder:Responder, ...parameters:Array):void
_rspResponder = rspResponder;
I get an implicit coercion error on the "_rspResponder = rspResponder;" line.
After “n” times we want to call the responder result method returning an error.
Is it possible to execute the result function of the Responder object?
Does something like this setup help you?
//# global vars
public var _rspResponder :Responder;
public var try_count :int = 0;
//# test it...
_rspResponder = new Responder( onResult, onError );
//# Since "result" param can be Object or String... using asterix to allow any data-type
private function onResult( result:* ) :void
{
trace( result ); try_count = 0;
}
//# no comment needed here...
private function onError( error:Object ) :void
{
try_count++;
_rspResponder = new Responder( onResult, onError ); //# retry again
//# after N retries, send custom error String to "onResult" function
if ( try_count == 5)
{
onResult( "Error: Connection timeout failure.\n A network connection error occurred, if needed please try to save work and restart the application.\n Otherwise just restart the application.\n" );
}
}

MvvmCross IMvxNavigationFacade, MvxViewModelRequest causes Init() to be called rather than Prepare()

I've implemented an IMvxNavigationFacade for deep linking in my MvvmCross 5.6.x sample app. I've added logic in BuildViewModelRequest() to construct a MvxViewModelRequest with parameters passed in as MvxBundle.
if (url.StartsWith("http://www.rseg.net/rewards/"))
{
var parametersBundle = new MvxBundle();
var id = url.Substring(url.LastIndexOf('/') + 1);
parametersBundle.Data.Add("id", id);
return Task.FromResult(
new MvxViewModelRequest(typeof(RewardDetailViewModel),
parametersBundle, null));
}
However, this approach causes the old style Init() method to be called in the target ViewModel rather than the new typesafe Prepare() method.
public class RewardDetailViewModel :
MvxViewModel<RewardDetailViewModel.Parameteres>
{
...
public new void Init(string id)
{
if (!string.IsNullOrWhiteSpace(id))
{
if (int.TryParse(id, out _rewardId))
RaiseAllPropertiesChanged();
}
}
public override void Prepare(Parameteres parameter)
{
if (parameter != null)
{
_rewardId = parameter.RewardId;
RaiseAllPropertiesChanged();
}
}
}
Is there a way to construct a MvxViewModelRequest so that you pass in an instance of the parameter class for the target ViewModel causing the Prepare() method to be called?
The entire solution can be viewed on GitHub https://github.com/rsegtx/So.MvvmNav2
Thanks in advance!
After doing some research I found at lease one way to accomplish this.
Create a ViewModelInstanceRequest rather than a ViewModelRequest so that you can call ViewModelLoader.LoadViewModel passing in a parameters object; the ViewModelRequest only allows parameters to be passed using a MvxBundle. Make the following change to BuildViewModelRequest() on the NavigationFacade:
var request = new
MvxViewModelInstanceRequest(typeof(RewardDetailViewModel));
var parameters = new RewardDetailViewModel.Parameteres();
.... parse parameters and fill in parameters object
request.ViewModelInstance = ViewModelLoader.LoadViewModel(
request, parameters, null);
return Task.FromResult((MvxViewModelRequest)request);
Create your own IMvxNavigationService and add logic to inspect the object returned from the NavigationFacde and if it is a ViewModelInstanceRequest then use it as is rather than one previously creating.
var facadeRequest = await facade.BuildViewModelRequest(path,
paramDict).ConfigureAwait(false);
...
if (facadeRequest is MvxViewModelInstanceRequest)
request = facadeRequest as MvxViewModelInstanceRequest;
else
{
facadeRequest.ViewModelType = facadeRequest.ViewModelType;
if (facadeRequest.ParameterValues != null)
{
request.ParameterValues = facadeRequest.ParameterValues;
}
request.ViewModelInstance = ViewModelLoader.LoadViewModel(
request, null);
}
I've updated the original example on GitHub https://github.com/rsegtx/So.MvvmNav2.

How to call a static function on an ActionScript object's ancestor class?

The Ancestor class does, indeed, have a function called (for the sake of example) "foo".
public static function callAncestorStaticMethod() : void
{
var ancestorClassName : String = getQualifiedSuperclassName(Descendant);
var ancestorClass : Class = Class(getDefinitionByName(ancestorClassName));
ancestorClass.foo(); // <---- runtime error here: foo is not a function
}
Examining ancestorClass finds it an Object with no visible properties (ancestorClass.prototype does not either).
So, how do I call a static function on a class when I only have its name as a string at runtime ?
I was able to call a static function in the superclass using the following code:
var c:ChildClass = new ChildClass();
var s:String = getQualifiedSuperclassName(c);
var cl:Class = getDefinitionByName(s) as Class;
cl.foo.call();
//cl["foo"].call();
A Class object has all of the static properties and methods of the Class, so this should be reliable. cl.foo returns a Function object that you can then .call().
You can get a reference to the instance's own class using the constructor property, but to access the ancestor classes, you have to use describeType and getDefinitionByName. These are powerful, but costly - so make sure you don't overuse this:
function callStaticAncestorProperty( instance:Object, staticProperty:String ):* {
var type:XML = describeType( instance );
var ret:* = instance.constructor[staticProperty];
for each(var extend:XML in type.extendsClass)
ret = ret ? ret : getStaticPropertyOrUndefined( extend, staticProperty );
return ret;
}
function getStaticPropertyOrUndefined( extend:XML, staticProperty:String ):* {
var clazz:Class = getDefinitionByName( extend.#type.toString().replace( "::", "." ) ) as Class;
return clazz[staticProperty] ? clazz[staticProperty] : undefined;
}
This checks if the class itself has the property, and then iterates over each super type. Note that the first value to be found will be returned, i.e. if both the subclass and a super class have this property, that of the subclass will be returned.
Edit
I only just realized you were asking about method calls, not properties. That works pretty much the same way:
function callStaticAncestorMethod( instance:Object, staticMethod:String ):void {
var type:XML = describeType( instance );
var method:Function = instance.constructor[staticMethod];
for each(var extend:XML in type.extendsClass)
method = method ? method : getStaticMethodOrUndefined( extend, staticMethod );
if (method) method();
}
function getStaticMethodOrUndefined( extend:XML, staticMethod:String ):Function {
var clazz:Class = getDefinitionByName( extend.#type.toString().replace( "::", "." ) ) as Class;
return clazz[staticMethod] ? clazz[staticMethod] : undefined;
}
Or (Based on Sam DeHaan answer's):
If Superclass and Descendant have both a String id property...
(getDefinitionByName(getQualifiedSuperclassName(Descendant))as Class).foo();
trace((getDefinitionByName(getQualifiedSuperclassName(Descendant))as Class).id);
Where :
// trace (Descendant.id);
// if private : compile time Error.
// 1178: Attempted access of inaccessible property id through a reference with static type Class.
var d:Descendant;
trace((getDefinitionByName("Descendant") as Class).id);
// output undefined if private : the value if public. But don't throw compile time Error.
(getDefinitionByName("Descendant") as Class).foo();
// Call static foo() from Descendant. // Throw a compile time Error if method is private
// trace (Superclass.id);
// if private : compile time Error.
// 1178: Attempted access of inaccessible property id through a reference with static type Class.
var s:Superclass;
trace((getDefinitionByName("Superclass") as Class).id);
// output undefined if private : the value if public. But don't throw compile time Error.
(getDefinitionByName("Superclass") as Class).foo();
// Call static foo() from Superclass. // Throw a compile time Error if method is private

Array.filter to dynamically test values

this is from Adobe docs:
package {
import flash.display.Sprite;
public class Array_filter extends Sprite {
public function Array_filter() {
var employees:Array = new Array();
employees.push({name:"Employee 1", manager:false});
employees.push({name:"Employee 2", manager:true});
employees.push({name:"Employee 3", manager:false});
trace("Employees:");
employees.forEach(traceEmployee);
var managers:Array = employees.filter(isManager);
trace("Managers:");
managers.forEach(traceEmployee);
}
private function isManager(element:*, index:int, arr:Array):Boolean {
return (element.manager == true);
}
private function traceEmployee(element:*, index:int, arr:Array):void {
trace("\t" + element.name + ((element.manager) ? " (manager)" : ""));
}
}
}
The problem is the Array class filter method. It works this way: you pass a function as an argument of filter and an array is returned based on the function you pass. The problem is that it seems you can't add any other parameter. So, if you must create (for example inside a for loop) 4 arrays from the same array and you want to use the same function, you can only test against a property of the class you must previously set to the value you want to test.
Is there any other way to add that parameter?
When filtering by a variable object properties in an array, I wrapped the filtering into another function:
protected function FilterByProperty(input_array:Array, extra_testing:Object):Array
{
function FilterFunction(element:Object, index:int, array:Array):Boolean
{
return element.property == extra_testing; // Arbitrary test
}
return input_array.filter(FilterFunction);
}
var filtered_array:Array = FilterByProperty(unfiltered_array, test_property);
You can use second parameter of filter() method to pass data to filter function. It will be avaliable as "this" variable. To do that first parameter must be a closure, not a class method.
var array:Array = [...];
var params:Object = {"param1": value1, "param2": value2};
var filterFunction:Function = function(item:*, index:int, array:Array):Boolean {
var param1 = this["param1"];
var param2 = this["param2"];
};
array.filter(filterFunction, params);
You want to use something like Delegates or function binding, or closures. Depending on your coding and terminology preferences. The idea behind all of them is that you create a dynamic function wrapper for the core "filter" function. That wrapper will have access to extra parameters that you pass. So, the first time you call it, you might go:
a.filter(Delegate.create(myFunc, param1));
and the next time:
a.filter(Delegate.create(myFunc, param2));
and you function would have something like this:
private function myFunc(item:*, index:Number, a:Array, param:Object=null):Boolean{}
A quick an dirty method is to just pass an inline function like this:
a.filter(
function(item:*, index:Number, a:Array):Boolean {
return myFunc(item,index,a,param1);
}
);
where param1 is passed using the closure created by the function definition.

Trying to understand the AsyncToken in Flex/Actionscript

I am trying to understand the way the AsyncToken works in actionscript. How can I call a remote service and ensure that a specific parameter is available in the result or fault event functions? I think it is the async functionality I want to use.
The following code will hopefully explain what I am trying to do. Feel free to modify the code block as your explanation.
Thanks.
public function testSerivceCall(data:Object, callBackCommand:String):void
{
// Assume callBackCommand == "FOO";
// How can I pass in callBackCommand as a parameter to the result or fault events?
// How do I create an async token here?
var remoteObject:RemoteObject;
remoteObject = new RemoteObject();
remoteObject.destination = "zend";
remoteObject.source = "MyService";
remoteObject.endpoint = "http://example.com/service";
remoteObject.test.addEventListener(ResultEvent.RESULT, _handleTestResult);
remoteObject.test.addEventListener(FaultEvent.FAULT, _handleTestFault);
remoteObject.test(data);
}
private function _handleTestResult( event:ResultEvent ) : void
{
// How do I get the async token value?
// How can I get the value of callBackCommand in this code block?
if (callBackCommand == "FOO")
{
// do something related to "FOO"
}
else
{
// do something else with the result event
}
}
private function _handleTestFault( event:FaultEvent ) : void
{
// How do I get the async token value?
// How can I get the value of callBackCommand in this code block?
}
An edit to make this question more clear:
Assume I make the following method call somewhere in my code:
testSerivceCall(personObject, "LoginCommand");
How do I get access to the actual string "LoginCommand" inside the _handleTestResult function block?
The reason I want to do this is because I want to dynamically call back certain functions and hand off the result data to specific commands that I know ahead of time when I am making the service call.
I am just having a time grokking the AsyncToken syntax and functionality.
I did not even need closures. I added a class as below which I called externally.
The call was like this:
public class MyClass
{
...
var adminServerRO:AdminServerRO = new AdminServerRO();
adminServerRO.testSerivceCall("FOO",cptyId);
}
public class AdminServerRO
{
private function extResult( event:ResultEvent, token:Object ) : void
{
//the token is now accessed from the paremeter
var tmp:String = "in here";
}
private function extFault( event:FaultEvent ) : void
{
var tmp:String = "in here";
}
public function testSerivceCall(callBackCommand:String, cptyId:String):void
{
var remoteObject:RemoteObject = new RemoteObject();
remoteObject.destination = "adminServer";
var token:AsyncToken = remoteObject.getCounterpartyLimitMonitorItemNode(cptyId);
token.addResponder(new AsyncResponder(extResult,extFault,cptyId));
}
}
While the accepted answer will accomplish what the original submitter wants it does not actually answer the question which was asked. An AsyncToken is created as a result of a remote method call and is accessible from the ResultEvent. Since AsyncToken is a dynamic class you can add whatever property to it that you want. The code below should demonstrate this:
public function testSerivceCall(data:Object, callBackCommand:String):void
{
var remoteObject:RemoteObject;
remoteObject = new RemoteObject();
remoteObject.destination = "zend";
remoteObject.source = "MyService";
remoteObject.endpoint = "http://example.com/service";
remoteObject.test.addEventListener(ResultEvent.RESULT, _handleTestResult);
remoteObject.test.addEventListener(FaultEvent.FAULT, _handleTestFault);
var token:AsyncToken = remoteObject.test(data);
token.callBackCommand = callBackCommand;
}
private function _handleTestResult( event:ResultEvent ) : void
{
if (event.token.callBackCommand == "FOO")
{
// do something related to "FOO"
}
else
{
// do something else with the result event
}
}
private function _handleTestFault( event:FaultEvent ) : void
{
//event.token.callBackCommand should be populated here too
}
If you want to access the properties used during the remote call (parameters to the call and/or AsycToken), you can make use of closures. Just define the result event handler inside the calling method as a closure. It can then access any variable in the calling function.
public function testSerivceCall(data:Object, callBackCommand:String):void
{
var _handleTestResult:Function = function( event:ResultEvent ) : void
{
// token is visible here now
if (callBackCommand == "FOO")
{
// do something related to "FOO"
}
else
{
// do something else with the result event
}
}
var remoteObject:RemoteObject;
remoteObject = new RemoteObject();
remoteObject.destination = "zend";
remoteObject.source = "MyService";
remoteObject.endpoint = "http://example.com/service";
remoteObject.test.addEventListener(ResultEvent.RESULT, _handleTestResult);
remoteObject.test.addEventListener(FaultEvent.FAULT, _handleTestFault);
var token = remoteObject.test(data);
}
If I'm reading your question correctly, you're trying to figure out how to access the actual data returned by the ResultEvent ?
If so, assuming you've made the call correctly and you've gotten data back in a format you're expecting:
private function _handleTestResult( event:ResultEvent ) : void
{
// you get the result from the result property on the event object
// edit: assuming the class Person exists with a property called name
// which has the value "John"
var person : Person = event.result as Person;
if (person.name == "John")
{
Alert.show("John: " + person.name);
}
else
{
Alert.show("Not John: " + person.name);
}
}
private function _handleTestFault( event:FaultEvent ) : void
{
// Maybe you know the type of the returned fault
var expectedFault : Object = event.fault as MyPredefinedType
if (expectedFault.myPredefinedTypesPredefinedMethod() == "BAR")
{
// something here
}
}
The ResultEvent has a property called result which will hold an instance of the object returned by the result (it might be the output of an XML file if using a web service, or a serialized object if using AMF, for example). This is what you want to access. Similarly, FaultEvent has a fault property that returns the fault information.
Edit: Changed code in _handleTestResult() in response to Gordon Potter's comment.