Use actionscript to uncheck a checkbox in a component? - apache-flex

I have a component with checkboxes, the checkboxes are bound to booleans in the main code:
<mx:CheckBox id="LyrClearAll" selected="{Application.application.bLyrClearAll}"/>
This works fine for the checkboxes that don’t change unless a user interacts with them again. My problem appears because I want to “uncheck” one of the boxes everytime the component is closed. (I know something other than a checkbox would work better, but I’m trying to keep things consistent in this component.)
I have tried setting the bound Boolean variable to false, and I’ve tried setting the checkbox.selected value to false. Neither are working, everytime I open the component the checkbox is still checked.
private function makeLyrsPopUp(evt:MouseEvent):void
{
var panelLyr:popUpLayers = PopUpManager.createPopUp(this, popUpLayers, false) as popUpLayers;
panelLyr.LyrClearAll.selected == false; //?? set checkbox back to unchecked
panelLyr["cancelButton"].addEventListener("click", removeMe);
panelLyr["okButton"].addEventListener("click", submitData);
PopUpManager.centerPopUp(panelLyr);
function submitData(event:Event):void //change layer visibility based on check boxes in popupLayer
{
bLyrStreet = panelLyr.LyrStreet.selected;
bLyrParcel = panelLyr.LyrParcel.selected;
bLyrClearAll = panelLyr.LyrClearAll.selected;
if (bLyrClearAll)
{
clearLayers();
bLyrClearAll == false; //?? set checkbox back to unchecked
}
removeMe(event);
}
}

Needed to change == false to = false

bLyrClearAll should be declared bindable:
[Bindable]
var bLyrClearAll: Boolean;

Related

Flex multiple selection drop down list with scrolling

I'm working in flex and I made a custom drop down where there are check boxes to allow the user to select multiple options. I used this template.
However this does not have scrolling because if you allow scrolling for some reason the checkboxes start to mess up. For instance if you have options 1 to 8 and only 1 to 5 are shown. You select option 1 and then scroll down to select option 7. When you scroll up the checkboxes start to switch around like option 3 all of a sudden is showing selected. Keep scrolling up and down and the checkbox selection just changes on it's own. I think this is a rendering issue and the actual selection data isn't changed at all (it knows only option 1 and option 7 were selected). Any ideas on how to fix this?
public function onOpen(event:DropDownEvent):void
{//load the checkboxes and set the mouse tracker
activateAllCheckBoxes();
this.scroller.verticalScrollBar.addEventListener(Event.CHANGE, list_verticalScrollBar_change);
callLater(observeMouse);
}
private function list_verticalScrollBar_change(evt:Event):void
{
//currentlySelectedCheckBoxes = selectedCheckboxes;
UpdateCheckBoxesWhenScrolling();
selectedIndex = -1;
}
protected function UpdateCheckBoxesWhenScrolling():void
{
for (var c:int = 0; c < dataGroup.numElements; c++) {
var obj:DropDownCheckBox = dataGroup.getElementAt(c) as DropDownCheckBox;
if(obj!=null)
{
var judgDebtorFromCheckBox:JudgDebtor = (obj.data) as JudgDebtor;
if(FindInCurrentList(judgDebtorFromCheckBox.JudgmentDebtorId)>0)
{
obj.checkbox.selected = true;
}
else
{
obj.checkbox.selected = false;
}
}
}
}
private function FindInCurrentList(ID:int):int
{
for(var i:int=0;i<currentlySelectedCheckBoxes.length;i++)
{
var JD:JudgDebtor = currentlySelectedCheckBoxes.getItemAt(i) as JudgDebtor;
if(JD.JudgmentDebtorId == ID)
return 1;
}
return -1;
}
So above code I register a scroll event listener on the drop down. It will update the drop down entries which has a check box and it uses an array collection called: currentlySelectedCheckBoxes. I debug the UpdateCheckBoxesWhenScrolling function and it's working fine, in other words it will check off the ones selected but for some reason it still is showing the wrong results for instance 11 entries in the list and only the second one is selected I scroll down and I can't see the the second entry but all of a sudden the last entry is showing that it's checked off.
This happens because the drop down list reuses the renderers when you scroll. For example if you have checked 1st item and scroll, the renderer for that is reused to display the item that becomes visible when you scroll. So the last item shows as checked. To avoid messing up the selection, you will have to do the following in the renderer that you are using
override public function set data(value:Object):void
{
super.data = value;
//inspect the property which indicates whether to select the checkbox or not
//and set the value of selected property accordingly
}
Hope this helps

How to re-render itemRenderer for a DropDownList in Flex4?

I have created a custom ComboCheck which extends the spark DropDownList that is a DropDownList of checkboxes. Inside of my itemRenderer I have the code:
[Bindable]override public function set data (value:Object):void {
if (value!=null) {
_data = value;
item.label = value.label;
item.group = value.group;
item.toolTip = value.toolTip;
item.selected = value.selected;
item.enabled = value.enabled;
...
This code allows me to enable and disable individual items in the dropdown list so that when it is rendered, you will not be able to select the items I have disabled. I am trying to create the functionality where a user clicks on a specific item that is in a given category which results in all other categories being disabled until you de-select everything.
My issue is that while the DropDownList is up, the items have already been rendered so changing the enabled property on each item that should be disabled doesn't change the items that have already been rendered. If you scroll down and back up to re-render the data it works fine.
Is there a way to have the itemRenderer re-render the data on the screen so that it refreshes and applies this update?
Below is sample code of an item being selected, it disables every other item then enables only the one you have selected. I also have a itemDeselect function that decrements the itemCount and enables everything
private function itemSelect(evt:Event):void{
itemCount++;
var myText:String = '';
var items:Vector.<Object> = allItems.selectedItems;
if(itemCount == 1){
for each(var obj:Object in allItems.dataProvider){
obj.enabled = false;
}
}
for (var i:String in items) {
if(items[i].group == "HU"){
items[i].enabled = true;
huList[items[i].label] = items[i].selected;
}else if(items[i].group == "ALL"){
items[i].enabled = true;
allCase = items[i].selected;
}else{
items[i].enabled = true;
otherList[items[i].label] = items[i].selected;
}
}
selectionChanged = true;
}
This works but again it is not re-rendered so the obj.enabled=false does not appear unless you scroll down and back up.
EDIT: Final Solution
Using the third option suggested by www.Flextras.com I used the itemUpdated property dataProvider.itemUpdated(obj) so inside of the
for each(var obj:Object in allItems.dataProvider){
obj.enabled = false;
allItems.dataProvider.itemUpdated(obj);
}
This will also not cause the dropdownlist to reset to scrollPosition 0
Is there a way to have the
itemRenderer re-render the data that
is shown to apply this update?
I have three ways.
1) invalidate the list's dataGroup instead of the list.
listInput.dataGroup.invalidateDisplayList();
2) Refresh the dataProvider
(listInput.dataProvider as ArrayCollection).refresh();
3) When the dataProvider item changes, invoke the itemUpdated() property on the collection. No code sample for this one, sorry.
The one thing I often forget to do in this situation is implement the renderer so that it knows to switch itself back into the 'non-active' state. So in your set data method of the itemRenderer be sure to add an else condition putting all those values back to some default.
I found the way to "re-render", just override the set data function and update all the properties in the itemRenderer: eg
I have a DataGrid with a column with an itemRenderer that shows a different backgroundColor for each item in my dataProvider.
<mx:DataGrid>
<mx:columns>
<mx:DataGridColumn itemRenderer="myItemRenderer"/>
</mx:columns>
</mx:DataGrid>
//myItemRenderer:
override public function set data( value:Object ) : void {
super.data = value;
if( value > 0) setStyle("backgroundColor",0xff99ff);
else setStyle("backgroundColor",0xffffff);
}
That's all.
You can also add event listener for dataChange event to the item renderer itself. This event gets fired after data property is changed.
<s:ItemRenderer dataChange="updateView(event)">
<fx:Script>
<![CDATA[
protected function updateView(event:Event):void{
//update logic
}
]]>
</fx:Script>
</s:ItemRenderer>

In Flex, how do I create a CheckBox that can't be un-checked?

In Flex, how do I create a CheckBox that can't be un-checked? I run a function when the checkbox is clicked. If that function encounters an error, I want the state of the checkbox to remain the same. How do I do that?
You can use the enabled attribute to prevent the checkbox from being accessed once it's in the state you mentioned.
onFunctionError():void {
yourCheckbox.enabled = false;
}

Flex Alert control: Activating the "default" button on enter/space key-press

No matter what I try, I can't seem to fire the click event on the "default" button in an Alert control in a Flex 3.4 application.
Alert.show(
'Are you sure you want to delete the selected link?',
'Confirm Delete',
Alert.YES | Alert.CANCEL,
null,
confirmDelete,
null,
Alert.YES
);
In the above code sample, the final argument: Alert.YES is specifying that the "default" option (from the bitwise list in the 3rd argument) is the "Yes" button. In theory, and based on my experience designing Windows applications, "default button" means that hitting the enter key (or sometimes the space bar) fires the click event for that button.
If it matters, the Alert in question is modal.
I can see that the button is styled as the default: it gets a bit of a halo or extra border when compared to the Cancel button or when compared to itself when passing null as the last argument.
However, hitting the enter and space keys seem to have no affect. Am I doing something wrong, or missing some crucial step in getting this functionality to work?
Update 2010-02-17:
Based on my 2nd comment on #rhtx's answer:
Ok, finally got around to trying this. Since the Alert class uses lots of static methods, I essentially just copied the Alert and AlertForm classes into my project (and fixed some relative paths for includes), and what I ended up with was an uglier alert box that works (or doesn't, depending on your perspective) the same way as the vanilla Alert class. I did realize, however, that if you hit TAB it will focus the alert buttons, at which point hitting Escape/Enter will have the desired effect... So how do I eliminate the need to hit TAB?
I tried a few more things and didn't get anywhere.
I tried faking a TAB keypress after opening the alert (with both KEY_DOWN and KEY_UP event types):
var a:Alert = Alert.show(msg, title, Alert.YES | Alert.CANCEL, null, fnCb);
var tabEvent:KeyboardEvent = new KeyboardEvent(
KeyboardEvent.KEY_DOWN,
true,
false,
0,
Keyboard.TAB
);
a.dispatchEvent(tabEvent);
I also found this blog post and tried doing this to focus the alertForm:
var a:Alert = Alert.show(msg, title, Alert.YES | Alert.CANCEL, null, fnCb);
a.mx_internal::alertForm.setFocus();
Neither of these threw errors, but neither produced the desired result, either.
I would approach this by extending the Alert class to include functionality that listens for keyUp events from the Enter and Space keys.
In the createChildren method of your subclass:
override public function createChildren():void
{
super.createChildren();
this.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);
this.stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener);
}
private function keyUpListener(e:KeyboardEvent):void
{
if(e.keyCode == Keyboard.ENTER || e.keyCode == Keyboard.SPACE)
{
//Trigger the Alert.YES functionality...
}
}
I'm having some issues with my set up this morning and can't get into the Alert class to provide info on how to "Trigger the Alert.YES functionality", but I'll try to post some more on this later on. Hope this little bit helps.
Also - I'm not 100% on this - but I think you will need to manually remove the event listeners when the Alert popup is removed.
Aaand... you may not need both of those listeners. Can't test right now to make sure.
UPDATE: -----------------
After a little more looking, maybe the best way to go about this is to extend the AlertForm class (which manages the Alert's buttons), and then extend the Alert class to use your extended AlertForm class.
The AlertForm class has a keyDownHandler method, which it defines like this:
override protected function keyDownHandler(event:KeyboardEvent):void
{
var buttonFlags:uint = Alert(parent).buttonFlags;
if (event.keyCode == Keyboard.ESCAPE)
{
if ((buttonFlags & Alert.CANCEL) || !(buttonFlags & Alert.NO))
removeAlert("CANCEL");
else if (buttonFlags & Alert.NO)
removeAlert("NO");
}
}
You can see that it is setting up the 'close' behavior in response to pressing the Escape key. You add a little logic, based on the code in the above 'keyUpListener' function to make a call to the AlertForm's removeAlert method, passing in the appropriate String value for the Yes button.
For reference, the removeAlert method looks like this:
private function removeAlert(buttonPressed:String):void
{
var alert:Alert = Alert(parent);
alert.visible = false;
var closeEvent:CloseEvent = new CloseEvent(CloseEvent.CLOSE);
if (buttonPressed == "YES")
closeEvent.detail = Alert.YES;
else if (buttonPressed == "NO")
closeEvent.detail = Alert.NO;
else if (buttonPressed == "OK")
closeEvent.detail = Alert.OK;
else if (buttonPressed == "CANCEL")
closeEvent.detail = Alert.CANCEL;
alert.dispatchEvent(closeEvent);
mx.managers.PopUpManager.removePopUp(alert);
}
I ran into a similar situation. What got me out of it was:
(1) defining the default button in Alert.show(), (2) using a callLater(), and (3) setting the focus manually on the default button.
For example, using Alert.CANCEL as the intended default button (can change to Alert.YES if needed):
var a:Alert = Alert.show(msg, title, Alert.YES | Alert.CANCEL, null, fnCb, null, Alert.CANCEL);
callLater(setAlertButtonFocus,[a]);
...
private function setAlertButtonFocus(a:Alert):void {
a.mx_internal::alertForm.mx_internal::defaultButton.setFocus();
}
This enables the Escape and Enter keys to act as if the user clicked the default button with the mouse.

asp.net hidden field not setting new value, need disabled alternative

I have a hidden field on my page
<input runat="server" type="hidden" id="selectedIndex" />
and it is being set by this bunch of code, an onclick event to a gridview's row:
var gridViewCtlId = '<%=GridView.ClientID%>';
var selectedIndex = '#<%=selectedIndex.ClientID%>';
var itemVisible = '<%=ItemVisible.ClientID%>';
var gridViewCtl = null;
var curSelRow = null;
var previousRowIndx = null;
window.onload = function showQuery()
{
if ($(selectedIndex).val() != undefined)
{
if ($(selectedIndex).val() != '')
{
var prevRowID = $(selectedIndex).val();
var prevRow = getSelectedRow(prevRowID);
prevRow.style.backgroundColor = '#1A8CD4';
}
}
}
function getGridViewControl(rowIdx)
{
if (gridViewCtl == null)
{
gridViewCtl = document.getElementById(gridViewCtlId);
}
}
function onGridViewRowSelected(rowIdx)
{
if (document.getElementById(gridViewCtlId).disabled == false)
{
var selRowCCA = getSelectedRow(rowIdx);
if (curSelRow != null)
{
var previousRow = getSelectedRow(previousRowIndx);
var CountIdx = previousRowIndx % 2;
if (document.getElementById(itemVisible) == null)
{
if (CountIdx == 0)
{
previousRow.style.backgroundColor = 'Silver';
}
else
{
previousRow.style.backgroundColor = 'White';
}
}
}
if (null != selRow)
{
previousRowIndx = rowIdx;
curSelRow = selRow;
selRow.style.backgroundColor = '#1A8CD4';
}
}
}
function getSelectedRow(rowIdx)
{
getGridViewControl(rowIdx);
if (gridViewCtl != null)
{
$(selectedIndex).val(rowIdx);
return gridViewCtl.rows[rowIdx];
}
return null;
}
This is what happens: When The page first loads, the hidden field is undefined, which it should be. When I click on a row and then click the 'select' button which then calls this:
GridView.Attributes.Add("disabled", "true");
The gridview becomes disabled (along with the select button) and another gridview comes up (which should happen depending on what is seleted in the first gridview). So now, here is the problem. When I click on a row in the gridview (I'm only talking about the initial gridview, not the secondary one which comes up, that's not an issue here), and click select, everything gets greyed out and most of the time, the selected row will highlight when the page loads (the other times for some reason it defaults to row #2). Then, say you click on row 4 then click on row 1 and then click select, for some reason row 4 will remain highlighted and row 4's data will then populate the second gridview, like you never clicked row 1. But if I click row 4 then click row 1 then click row 1 again, does it save. Does anyone know why that happens?
Also, I'm pretty much trying to disable the first gridview when select is hit so I do
GridView.Attributes.Add("disabled", "true");
rather than
GridView.Enabled = false;
If a user re-clicks the search button (another button located previously on the page which makes this gridview become visible), I would like the secondary gridview to become hidden, and the primary gridview (this one in question) to become re-enabled. But doing
GridView.Attributes.Add("disabled", "false");
when the search button is fired only disables the gridview, which is very weird. Now I know that the disabled field is not supported by any other browser except IE, and i only use it because I need to check if the gridview is disabled so a user cant click on another row after they've made their selection (which happens if I dont do the following:
if (document.getElementById(gridViewCtlId).disabled == false)
So could anyone let me know of another way of accomplishing that task? Thanks again in advance.
Some bits of info on disabled:
Browsers won't send any disabled control's value to the server. This is by definition.
Disabled field is supported by other browsers, but it uses a different model. Note list of supported browsers: http://www.w3schools.com/tags/att_input_disabled.asp (also how it is defined disabled='disabled').
Also see how it compares to the read-only: http://www.w3.org/TR/html401/interact/forms.html#h-17.12.2
Also note according to the standard its support its limited to certain elements. This is important, as you are applying it at an unsupported html element, which is also a likely cause of it not working in other browsers in your scenario. You can disable the supported control by using an script, getting the controls to apply it like $get("someClientID").getElementsByTagName("input");

Resources