I have actionscript file with a binding {someBinding}...
The Main.mxml is where all the action happens. If I set {someBinding} in the "text" of a label component I will have a number.
I have another form.mxml file. Where I want that binding to be in, but it can't find such binding.
I need to have that {someBinding} in that other mxml, the same way as in the Main.mxml
Thanks, Yan
You can't a value in one component (or File) to a value in another component (or file) in the way you seem to be asking. You'll have to expose those related values as properties and set the values.
This type of approach should work:
First add a property to component 2 and make it Bindable. Do this in a Script block, like this:
[Bindable] public var hBoxWidth : int;
Then bind it to something in your MXML of the same component, like this:
<mx:HBox width="{this.hBoxWidth}" />
Now some component will contain this one:
<mx:HBox>
<myCustomComp:customHBox hBoxWidth={this.othervalue} />
</mx:Hbox>
So, when the othervalue changes it will change the hBoxWidth value on the customHBox component which will in turn change the width property on the HBox inside of customHBox.
Does that make sense?
You can create the binding but you have to use ActionScript and you need a reference to the form.mxml file in the main.mxml (or visa versa).
This should give you an ideal of how it might work. Take a look at the syntax for the BindingUtils. bindProperty method. The use of BindingUtils code would be within main.mxml.
BindingUtils.bindProperty(otherForm.someOtherTextComponent, "text", this.someTextComponent, "text");
Related
Hi, I have been working on a Flex Mobile application using Flash Builder 4.6.
I have 2 mxml 'views' in my project. In one mxml file, i have a function that grabs xml data.
In my other mxml file, I have a refresh button that when depressed is suppsosed to call the function in the first mxml file in order to once again grab the xml data.
I dont know how to call that function from outside the mxml file it is housed in.
I appreciate any help given. Thank you!
[UPDATE #2]*
I thought I should share some more details about my issue.
It is a reddit client mobile app. It fetches the feeds, etc.
In my main view called RedditReaderHomeView.mxml, I am using a splitViewNavigator spark component to house two other views like so:
RedditReaderHomeView.mxml
<s:SplitViewNavigator width="100%" height="100%" id="splitViewNavigator" autoHideFirstViewNavigator="true">
<s:ViewNavigator id="redditList" firstView="views.subredditList" width="300" height="100%"/>
<s:ViewNavigator id="redditFeed" firstView="views.redditFeed" width="100%" height="100%">
<s:actionContent.landscape>
<s:Button id="refreshButtonlLandscape" icon="#Embed('assets/refresh160.png')" click="refreshRSS()" />
</s:actionContent.landscape>
<s:actionContent.portrait>
<s:Button id="refreshButton" icon="#Embed('assets/refresh160.png')" />
<s:Button id="navigatorButton" label="Search" click="splitViewNavigator.showFirstViewNavigatorInPopUp(navigatorButton)" />
</s:actionContent.portrait>
</s:ViewNavigator>
</s:SplitViewNavigator>
As you can see in the code above, in my main view I have a button with the id "refreshButton." When I click this button, I want the reddit data to refresh. In other words I want to call a function to refresh the data, that is housed in the view, 'redditFeed'.
This is the function which is in a separate view named 'redditFeed.mxml', that I want to call using the refresh button in the main view shown above.
redditFeed.mxml
protected function myList_creationCompleteHandler(url:String):void
{
getRedditFeedResult.token = redditFeedGrabber.getRedditFeed(url);
getRedditFeedResult.addEventListener(ResultEvent.RESULT,busyOff);
}
I hope this helped clear out confusion as to what I was trying to do. Im assuming that the solution is quite simple, but alas, I am a novice programmer and new to Flex, so Im learning the ropes. Any help is appreciated. Thank you!
IF you have an instance of the view, then just do:
myViewInstance.myPublicFunction();
In MXML, the id element of the MXML tag is used to reference the view in ActionScript. Since you didnt' describe your architecture; it is unclear how one view can call the other.
If the view that needs to trigger the call is a parent of the view that has the function to make the call, then you could use the approach described above.
If the view that need to trigger the call is a child of the view that has the function to make the call, then you should dispatch an event from the "child" which the parent can listen to. In the event handler you would trigger the call.
If the view that needs to trigger and the view that has the function to make the call are both children of the same parent; then you should dispatch an event from the "Trigger" view, listen for it in the parent, and then use that event listener to make the call (Using similar code to what I explained above).
If you have a more complicated architecture of these two views; then you should look into some method to encapsulate the "remote call" functionality, such as into a service class. Many frameworks offer approaches to share that service class and/or results across multiple classes. ( MXML Files are classes).
There are two ways you can do this without getting into bad architecture by having the child view explicitly know about its parent:
Your child view can generate an event, which the parent is listening for. The parent will then call the function
The child view can have a public property of type Function. The parent view passes a reference to that function by setting the variable. The child view then calls the function (after checking to make sure it is not null).
I hava a problem with flashbuilder:
I have a list with an itemrenderer that renders an image that (should be) draggable.
the rendered image refers to a function that is declared in an actionscript file: dragDrop.as in the folder AS.
the list:
<s:List id="imageList" width="139" height="438"
dataProvider="{xmlListColl}"
itemRenderer="itemRenderer.ImageRenderer"
dragEnabled="true">
</s:List>
the itemrenderer renders this image and refers to the function doDrag:
<mx:Image width="100" height="70" maintainAspectRatio="true"
MouseDownEffect="AS.dragDrop.doDrag(event)"
source="{data.#thumbnailImage}"/>
the function in dragDrop.as:
public function doDrag(event:MouseEvent):void
{
var img:mx.controls.Image = event.currentTarget as mx.controls.Image;
var dragImg:mx.controls.Image = new mx.controls.Image();
dragImg.source = img.source;
var dsource:DragSource = new DragSource();
dsource.addData(img, 'img');
DragManager.doDrag(img, dsource, event, dragImg);
}
but it seems the function is never called...
also parentdocument and outerdocument don't seem to work (if i put the function in the document where the itemrenderer is called)
Please Help!
There's a few issues here, but ultimately, you're not seeing a reference to that method, which means your dragDrop.as file is not including.
Here are a few suggestions:
Replace MouseDownEffect with mouseDown. Instead of causing an effect to occur, you're now listening for the "MouseEvent.MOUSE_DOWN" event to fire. Differences between effects and responding to events are described here and, to quote, "Behaviors let you add animation and motion to your application when some user or programmatic action occurs, where a behavior is a combination of a trigger paired with an effect. A trigger is an action, such as a mouse click on a component ... An effect is a visible or audible change to the target component that occurs over a period of time, measured in milliseconds."
Make sure you're including your dragDrop.as file. Flex 3 vs. Flex 4 handle script tags differently. If you're not including or importing your code, then of course it won't fire.
include vs import is a good question. You can "include" code that's a definition of methods, instances, constants, etc. But you would "import" defined classes for use. Since your method is a public function, does it live within a class? Or is it meant to just live in the script file, in which case you should remove the accessor "public"
If you're looking to implement Drag-and-Drop, I highly recommend NOT re-inventing the wheel and checking out what Adobe has already implemented for components, including dragEnabled='true' and dragMoveEnabled='true'. Check them out here: http://livedocs.adobe.com/flex/3/html/help.html?content=dragdrop_4.html
http://livedocs.adobe.com/flex/3/html/help.html?content=dragdrop_1.html
Here is an example of a Flex 3 script tag:
<mx:Script source="AS/dragDrop.as"/>
Here is an example of a Flex 4 script tag:
<fx:Script source="AS/dragDrop.as"/>
This is an link to the documentation on how to include directly into a <fx:Script> tag the code you'd like: http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf61c8a-7ff4.html
I've done a data-binding following a tutorial on the web:
<mx:Script><![CDATA[
public static const selectedChild:Boolean = true;
]]></mx:Script>
<mx:Button label="{resourceManager.getString('resources', 'button.startLab')}"
id="nextStepButton" enabled="{selectedChild}" />
My question is how we can accsess this bindable variable from another mxml file?
Thanks.
As already stated, you can access selectedChild from another class using ClassName.selectedChild, where ClassName is the name of your mxml file.
Please note couple of things though:
selectedChild is not declared as bindable. You should use the [Bindable] metadata tag to make a variable declared in actionscript to be bindable.
selectedChild is declared as const, meaning its value cannot change in between. Thus, you need not use data binding on that field - just assign the value to the enabled field of the button once it is created.
It is declared as static - which means there is only one instance of it for the whole class. If you have another component of the same type, it'll have the same value as this one - as you have declared it as a constant, that might be the behavior you want, but in that case, you need not use data binding.
yes you can
ClassName.variable_name will give you the value
I have a component that has a sub-component they both use a shared variable from the model. The shared variable needs to be set by the parent component before it can be used by the child component. I did like this in the parent component:
<mx:Canvas
xmlns:mx="library://ns.adobe.com/flex/mx"
...
creationComplete="group1_completeHandler(event)" >
....
protected function group1_activateHandler(event:Event):void {
model.myVariable = something;
}
....
<components:myCustomComponent>
...
<components:myCustomComponent>
...
</mx:Canvas>
But for some reason when the code inside myCustomComponent tries to use myVariable for the first time I get a "null" object error. This means I guess that the child component gets rendered before the group1_activateHandler gets called and consequently myVariable gets set.
What should I do to ensure that the parent container initializes the variable before the child component gets created?
You should set the variable in initialize() instead of creationComplete() which is invoked after all components are created and rendered.
I recommend you factor the variable out of the components into a separate code which you can instantiate separately from the actual components. Then use binding to bind your components to this class. This will give you a much cleaner design.
I would like to let the data provided to a DataGrid decide how best it should be rendered (that is, let the data carry with it an object which will do the rendering).
For example, by creating a "Renderable" interface, which has a 'renderer:IFactory' property, then used as below:
<mx:DataGrid x="0" y="0" width="100%" dataProvider="{myDataProvider}">
<mx:columns>
<mx:DataGridColumn headerText="Task" width="100"
itemRenderer="{(data as Renderable).renderer}"/>
</mx:columns>
</mx:DataGrid>
But to do this, Renderable has to extend IEventDispatcher, which seems like a little much...
I've also tried using:
itemRenderer="{(data as Renderable).getRenderer()}"
Which does nothing (in fact, the getRenderer method never gets called).
Is there a better way to do this? Am I doing something fundamentally wrong?
Thanks!
I could be wrong but I think the "data" property you're referencing in the code sample above is the "data" for the top-level Container in your view and not for that particular row of the DataGrid. A few other approaches come to mind:
Implement a single item renderer class that examines the data being passed to it and utilizes the proper item renderer for the type of data supplied.
Implement a function in the view of your DataGrid that examines your dataProvider and returns the proper item renderer class; call this inside the DataGridColumn.itemRenderer property using a binding expression.
Implement an subclass of DataGridColumn that has the logic baked into it to set the correct itemRenderer.
I would actually recommend against mixing "renderer data" that is View-specific with data from your Model. Unless you wrap the core model data with an object that exposes it along with the renderer (what some people call a ViewModel).
Make getRenderer a [Bindable] property