Flex - ArrayCollection - Aggiunta e rimozione di una filtraggio
-
27-10-2019 - |
Domanda
Sto usando Adobe Flash Builder 4 Premium. Ho un mx:DataGrid
e a s:TextInput
, e sto cercando di impostare una casella di ricerca che filtra il datagrid su ciascuna pressione del tasto.
Questa pagina mostra un esempio quasi perfetto di ciò che sto cercando di fare, tranne per il fatto che lo sto preparando in a s:TitleWindow
, che viene allevato come popup usando il popupmanager. L'elenco che sto cercando di filtrare può essere molto grande. È un elenco di nomi utente, recuperati da un database MySQL tramite PHP. Dal momento che può essere così grande, voglio che l'elenco venga popolato una volta nell'applicazione principale e quindi referenziato nella finestra popup in modo che non debba recuperare tutti i nomi utente ogni volta che l'utente apre il popup.
Ho tutto questo funzionare bene per la prima volta che tiri su il popup, ma se lo chiudi e lo rialzi, ricevo questo errore di runtime:
Ricevo anche questo errore se provo a impostare il filterFunction
Torna a Null poco prima di chiudere il popup.
Vedi il codice di esempio di seguito:
Applicazione principale:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.collections.*;
import mx.managers.PopUpManager;
[Bindable] public var allMembersList:ArrayCollection;
private function openPopup():void
{
var popupInstance:popup = PopUpManager.createPopUp(this as DisplayObject, popup, true) as popup;
PopUpManager.centerPopUp(popupInstance);
}
]]>
</fx:Script>
<s:Button label="Open Popup" click="openPopup()"/>
</s:Application>
Apparire:
<?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:model="services.model.*"
tabChildren="false"
close="close()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.managers.PopUpManager;
private function getUsers(startsWith:String = ""):void
{
if (FlexGlobals.topLevelApplication.allMembersList == null)
{
FlexGlobals.topLevelApplication.allMembersList = new ArrayCollection();
getUsersResult.token = php.getUsers();
}
FlexGlobals.topLevelApplication.allMembersList.filterFunction = function(item:Object):Boolean
{
return item.username.match(new RegExp("^"+ startsWith, "i"));
};
FlexGlobals.topLevelApplication.allMembersList.refresh();
grdMemberList.dataProvider = FlexGlobals.topLevelApplication.allMembersList;
}
private function getUsersResultHandler():void
{
var users:Object = getUsersResult.lastResult;
for each (var user:Object in users)
FlexGlobals.topLevelApplication.allMembersList.addItem({"username":user.username});
}
private function close():void
{
FlexGlobals.topLevelApplication.allMembersList.filterFunction = null;
FlexGlobals.topLevelApplication.allMembersList.refresh();
PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<fx:Declarations>
<model:MODEL id="php" fault="{Alert.show('There was a PHP error!\nPlease note the steps taken to produce this error and call support.\n\nError Message: '+ event.fault.faultDetail, 'Error');}" showBusyCursor="false"/>
<s:CallResponder id="getUsersResult" result="getUsersResultHandler()"/>
</fx:Declarations>
<mx:DataGrid id="grdMemberList" creationComplete="getUsers()">
<mx:columns>
<mx:DataGridColumn headerText="Member List" dataField="username"/>
</mx:columns>
</mx:DataGrid>
<s:TextInput id="txtUsername" keyUp="{ if (event.charCode != 13 && event.charCode != 0) getUsers(txtUsername.text); }"/>
</s:TitleWindow>
L'app sembra ancora funzionare come previsto, nonostante l'errore, ma non sono un fan di avere errori nella mia app, quindi mi piacerebbe davvero capire cosa sta causando questo problema.
Grazie!
Soluzione
Si scopre che il problema è stato con il tabChildren
proprietà. La documentazione dice di non utilizzare questa proprietà in Flex, ma di utilizzare hasFocusableChildren
invece. Non sono sicuro del perché questo problema si sia mostrato solo una volta che stavo cercando di impostare il filterFunction
.
Il motivo per cui stavo impostando tabChildren
A False è stato in modo che la funzionalità chiave della scheda predefinita (focus di commutazione) non si svolgesse, in modo da poter controllare quel comportamento da solo. Il hasFocusableChildren
La proprietà non funziona (o almeno, impostarla su False non impedisce alla messa a fuoco del tasto TAB), quindi potrei aver bisogno di provare un altro mezzo per catturare l'evento del tasto Tab e fermarlo.
MODIFICARE:
Per chiunque sia interessato (anche se non ha davvero nulla a che fare con il post originale), la soluzione era cambiare:
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:model="services.model.*"
width="1000"
height="550"
tabChildren="false"
close="close()">
a:
<s:TitleWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:model="services.model.*"
width="1000"
height="550"
keyFocusChange="{ event.preventDefault(); }"
close="close()">
Altri suggerimenti
Non provo mai a testare il tuo codice (perché necessita anche del lato server) ma penso che non dovresti ripristinare il filtro su NULL. In alternativa, è possibile impostarlo su una funzione che restituisce sempre vero.
function defaultFilterFunc( item: Object ): Boolean { return true; }