ComboBox visiblity in Flex - fails - apache-flex

I have setup a ComboBox named cmbCopyFrom and its visibility is based on the whether a item 'Pricing Zone' was selected from another ComboBox, cmbBoundary, and it sometimes doesn't make the cmbCopyFrom to be visible even though, Pricing zone was selected. Not sure what might be causing this. Any suggestions?
<s:ComboBox id="cmbBoundary" prompt="Select a Boundary"
labelFunction="codeLabel" />
<s:ComboBox id="cmbCopyFrom" prompt="Copy From" labelFunction="codeLabelKey"
dataProvider="{model.arrOfLOB}"
includeInLayout="{model.isCopyFromVisible}"
visible="{model.isCopyFromVisible}" />
cmbBoundary.addEventListener(IndexChangeEvent.CHANGE,boundarySelected);
protected function boundarySelected(evt:IndexChangeEvent):void {
trace("Index change event fired..."+this.cmbBoundary.selectedItem.name);
if (this.cmbBoundary.selectedItem && this.cmbBoundary.selectedItem.name == "Pricing Zones" ) {
model.isCopyFromVisible = true;
}
else {
model.isCopyFromVisible = false;
}
}

Related

Flex: Delete item from collection bound to datagrid and update the grid selected index

I have a datagrid with an xmlListCollection bound to it:
<mx:DataGrid id="dgCompetente" includeIn="Competente" x="10" y="66" width="547" height="468"
change="dgCompetente_changeHandler(event)" dataProvider="{colCompetente}"
editable="false">
<mx:columns>
<mx:DataGridColumn headerText="ID Competenţă" dataField="idCompetenta"/>
<mx:DataGridColumn headerText="Denumire Competenţă" dataField="denCompetenta"/>
<mx:DataGridColumn headerText="Competenţă Superioară" dataField="idCompSuperioara" labelFunction="labelFunctionCompetentaSuperioara"/>
</mx:columns>
</mx:DataGrid>
and a button to delete the currently selected item in the datagrid, which has this function assigned to the click event:
<s:Button id="btnDeleteCompetenta" includeIn="Competente" x="813" y="65" label="Stergere" click="deleteCompetenta()"/>
private function deleteCompetenta():void
{
try {
var position:int = dgCompetente.selectedIndex;
if (position >= 0) {
colCompetente.removeItemAt(position);
dgCompetente.selectedIndex = position;
}
clearEdit(fieldsCompetente);
saveCompetente();
} catch (error:Error) {
errorHandler.defaultErrorHandler(error);
}
}
I want the selectedIndex to remain the same. So, if I delete item 2, the next in the list should be selected. The problem is that if I delete item 2, item 3 will be selected and I have no idea why.
Can someone tell me what I'm missing?
Thank you!
It doesn't work selectedIndex don't update with the good value also in updateCompleteHandler
but with value-1 if force value+1, take value+2 and the selection escape from click, so it's exactly the same.
You're probably resetting the selectedIndex too early, before the DataGrid is updated, but it's hard to tell exactly since your code calls a bunch of functions. Try this
Add a "cached position" variable, like this:
protected var cachedPosition : int;
Then modify your deleteCompetenta method
private function deleteCompetenta():void
{
try {
cachedPosition = dgCompetente.selectedIndex;
if (position >= 0) {
colCompetente.removeItemAt(position);
// don't reset this here
// dgCompetente.selectedIndex = position;
}
clearEdit(fieldsCompetente);
saveCompetente();
} catch (error:Error) {
errorHandler.defaultErrorHandler(error);
}
}
Then add an updateCompleteHander to the DataGrid:
<mx:DataGrid id="dgCompetente" includeIn="Competente" x="10" y="66" width="547" height="468"
change="dgCompetente_changeHandler(event)" dataProvider="{colCompetente}"
editable="false" updateComplete="updateCompleteHandler(event)">
And reset the selectedIndex int he updateCompleteHandler:
protected function updateCompleteHandler(event:Event):void{
// reset here
dgCompetente.selectedIndex = cachedPosition;
}
Would that solve it?

changing "enabled" value of a button during runtime in flex

i want to make a button disabled if a datagrid is empty and it should be enabled when there is atleast 1 entry.the entries in the grid are made at runtime.I tried this
this is the button:
<mx:Button id="update" label="Update Contact" enabled="{isButtonEnabled()}"/>
and the function is defined as where dg_contact is the datagrid:
public function isButtonEnabled():Boolean
{
if(dg_contact.selectedIndex==-1)
{
return false;
}
else
{
return true;
}
}
where am i going wrong?
Your code doesn't work because isButtonEnabled() doesn't get called when selectedIndex changes. You can use BindingUtils to do that, but this can be done without BindingUtils
DataGrid can have items and yet have its selectedIndex equal to -1. If you're not bothered about if an item is selected or not, bind it to the length of DataGrid's dataProvider
<mx:Button id="update" label="Update Contact"
enabled="{dg_contact.dataProvider.length != 0}"/>
If you want button to be enabled only when something is selected, bind it to selectedIndex
<mx:Button id="update" label="Update Contact"
enabled="{dg_contact.selectedIndex != -1}"/>

Flex AS3: ComboBox set visible to false doesn't hide

I have a combobox in a view that receives information about application state changes, and then is supposed to show or hide it's children based on the whole application state.
It receives state change messages, it traces the correct values, it does what it's supposed to do, however, it just doesn't seem to work. Essentially, all it needs to do is hide a combobox during one state, and show it again during another state.
Here is the code:
public function updateState(event:* = null):void {
trace("Project Panel Updating State");
switch(ApplicationData.getSelf().currentState) {
case 'login':
this.visible = false;
break;
case 'grid':
this.visible = true;
listProjects.includeInLayout = false;
listProjects.visible = false;
trace("ListProjects: " + listProjects.visible);
listLang.visible = true;
break;
default:
break;
}
}
Here is the MXML:
<mx:HBox>
<mx:Button id="btnLoad" x="422" y="84" label="Load" enabled="true" click="loadProject();"/>
<mx:ComboBox id="listProjects"
x="652"
y="85"
editable="true"
change="listChange()"
color="#050CA8"
fontFamily="Arial" />
<mx:Label x="480" y="86" text="Language:" id="label3" fontFamily="Arial" />
<mx:ComboBox id="listLang"
x="537"
y="84"
editable="true"
dataProvider="{langList}"
color="#050CA8"
fontFamily="Arial"
width="107"
change="listLangChange(event)"/>
<mx:CheckBox x="830" y="84" label="Languages in English" id="langCheckbox" click='toggleLang()'/>
</mx:HBox>
It's not that clear form your code where and how the updateState function gets called, and to get any further into a solution I think I would need to see that. However, I think you may like to consider a different approach.
Have you tried using views instead of manually showing and hiding things and setting properties? I think you would have simpler code if you had a different view state for each of the cases in your switch, e.g. 'login' etc. Then all the showing hiding stuff becomes a design-time activity rather than run-time and all you have to do is set the current state.
If you matched your state names with your ApplicationData currentState values you may even be able to do away with the updateState function completely.
Have you tried changing
updateState(event:* = null):void
to this
updateState(event:Event = null):void
Im still looking into the event:* and everything I have found so far has Event instead of *. Will repost still looking

Flex conditional data binding

I have got two labels in my flex mxml component.
first one shows playheadtime of videodisplay and another is also used for same purpose. the difference is that when we are in add mode(decided from a flag variable) both should show current playheadtime using binding. but when we are in edit mode(again decided from flag) the latter label should remain static, to be more specific, the value retrived from database.
how can I do that using actionscript. I tried ChangeWathcer but I found it a bit tricky. Is there any other simpler way or am I missing something.
following is my code.
private function init():void
{
if (queFlag == 'a')
{
// timeLbl.text = currentTimeLbl.text using some binding mechanism
}
else if(queFlag == 'e')
{
// timeLbl.text = 'value retrived from database' ;
}
}
here currentTimeLbl shows videoDisplay playheadtime so it changes dynamically as video plays.
please help me out.
You could do it in something like the following:
<Label id="timeLbl" text="{timeLabelText}"/>
<Label id="currentTimeLbl" change="dispatchEvent('currentTimeLblChanged')"/>
[Bindable(event = "queFlagChanged")]
[Bindable(event = "currentTimeLblChanged")]
private function get timeLabelText():String
{
if(_queFlag == 'a')
{
return currentTimeLbl.text;
}
else
{
return 'value retrived from database';
}
}
public function set queFlag(value:String):void
{
_queFlag = value;
dispatchEvent(new Event("queFlagChanged"));
}
Here is a very short way of conditional binding in Flex. If you code the conditions into MXML curly-bracket-bindings they will be transformed by the MXML compiler to listeners on all objects participating in this expression.
Here is a working example:
<mx:CheckBox id="flagBox"/>
<mx:ComboBox dataProvider="{['a','e']}" id="flagBox2"/>
<mx:TextInput id="txtBox"/>
<mx:Label text="default: {txtBox.text}"/>
<mx:Label text="conditional (bool): { (flagBox.selected)? txtBox.text: 'default' }"/>
<mx:Label text="conditional (value): { (flagBox2.selectedItem == 'a')? txtBox.text: 'default' }"/>
Checking flagBox will result in label #2 displaying "default" otherwise the text from the txtBox is displayed.
Selecting "a" in flagBox2 will result in label #3 displaying "default" otherwise the text from the txtBox is displayed.
I regularly use this for reducing my lines of code in my UI-logic and it works quite well for me. A problem of this techniques is that you can't use all logic symbols in curly-braket-bindings, such as < or &&, but i usually could life with that.

Flex: Determine if a component is showing

What is the best way to determine if a component in Flex/Flash is showing on the user's screen? I'm looking for an analog to Java's Component.isShowing() method.
The show and hide events fire for visibility, and this seems to work for the first descendant of a ViewStack component, but not further down the display tree.
... or avoiding recursion:
public static function isVisible(obj:DisplayObject):Boolean
{
while (obj && obj.visible && obj !== Application.application)
{
obj = obj.parent;
}
return obj && obj.visible;
}
You want to check if the component property visible is true and this is for all the parents of your component in the DisplayList, am I correct?
public static function isVisible(c : UIComponent) : Boolean {
if (c == null) return false;
if (c is Application) return c.visible;
return c.visible && isVisible(c.parent);
}
UIComponent.visible is not necessarily valid for children of an object where visible=false. From the docs:
"In either case the children of the object will not emit a show or hide event unless the object has specifically written an implementation to do so."
I wrote a sample application that confirms this to be true. What you can do is walk up the display list checking for visible to be false on a parent. Basically "visible" gives false positives but shouldn't give false negatives. Here is a quick utility I put together:
package
{
import flash.display.DisplayObject;
import mx.core.Application;
public class VisibilityUtils
{
public static function isDisplayObjectVisible(obj : DisplayObject) : Boolean {
if (!obj.visible) return false;
return checkDisplayObjectVisible(obj);
}
private static function checkDisplayObjectVisible(obj : DisplayObject) : Boolean {
if (!obj.parent.visible) return false;
if (obj.parent != null && !(obj.parent is Application))
return checkDisplayObjectVisible(obj.parent);
else
return true;
}
}
}
I haven't done anything more than trivial tests on this but it should get you started.
Strange as it seems, now that you mention it, I don't believe there is a simple test to determine whether a component is actually visible onscreen in the sense Component.isShowing() implies.
It's also true the show and hide events don't bubble by default, so if you want to be notified of visibility changes in a descendant of a ViewStack container, you'll need to listen for them explicitly. The implementation details would vary depending on what sort of behavior you were after, but to take the simple example:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:VBox>
<mx:HBox>
<mx:Button id="btn1" click="vs.selectedIndex = 0" label="Show 1" />
<mx:Button id="btn2" click="vs.selectedIndex = 1" label="Show 2" />
</mx:HBox>
<mx:ViewStack id="vs" selectedIndex="0">
<mx:Panel id="panel1">
<mx:Label id="label1" text="Label 1" show="trace('showing label 1')" hide="trace('hiding label 1')" visible="{panel1.visible}" />
</mx:Panel>
<mx:Panel id="panel2">
<mx:Label id="label2" text="Label 2" show="trace('showing label 2')" hide="trace('hiding label 2')" visible="{panel2.visible}" />
</mx:Panel>
</mx:ViewStack>
</mx:VBox>
</mx:Application>
... you'll see the show and hide events for each label fire once their visible properties have been bound to their parent panels'. Hopefully that illustrates the point; you can extend it however best suits your application. Good luck!
I was trying to obtain the same in a reusable manner.. I almost found out a way using getObjectsUnderPoint() - this returns the object under a particolar point, z-ordered (even if they are not siblings, e.g. ViewStack, Popups, ecc.).
Basically, I get the topmost display object on under a particular point of the stage, then go up un the display object hierarchy to find the tested object. If I find it, the object is visible (not visible objects in the hierarchy should be already filtered out by the getObjectsUnderPoint call).
The problem here is that you must use a non-transparent point of your object (in my case, I used an offset of 5 pixel due to rounder borders), otherwise it will not be picked up by this function.
Any ideas to improve it?
Cosma
public static function isVisible(object:DisplayObject):Boolean {
var point:Point = object.localToGlobal(new Point(5, 5));
var objects:Array = object.stage.getObjectsUnderPoint(point);
if (objects.length > 0) {
if (isDescendantOf(object, objects[objects.length - 1] as DisplayObject)) {
return true;
}
}
return false;
}
public static function isDescendantOf(parent:DisplayObject, child:DisplayObject):Boolean {
while (child.parent != null) {
if (child.parent === parent) {
return true;
} else {
child = child.parent;
}
}
return false;
}
This is all you really need. The "Application.application" check is futile.
/**
* Returns `true` if this component is actually shown on screen currently. This could be false even with
* "visible" set to `true`, because one or more parents could have "visible" set to `false`.
*/
public static function isShowing (c : DisplayObject) : Boolean {
while (c && c.visible && c.parent) {
c = c.parent;
}
return c.visible;
}

Resources