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.
Related
I have a custom component with an input property as follows:
export class MyComponent{
#Input() value:number;
}
So that I can plop one on a parent component:
<my-component [(value)]="someValueAtParentComponent"></my-component>
Note that I did not provide #Component decorator and the class for the parent component because I don't think those are relevant.
Now, things happen internally in MyComponent that can change the value of value.
From inside MyComponent's template, I display {{value}}, and it displays the correct value throughout its lifetime.
From the parent component's template, I display {{someValueAtParentComponent}}, but it doesn't update with MyComponent's value. I thought [(value)] will automatically do the job, but I guess not.
I don't want to create an #Output event on MyComponent for the parent component to handle the event where it would set someValueAtParentComponent explicitly.
I believe Angular wants to emit an event for a parent component to handle, but that seems very tedious. Is there something we can do in our own components so that we may use the syntactic sugar [(value)] instead of [value]="..." (onValueChanged)="onValueChangedHandler($event)"?
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 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");
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 need to create an extension of a Flex component, which (obviously) means that the new component should be able to be used whenever the parent is used. But I don't see the way to do it, Flex offers two ways of extending a component, by defining an AS class extending the parent or by creating an MXML file that uses the parent component as a root element; in both cases I can’t use nested elements to configure the child as I do for parent.
E. G.
package components {
import mx.controls.AdvancedDataGrid;
public class FixedDataGrid extends AdvancedDataGrid {
public function FixedDataGrid() {
super();
}
}
}
This is Valid MXML
<mx:AdvancedDataGrid>
...
<mx:columns>
...
This is NOT Valid MXML
<mx:FixedDataGrid>
...
<mx:columns>
...
It doesn't seem like a valid is-a relation.
Your FixedDataGrid doesn't exist in the same namespace as the mx components...
you need to specify the correct namespace for it to be legal.
<mx:Application xmlns:components="components.*" ... >
<components:FixedDataGrid>
....
You are doing the mxml equivalent of declaring your component in the components package then complaining you can't reference it as mx.controls.FixedDataGrid
When defining properties via a new MXMLtag, the property must contain be specified in the same namespace as the tag.
So you could do something like this:
<myComp:FixedDataGrid columns="SomeArray">
Without any issues. If you use the MXML tag syntax to define the columns array property, you need to do this:
<myComp:FixedDataGrid >
<myComp:columns>
<mx:AdvancedDataGridColumn />
<mx:AdvancedDataGridColumn />
</myComp:columns>
</myComp:FixedDataGrid >
columns is a property on the AdvancedDataGrid, and therefore must be defined in the same namespace as your custom extension to the AdvancedDataGrid. AdvancedDataGridColumn is a different component, so it would be definined in the mx namespace.
As mentioned by an alternate poster, the 'myComp' namespace must be defined in the top level component of your application. Most of the time Flash Builder will add the namespace automatically for you.