how to pass argument to Marionette.CompositeView - html

how to pass a values dynamically to an Marionette.CompositeView during run time? like in java we create a method like the following
package com.test.poc;
public class SampleMethod {
public int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
SampleMethod method = new SampleMethod();
int firstValue = 90, secondValue = 90;
System.out.println("add : " + method.add(firstValue, secondValue));
}
}
the above is the simple java code anybody can understand like the above how to create and pass arguments to Marionette.CompositeView and work on them?
Best Regards

at the moment you instanciate a view, you can pass whatever arguments you want. normally you pass the model and the collection to be rendered in the compositeView, but you can pass more data if you need.
var MyCompositeView = Backbone.Mationette.CompositeView.extend({
initialize : function (options){
this.dataValue = options.dataValue1;
this.helperObject = options.helperObject;
this.useValues();
},
useValues: function () {
console.log(this.dataValue);
}
});
var helperObject = {
value3 : "I have a value",
value4 : "I dont!"
}; /// a js object literal
var myModel = new MyModel();
var myCollection = new MyCollection();
var myCompositeView = new MyCompositeView({model:myModel,
collection:myCollection,
helperObject:helperObject,
dataValue1:"Hi there"});
notice that Im passing 4 values in the at the time to intanciate the view, and Im reading just two of them, the model and the collection will be handled by marionette, but the other two you can read them in your initialize function.
hope that helps.

Related

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.

Mapping parsed json to java object not working-LibGdx

First time I am using json parsing in my LibGDX project and I am not able to get the parsed results properly.
Here I want to manage the obstacles with properties;name,direction,gap and speed.
I have a json file like this:
"obstacles": [
{"name":"eagle","dir":"up","gap":"100","speed":"0"},
{"name":"bigbird","dir":"up","gap":"200","speed":"0"},
{"name":"elephant","dir":"middle","gap":"300","speed":"0"},
{"name":"tiger","dir":"middle","gap":"400","speed":"0"},
{"name":"bear","dir":"down","gap":"500","speed":"0"},
],
and I am reading the array like this:
public class ReadJson {
static int levelNum = 0;
public ReadJson()
{
}
public static synchronized ArrayList<String> loadLevelJson(int levelno, String name) {
ArrayList obs = new ArrayList<String>();
JsonValue jsonValue = new JsonReader().parse(Gdx.files.internal("levels/level1.json"));
JsonValue objList = jsonValue.get(name);
System.out.println("name:" + objList);
if (name.equals("obstacles")) {
Constants.OBS_COUNT = 0;
for (JsonValue values : objList.iterator()) // iterator() returns a
// list of children
{
obs.add(values.getString("dir"));
Constants.OBS_POSITION[obs.size() - 1] = Integer.parseInt(values.getString("gap"));
Constants.OBS_NAME[obs.size() - 1] = values.getString("name");
Constants.OBS_SPEED[obs.size() - 1] = Integer.parseInt(values.getString("speed"));
Constants.OBS_COUNT++;
}
}
else if (.....)) {
//code
}
return obs;
}
}
Arrays are defined in constant class like this:
public static int OBS_COUNT =20;
public static int[] OBS_POSITION= new int[50];
public static String[] OBS_NAME= new String[50];
public static int[] OBS_SPEED= new int[50];
public static ArrayList<String> obsArray;
I want to map the parsed json to the object bear.For that,I did like this:
private ReadJson readJson;
public ObsObjectFactory() {
readJson = new ReadJson();
readJson.loadLevelJson(1,"obstacles");
Constants.obsArray=readJson.loadLevelJson(1,"obstacles");
}
public Bear createBear() {
Bear bear = new Bear();
bear.setName(Constants.OBS_NAME[Constants.OBS_COUNT]);
bear.setDirection(Constants.obsArray.get(Constants.OBS_COUNT));
bear.setSpeed(Constants.OBS_SPEED[Constants.OBS_COUNT]);
bear.setGap(Constants.OBS_POSITION[Constants.OBS_COUNT]);
bear.setPosition(Constants.EAGLE_X,Constants.EAGLE_Y);
bear.setSize(Constants.BEAR_WIDTH,Constants.BEAR_HEIGHT);
return bear;
}
}
But when I call this createBear()method and run this code,it is throwing IndexOutOfBoundsException in this line:
bear.setDirection(Constants.obsArray.get(Constants.OBS_COUNT));
Parsed values are displaying properly in console.
What mistake I did here?
Your constants don't seem to be constants, as they can change. I found that odd, and as another aside, the code is quite confusing to follow. I'm not entirely sure what you're trying to achieve.
But the index error is likely caused by incrementing your constant (hint, not a constant then, is it?) Constants.OBS_COUNT++; in the readJson method. Given your json file, OBS_COUNT might end up being 5, so Constants.obsArray.get(Constants.OBS_COUNT) is failing as your array only has index positions 0 through 4.

Get AS3 instance method reference from Class object

class Foo {
public function bar():void { ... }
}
var clazz:Class = Foo;
// ...enter the function (no Foo literal here)
var fun:Function = clazz["bar"]; // PROBLEM: returns null
// later
fun.call(new Foo(), ...);
What is the correct way to do the above? The Java equivalent of what I want to do is:
Method m = Foo.class.getMethod("bar", ...);
m.invoke(new Foo(), ...);
Actual code (with workaround):
class SerClass {
public var className:String;
public var name:String;
private var ser:String = null;
private var unser:Function = null;
public function SerClass(clazz:Class):void {
var type:XML = describeType(clazz);
className = type.#name;
// determine name
name = type.factory.metadata.(#name=="CompactType").arg.(#key=="name").#value;
// find unserializer
var mdesc:XML = XML(type.method.metadata.(#name=="Unserialize")).parent();
if (mdesc is XML) {
unser = clazz[mdesc.#name];
}
// find serializer
var sdesc:XML = XML(type.factory.method.metadata.(#name=="Serialize")).parent();
if (sdesc is XML) {
ser = sdesc.#name;
}
}
public function serialize(obj:Object, ous:ByteArray):void {
if (ser == null) throw new Error(name + " is not serializable");
obj[ser](ous);
}
public function unserialize(ins:ByteArray):Object {
if (unser == null) throw new Error(name + " is not unserializable");
return unser.call(null, ins);
}
}
Here the function bar only exist when your class is instanciated :
var foo:Foo = new Foo()
var fun:Function = foo.bar // <-- here you can get the function from the new instance
if you want to access it directlty you have to make it static:
class Foo {
public static function bar():void{ ... }
}
now you can access your function from the class Foo:
var fun:Function = Foo.bar
or
var clazz:Class = Foo
var fun:Function = clazz["bar"]
I am not sure about what you are intending to do.
However AS3Commons, especially the reflect package have API's that let you work with methods, instances and properties of a class.
There are also API methods to create instances of certain class types on the fly and call their respective methods.
Cheers
It's not
fun.call(new Foo(), ...);
Use instead since no parameters are required for the function
fun.call(clazz);
The first parameter as specified by adobe docs.
An object that specifies the value of thisObject within the function body.
[EDIT]
Forgot to point out you have to instantiate a non-static class with the "new" keyword.
var clazz:Class = new Foo();
[EDIT2]
Ok I played around and think I got what you want.
base.as
package{
public class Base {
public function Base() {
trace('Base constructor')
}
public function someFunc( ){
trace('worked');
}
}
}
//called with
var b:Base = new Base( );// note I am not type casting to Class
var func:Function = b.someFunc;
func.call( );
My workaround is to store the function name instead of the Function object.
var fun:String = "bar";
// later...
new Foo()[fun](...);

ActionScript - Determine If Value is Class Constant

i'd like to throw an argument error if a particular function doesn't work without a passed value that also happens to be a public constant of the class containing the function.
is there anyway to determine if a class owns a public constant instead of having to iterate thru all of them?
something like this:
public static const HALIFAX:String = "halifax";
public static const MONTREAL:String = "montreal";
public static const TORONTO:String = "toronto";
private var cityProperty:String;
public function set city(value:String):void
{
if (!this.hasConstant(value))
throw new ArgumentError("set city value is not applicable.");
cityProperty = value;
}
public function get city():Strig
{
return cityProperty;
}
currently, for this functionality i have to write the city setter function like this:
public function set city(value:String):void
{
if (value != HALIFAX && value != MONTREAL && value != TORONTO)
throw new ArgumentError("set city value is not applicable.");
cityProperty = value;
}
is this the only way to accomplish this task?
Yes, if you use reflections:
private var type:Class;
private var description:XML;
private function hasConstant (str : String ) : Boolean
{
if (description == null)
{
type = getDefinitionByName (getQualifiedClassName (this)) as Class;
description = describeType (type);
}
for each ( var constant:XML in description.constant)
{
if (type[constant.#name] == str) return true;
}
return false;
}
Note that for this to work, all constants must always be String objects declared public static const.
I was looking for an answer to this question myself and found it annoying that hasOwnProperty() did not work for static properties. Turns out though, that if you cast your class to a Class object, it does work.
Here's an example:
public final class DisplayMode
{
public static const one: String = "one";
public static const two: String = "two";
public static const three: String = "three";
public static function isValid(aDisplayMode: String): Boolean {
return Class(DisplayMode).hasOwnProperty(aDisplayMode);
}
}
I owe this solution to jimmy5804 from this discussion, so hats off to him.
You should be able to use bracket notation to do this. For example:
var foo:Sprite = new Sprite();
foo.rotation = 20;
trace( foo["x"], foo["rotation"]); // traces "0 20"
or more specific to your case:
var bar:String = "rotation";
trace( foo[bar] ); // traces "20"
The only thing you have to look out for here, is that the bracket accessor will throw a ReferenceError if you ask for an object property that isn't there, such as:
trace ( foo["cat"] ); // throws ReferenceError
But it will not throw if you are asking for a static property:
trace ( Sprite["cat"] ); // traces "undefined"
So in your case you might try:
if ( this[value] == undefined ) {
throw new ArgumentError("set city value is not applicable.");
}
EDIT:
Sorry, I was confusing the const's names with their values.
For this to work on your problem you would have to make the String value the same as the const's name, so for example:
public static const HALIFAX:String = "HALIFAX";
then you could use the query as described above and it would give you the desired result.

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.