PDA

Volledige versie bekijken : mass delete


inge88
%Europe/Berlin %888 %2006, 21:18
Wéér een vraag...

Ik heb nu dus een component in een datagridcolumn staan, een checkbox. Ik wil dat de items met een aangevinkte checkbox worden verwijderd zodra er op de verwijder button wordt geklikt. Ik kom er weer eens niet uit. Mijn leraar zei dat ik moest kijken naar de itemEditor, maar ik snap er de ballen niet van.

Vrijwel dezelfde code als in mijn andere topic; oplossing uit die topic erin verwerkt :)

main.mxml

<mx:Script>
<![CDATA[
import mx.core.ClassFactory;
private var CheckBoxItemRenderer:ClassFactory = new ClassFactory(CheckBox);

private function init():void
{
CheckBoxItemRenderer.properties = {changeHandler: CheckBoxChangeHandler};
}

private function CheckBoxChangeHandler(event:Event,data:Object): void
{
btnDelete.addEventListener("click", handleDeleteBtn);

}
private function handleDeleteBtn(event : MouseEvent): void
{
/*deleteContents.send({id:CheckBoxItemRenderer});*/
}
</mx:Script>
<mx:HTTPService id="listContents" url="http://localhost:3000/contents/list" useProxy="false" method="GET"/>
<mx:HTTPService id="editContents" url="http://localhost:3000/contents/update" useProxy="false" method="POST" result="listContents.send()"/>
<mx:HTTPService id="deleteContents" url="http://localhost:3000/contents/delete" useProxy="false" method="POST" result="listContents.send()"/>
<mx:HTTPService id="createContents" url="http://localhost:3000/contents/create" useProxy="false" method="POST" result="listContents.send()"
contentType="application/xml">
<mx:request xmlns="">
<contents>
<author>{author.text}</author>
<title>{title.text}</title>
<text>{text.text}</text>
</contents>
</mx:request>
</mx:HTTPService>
<mx:DataGrid width="100%" height="324" id="contents_dg" dataProvider="{listContents.lastResult.contents.content}" y="0">
<mx:columns>
<mx:DataGridColumn itemRenderer="{CheckBoxItemRenderer}" width="150" headerText="Verwijder?"/>
<mx:DataGridColumn headerText="Auteur" dataField="author"/>
<mx:DataGridColumn headerText="Titel" dataField="title"/>
<mx:DataGridColumn headerText="Categorie" dataField="category-id"/>
</mx:columns>
</mx:DataGrid>

<mx:ControlBar horizontalAlign="right">
<mx:Button id="btnDelete" label="Verwijder"/>
</mx:ControlBar>
</mx:Panel>


CheckBox.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:CheckBox change="myChangeHandler(event)" xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script>
<![CDATA[
[Bindable]
public var changeHandler:Function;

private function myChangeHandler(event:Event):void{
if(changeHandler != null){
changeHandler(event,data);
}
}
]]>
</mx:Script>

</mx:CheckBox>

TheDutch
%Europe/Berlin %949 %2006, 22:47
De ItemEditor is niet echt de oplossing voor deze vraag :).

Wat een ItemRenderer is je volgensmij al duidelijk. Een ItemEditor is werkelijk een ItemRenderer die alleen zichtbaar is wanneer de property "editable" op true staat en je op het veld hebt geklikt om te editen. In jouw geval moet hij altijd zichtbaar zijn dus moet je een ItemRenderer gebruiken zoals je al deed.

Ik zal de aangepaste versies neerzetten (met comments) zodat je ze kunt vergelijken.

main.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
initialize="init()">

<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.core.ClassFactory;
import mx.controls.Alert;

[Bindable]
private var dummyCollection:ArrayCollection = new ArrayCollection([
{itemName: "item 1", checkBoxData: false},
{itemName: "item 2", checkBoxData: false},
{itemName: "item 3", checkBoxData: false},
{itemName: "item 4", checkBoxData: false},
{itemName: "item 5", checkBoxData: false},
{itemName: "item 6", checkBoxData: false},
{itemName: "item 7", checkBoxData: false},
{itemName: "item 8", checkBoxData: false},
{itemName: "item 9", checkBoxData: false},
{itemName: "item 10", checkBoxData: false},
{itemName: "item 11", checkBoxData: false},
{itemName: "item 12", checkBoxData: false},
{itemName: "item 13", checkBoxData: false},
{itemName: "item 14", checkBoxData: false},
{itemName: "item 15", checkBoxData: false},
{itemName: "item 15", checkBoxData: false},
{itemName: "item 16", checkBoxData: false}
]);

[Bindable]
private var myCheckBoxItemRenderer:ClassFactory = new ClassFactory(MyCheckBox);


private function init():void{
myCheckBoxItemRenderer.properties = {changeHandler: myCheckBoxChangeHandler};
}

private function myCheckBoxChangeHandler(event:Event,data:Object):v oid{
Alert.show("Checkbox changed at: "+event.currentTarget.parent.parent.selectedIndex);
}

// Function to remove all items from dummyCollection that are selected.
private function removeSelected():void{
for(var i:int=itemDG.dataProvider.length-1;i>=0;i--){
if(itemDG.dataProvider[i].checkBoxData == true){
itemDG.dataProvider.removeItemAt(i);
}
}
}


]]>
</mx:Script>
<mx:VBox width="100%" height="100%">

<mx:DataGrid id="itemDG" dataProvider="{dummyCollection}">
<mx:columns>
<mx:DataGridColumn headerText="Item List" dataField="itemName" />
<mx:DataGridColumn headerText="Checkbox" dataField="checkBoxData" itemRenderer="{myCheckBoxItemRenderer}" />
</mx:columns>
</mx:DataGrid>

<!-- Button to remove selected items. -->
<mx:Button label="Remove" click="removeSelected()" />
</mx:VBox>
</mx:Application>

MyCheckBox.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:CheckBox selected="{/*Bind column value to CheckBox */ data[listData['dataField']]}" change="myChangeHandler(event)" xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script>
<![CDATA[
[Bindable]
public var changeHandler:Function;

private function myChangeHandler(event:Event):void{
if(changeHandler != null){
// Make sure the change is permanent.
data[listData['dataField']] = event.currentTarget.selected;

// Call the change handler.
changeHandler(event,data);
}
}
]]>
</mx:Script>

</mx:CheckBox>


Als je vragen hebt over aanpassingen dan hoor ik het wel :).

ps. Geef je zelfgemaakte componenten nooit(!) dezelfde naam als componenten die standaard in Flex zitten zoals CheckBox. Ik meen dat Waldo je dit ook al eens heeft aangegeven. Dat is namelijk vragen om problemen.

TheDutch
%Europe/Berlin %958 %2006, 22:59
Ik merk net op dat er een bug zit in het verwijderen van items uit de data provider met die FOR loop. Ben er nog niet achter wat het probleem veroorzaakt :).


Ik heb de bug even heel "dirty" opgelost door i=-1; in de FOR loop te zetten tijdens het verwijderen van de items uit de data provider. Het is namelijk zo dat wanneer 1 en 2 zijn geselecteerd en hij loopt om te verwijderen en gooit 1 weg dan is 2 weer 1 geworden maar staat de index van de FOR loop al op 2 en dus zal er altijd één geselecteerd blijven. Met die i=-1; gaat hij steeds overnieuw de FOR loop doen na elke verwijdering. Niet echt netjes maar voor nu even de oplossing. Ik zou zeggen bekijk en probeer de laatste versie eens!


[edit 2]
De bug is nu wel opgelost. De FOR loop gaat nu achterstevoren om niet in de knoop te komen met het teruglopen van de collectie grote en de posities.
[/edit 2]

inge88
%Europe/Berlin %464 %2006, 11:09
Geweldig! :D alleen ik moet de items uit een database halen... die dus verwijderd moeten kunnen worden. Hoe krijg ik die dan in die ArrayCollection?

inge88
%Europe/Berlin %498 %2006, 11:57
Ik heb al een oplossing :D ik maak gewoon geen gebruik van de arrayCollection, maar van de database.

Dit stukje code aangepast (contents_dg is mijn datagrid ID trouwens)


// Function to remove all items from dummyCollection that are selected.
private function removeSelected():void{
for(var i:int=contents_dg.dataProvider.length-1;i>=0;i--){
if(contents_dg.dataProvider[i].checkBoxData == true){
deleteContents.send(contents_dg.dataProvider.remov eItemAt(i));
}
}
}


heel erg bedankt voor je hulp! :D

TheDutch
%Europe/Berlin %525 %2006, 12:36
Als ik jou was zou ik ook contents_dg.dataProvider.removeItemAt(i); er tussen laten staan om ze ook uit het DataGrid te halen zonder dat je weer alle data uit de database moet gaan halen. Idee?

Verder lijkt me het een prima oplossing zo :).

Graag gedaan hoor!

inge88
%Europe/Berlin %527 %2006, 12:40
Ik snap je niet helemaal? Zonder dit stukje haalt hij ze ook gelijk uit de datagrid? Ik hoef niks te vernieuwen oid...

TheDutch
%Europe/Berlin %565 %2006, 13:34
Nu ik je code beter bekijk zie ik dat je de removeItemAt() in je send() method hebt staan van de RemoteObject. Daarom wordt hij verwijderd uit het DataGrid. Ik vraag me alleen sterk af of hij wel uit de database verwijderd wordt aangezien removeItemAt() geen returnwaarde geeft en dus niets meegeeft aan de method deleteContents().

Kan je de volgende regel wat toelichten? :)

deleteContents.send(contents_dg.dataProvider.remov eItemAt(i));

inge88
%Europe/Berlin %579 %2006, 13:54
uhm.. ik heb maar een beetje zitten prutsen.. ik had eerst ook niet verwacht dat hij dit stukje code correct zou uitvoeren. Maar hij doet 't toch :)

Naar mijn idee, kijkt hij eerst naar de lijst in de datagrid.. deze lijst is gevult met items uit de database met ieder een eigen id. ik denk dat die FOR loop kijkt naar de ID's van de items zelf en niet naar die van de datagrid, of ze zijn op een of andere manier aan elkaar gekoppelt. Door deleteContents.send() te gebruiken verwijderd hij die ID's, dus die items...

Ik kan 't verkeerd hebben hoor, maar zo dacht ik dus...

TheDutch
%Europe/Berlin %598 %2006, 14:21
Ik heb het even nagekeken in de Livedocs van Flex 2 en ik zie inderdaad dat Adobe de removeItemAt() function hebben veranderd vanaf Flash 8 en Flex 2 ten opzichte van Flex 1.5 en Flash MX 2004. Nu geeft removeItemAt() het item terug wat verwijderd is dus is jouw code in orde :).

Top!