static/private child component in mxml? - apache-flex

Are there any way to declare a child component in mxml which is private/protected or even static?
Sure we can do this inside a script tag, but are there any other way?

Ashier suggests using the "Exclude" metadata tag, but Maskit offers its limitations and suggests alternative solutions:
http://blog.ashier.com/2008/03/25/hiding-properties-in-flex-components/
http://smaskit.blogspot.com/2008/07/making-mxml-subcomponent-private.html

In the strict meaning of these terms, no you can't do that using mxml. The second link posted by Luis contains some workarounds for private/protected behavior.

I found a solution to the static question. I wanted a quick memo pad that could be accessed anywhere in the mobile app, without one instance overwriting edits left open in a different screen.
I created a memo pad mxml control, and then placed it inside a declarations section in the top level application mxml. In each view that I wanted the memo to appear in, I added:
import mx.core.FlexGlobals;
import components.QuickMemo;
private var memo:QuickMemo;
In the view creation complete:
memo = FlexGlobals.topLevelApplication.memo;
In the viewActivation code, I added:
memo.visible = false;
addElement(memo);
In the viewDeactivation code, I included:
removeElement(memo);
The net effect is that only one instance of the memo exists at any time, and that one instance opens in whatever state it existed in the last view it appeared in.

Related

Flex: PopUpManager giving "...null object reference" error

I have a main application calling several ViewStack states, each with popup windows. If I don't open any popup windows, I can move between states fine. If I open a popup window then try to change the state using currentState=... I get the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at spark.components::Scroller/focusInHandler()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\Scroller.as:2139]
at flash.display::Stage/set focus()
at mx.core::UIComponent/setFocus() [E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:9905]
...
I see others having the same problem, for example here:
http://forums.adobe.com/thread/1031531
http://forums.adobe.com/message/2767130
http://forums.adobe.com/message/3448443
http://forums.adobe.com/thread/655749?tstart=-1
http://forums.adobe.com/thread/801149
http://flex4examples.wordpress.com/2011/05/05/skinnabletextbase-focusmanager-runtime-error-popup/
http://bugs.adobe.com/jira/browse/SDK-32036?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel
But I haven't figured out how to implement the recommended solution. It sounds like I should just include:
import mx.managers.PopUpManager; PopUpManager;
inside my main application and it should work, but it doesn't work for me.
My application has each view state in a different file, each defined using <views:View>. Also, all of the popups are separate files defined as <s:TitleWindow>. Each file includes this line:
import mx.managers.PopUpManager;
I wonder if this means each file is using a different popup manager(?), when it's a singleton and only one should be used for the whole app (how to set that up?).
The code I use to call a popup is:
var _popupName:MyTitleWindowFileName = MyTitleWindowFileName(
PopUpManager.createPopUp(this, MyTitleWindowFileName, true));
_popupName.addEventListener(MyAppController.CLOSE_POPUP,onClosePopUp);
PopUpManager.centerPopUp(_popupName); // call popup
Note that when the main application (the one defined as <s:Application>) runs, the ViewStack states have not been loaded yet (since they get loaded when they are used the first time). Not sure if that has any cause/effect here.
I've tried to follow Adobe's example code in the "Passing data to and from a Spark pop-up window" section here:
http://help.adobe.com/en_US/flex/using/WS6c678f7b363d5da52e8f1ca1124a0430dcf-8000.html#WS6c678f7b363d5da52e8f1ca1124a0430dcf-7ffe
Any ideas much appreciated.
Based on your comments, it seems like the error occurs because the focus remains in the popup. I would expect the PopUpManager and FocusManager classes to handle this better.
One thing I can think of is that the FocusManager may be trying to handle this. But since the state changes, the item that originally had focus (in the view stack child, before the pop up was opened) may no longer be there when the view state changes. Just a hunch, w/out seeing your code.
Here's some things you can do to either work around the problem (or better) further debug it to understand what is happening:
Use FocusManager.setFocus() to move the focus back to an object in the view stack child before closing the pop up
Use FocusManager.getFocus() to debug and see where it thinks the focus is at various stages (before opening popup, before/after changing state, and before/after closing pop up).
It appears this is the situation I'm experiencing:
Adobe Air: scroller throws error when changes focus between different applications
It's an Adobe bug. Solution from Adobe is:
This bug is easily fixed by changing Scroller to do a null pointer check on focusManager before using it.
which is what the first link above attempts to do.
Another link: http://forums.adobe.com/message/3812805

Is there a reliable way to "refresh" a component?

By "refresh" I am completely disposing it and then introducing it again in the application (without closing the application itself - that is). Other than than I think the question is self-explanatory.
Example:
Say I have a component named myComponent. I add that component to the application using MXMl in the standard way <components:myComponent id="myID" />. Say that when a user clicks a button (the button may be in another state), the component with id myID should be garbage-collected and a new instance of it added to the application.
How do I go about doing that? If there are multiple solutions which one is the optimal performance-wise?
I am new to Flash and Flex so excuse me if any incorrect terminology were used.
Remove all the event listeners from the old component; whatever they are using the removeEventListener method:
myButton.removeEventListener(someEvent, someEventHandlerMethod);
Then all variables that refer to the component should be set to null. If created in an MXML file, like this:
<s:Button id="myButton" />
Then all you have to do is set that value to null:
myButton = null;
Once there are no references to the component, it can safely become eligible for garbage collection.
If you want to re-created, then just re-created it. You'll have to re-create it in ActionScript, but the code isn't hard. Conceptually something like this:
myButton = new myButton();
myButton.properties = propertyValues;
myButton.addEventListener(someEvent, someEventHandlerMethod);
parentContainer.addChildAt(myButton, whateverPositionYouWantToADdTheComponentAt);
I'm not sure I see the benefit of doing this. I suspect it'll be much more efficient to tweak the existing button instance in the way you need to as opposed to destroying it and trying to replace it with the exact same thing.

address a Flex checkbox in a component

I have a checkbox in a component:
<s:CheckBox id="myCB_1" />
In my main.mxml I need to test for the state of the checkbox. I originally had all my code in main.mxml, but it was getting really long, and I thought that it was better practice to break my code into components. Also, I have other projects where the same concept will apply, so I really want to figure this out.
I have the following function :
private function checkAlarms(currentTime:Date):void
{
if (!breakfastAlarmSounded)
{
if ((currentTime.hours > breakfastTime.hours) || ((currentTime.hours == breakfastTime.hours) && (currentTime.minutes >= breakfastTime.minutes)))
{
if (myCB_1.selected)
{
playBreakfastAudioAlarm();
}
if (myCB_2.selected)
{
playBreakfastVisualAlarm();
}
breakfastAlarmSounded = true;
}
}
...
simply addressing the component, as in:
myComponent.myCB_1.selected
doesn't work. Someone mentioned that I need to create a variable in my component that refers to the id (myCB_1) of checkbox, but I don't really understand or know how to do that, and they didn't elaborate.
How do I test for the status of the CheckBox "myCB_1" in the component from within my main.mxml?
many thanks,
Mark
(newbie)
With very little information, I'm going to suspect you originally had the CheckBox included in main.mxml and moved it to a custom component. If so, you need to address the CheckBox's ID via the custom component's ID. Something like this (from main.mxml):
if(yourComponentsID.myCB_1.selected)
{
...
}
If this isn't the case, please edit your post and give us more detail.
EDIT
You said you created a new custom component and moved the CheckBox into it. Great, that's a helpful start :) When you included your new component in your main.mxml file, it should look something like this:
<component:YourNewComponent />
Of course, however you named it (and whichever namespace is used to reference it) will be different from my example, but the principle should still apply. In main.mxml, you need to give your custom component a unique ID string so you can reference it within main:
<component:YourNewComponent id="myComponent" />
From here on, you should be able to reference the component, and any public elements within it: myComponent.myCB_1.
It would be useful to provide more details about the context in which you're using this script. Nonetheless I'm going to throw out some information that may help.
In order for the script to access the component, it has to be within the scope of the component. Usually that means one of the following:
You have a <script> tag in the MXML, with code in it that references components within the same MXML file.
You have a <script source='external.as'/> tag in the MXML, where external.as is referencing components in the MXML file.
You are creating the component in your script and you have a definition for the component within ActionScript (ex. var myCB_1:CheckBox; is within the class definition).
If the script and the component aren't within the same scope then they can't see one another.
You need to refer to the checkbox through the component. Lets say that you use your component in your main like this:
<local:MyComponent id="myComponent" />
In your script, you want to refer to it:
if(myComponent.myCB_1.selected) { // do something }
Strangely enough, it works. I was getting a getting an 1119 error (Description 1119: Access of possibly undefined property myCB_1 through a reference with static type Class.) when I refer to the component with dot notation (myComponent.myCB_1.selected) and an 1120 error (Description 1120: Access of undefined property myCB_1) when not addressing it via myComponent.
With these errors I never thought to try running the thing. Long story short - it runs with or without addressing the component (???) go figure!
thanks for all the input and would love to hear any other comments.
MCE

Accessing children elements in a SWC

Does anyone know if its possible to access children elements in a SWC? I have created some MC's and inside of some of these MC's I have some dynamic textFields. I export the content to a SWC and load it into my Flex project. No problem loading it or accessing the parent elements, they display fine. But I want to access the textfields nestes in the MC's and modify the text. When I debug the app, I can see the textfields as child elements. It's typed as a TextField and the Instance Name is the same as input in the Flash IDE but I cannot access it. When Flex compiles it throws an error saying it doesn't recognize the method. I've tried to insert actionscript on the timeline, linked external classes and nothing can be accessed. Does anyone know of a way to do this?
It's hard to say since you're not showing your code that fails, but I suspect you're doing:
import myswc.*;
myswc.Symbol1.myTextField.text = "Foo"
instead of
var clip:MovieClip = new myswc.Symbol1();
clip.myTextField.text = "Foo"
I just bumped into this as well, and am curious as to why you're suggesting he's NOT using the instance name since myTextField is obviously an instance name for the TextField he's using....

Flex component access other component

I have 2 components for example (editor.mxml using mx:windows), when I click an edit button, I want to get the current value from the other component's datafield? (datagrid.mxml using mx:window)
I do know how to access the main MXML's datagrid by parentDocument or Application.application method, but stumped block if I want to access other way as mentioned above. Keep the code as simple as possible.
You could either do dependency injection, that is, give component A a reference to component B so that they can communicate directly (example of tighter coupling,) or have both components communicate through a common mediator using events (example of more loose coupling.)
Both of those options would be implemented wherever it is that you're creating those components (A and B in this example) and adding them to the display list.
This might be more complicated than it deserves, and it smacks of Pattern-Fever, but you could use a mediator class that listens for the CLICK event from the button and knows enough about the other component to query its property. It could even transmit that data using a custom event, which the button listens for.
While this involves three classes instead of two, it often turns out to be easier to have two components that focus on looking good and one that worries about coordination.
Cheers
Try this:
FlexGlobals.topLevelApplication
This points Your root. From the root You can grab every element You want.
You can also add an id to the custom component like this,
<custom:Editor id="myCustomComponent">
</Editor:AddressForm>
and
access your datagrid's value like this,
var data:ArrayCollection = myCustomComponent.DatagridID.dataProvider;

Resources