Delete item from array using repeater

I have some sort of custom form to order stuff.
When the user fills it in and presses a button the data is added to an array (shopping cart).
When the data is added to the array it also is added to the repeater

This happends when submitting to the shoppingcart array

if (winkelmand.length < 1) {
        console.log("kleiner dan 1")
 let toInsert = [{
 "_id": "item1",
 "positie" : $w("#txtPositie").value,
 "aantal": $w("#txtAantal").value,
 "profiel": $w("#ddDikteKader").value,
 "doorkijkafgewerktematen" : $w("#ddDoorkijkAfgewerkteMaten").value,
 "breedte" : $w("#txtBreedte").value,
 "hoogte" : $w("#txtHoogte").value,
 "kleurkader" : ralCode,
 "poedercode" : poedercode,
 "uitvoering" : uitvoering,
 "typegaas" : $w("#ddTypeGaas").value,
 "kleurpees" : $w("#ddKleurPees").value,
 "klikborstel" : $w("#ddKlikBorstel").value,
 "dikteklikborstel" : $w("#ddDikteBorstel").value,
 "kleurklikborstel" : $w("#ddKleurBorstel").value,
 "borstelboven" : borstelBoven,
 "borstelrechts" : borstelRechts,
 "borstelonder" : borstelOnder,
 "borstellinks" : borstelLinks,
 "typeclips" : $w("#ddTypeClips").value,
 "soortbevestiging" : $w("#ddSoortBevestiging").value
 }]
        winkelmand = toInsert //if shoppingcart is empty winkelmand = toInsert
        loadWinkemand() //load shoppingcart repeater data
        $w("#repeater1").expand()
 } else {
        console.log("groter dan of gelijk aan 1")
 let toInsert = {
 "_id": "item" + (winkelmand.length + 1).toString(),
 "positie" : $w("#txtPositie").value,
 "aantal": $w("#txtAantal").value,
 "profiel": $w("#ddDikteKader").value,
 "doorkijkafgewerktematen" : $w("#ddDoorkijkAfgewerkteMaten").value,
 "breedte" : $w("#txtBreedte").value,
 "hoogte" : $w("#txtHoogte").value,
 "kleurkader" : ralCode,
 "poedercode" : poedercode,
 "uitvoering" : uitvoering,
 "typegaas" : $w("#ddTypeGaas").value,
 "kleurpees" : $w("#ddKleurPees").value,
 "klikborstel" : $w("#ddKlikBorstel").value,
 "dikteklikborstel" : $w("#ddDikteBorstel").value,
 "kleurklikborstel" : $w("#ddKleurBorstel").value,
 "borstelboven" : borstelBoven,
 "borstelrechts" : borstelRechts,
 "borstelonder" : borstelOnder,
 "borstellinks" : borstelLinks,
 "typeclips" : $w("#ddTypeClips").value,
 "soortbevestiging" : $w("#ddSoortBevestiging").value
 }
        winkelmand.push(toInsert) // if there already is value in winkemand add to winkemand(shoppingcart)
        loadWinkemand()       //load shoppingcart repeater data
 }

Here is the loadWinkemand function (loading the shoppingcart)

function loadWinkelmand() {
    console.log("before data added")
    $w("#repeater1").data = winkelmand
    console.log("after data added")
    $w("#repeater1").forEachItem(($item, itemData, index) => {
 const VIEWDETAIL = $item("#btnDetail")
 VIEWDETAIL.onClick((event) => {
            console.log(winkelmand)
            $w("#txtPositieDetail").text = winkelmand[index].positie
            $w("#txtAantalDetail").text = winkelmand[index].aantal
            $w("#txtProfielDetail").text = winkelmand[index].profiel
            $w("#txtDoorkijkAfgewerkteMatenDetail").text = winkelmand[index].doorkijkafgewerktematen
            $w("#txtBreedteDetail").text = winkelmand[index].breedte
            $w("#txtHoogteDetail").text = winkelmand[index].hoogte
            $w("#txtKleurDetail").text = winkelmand[index].kleurkader
            $w("#txtPoedercodeDetail").text = winkelmand[index].poedercode
            $w("#txtUitvoeringDetail").text = winkelmand[index].uitvoering
            $w("#txtKlikborstelDetail").text = winkelmand[index].klikborstel
            $w("#txtDikteKlikborstelDetail").text = winkelmand[index].dikteklikborstel
            $w("#txtKleurKlikborstelDetail").text = winkelmand[index].kleurklikborstel
            $w("#txtTypeGaasDetail").text = winkelmand[index].typegaas
            $w("#txtKleurPeesDetail").text = winkelmand[index].kleurpees
            $w("#txtTypeClipsDetail").text = winkelmand[index].typeclips
            $w("#txtSoortbevestigingdetail").text = winkelmand[index].soortbevestiging
            $w("#txtBorstelBovenDetail").text = winkelmand[index].borstelboven
            $w("#txtBorstelRechtsDetail").text = winkelmand[index].borstelrechts
            $w("#txtBorstelOnderDetail").text = winkelmand[index].borstelonder
            $w("#txtBorstelLinksDetail").text = winkelmand[index].borstellinks
            $w("#boxDetail").expand()
 })

 const DELETE_ITEM = $item("#btnDelete")
 DELETE_ITEM.onClick((event)=>{
            console.log("index = ",index)
            winkelmand.splice(index,1); 
            reloadWinkemand()
 })
        console.log("in forEach")
        $item("#text200").text = "Positie : " + itemData.positie + "     Profiel : " + itemData.profiel + "\n" + "Breedte : " + itemData.breedte + "   Hoogte : " + itemData.hoogte + "\n Doorkijk/Afgewerkt : " + itemData.doorkijkafgewerktematen

 })
}

Now the problem i have is taht when i delete an item
It doesn’t delete as it should…
When i add a few items to the repeater it deletes evrything form that index until the last one


When i click the red square
This is the result

Any idea how i can fix it so it only deletes the item that needs to be deleted?

Kinds regards,
Kristof.

Kristof, looking at your code. I believe the source of the problem is that you register the button inside the repeater’s forEachItem, meaning it gets registered as many times as there are items, thus, when clicked, it will execute the action as many times as the button was registered.
Try registering the event listeners outside the loop, thus only once. I give you a piece of my code where I do the same, but getting the index from the context now, instead of the index from inside the repeater:

    $w('#btnDelete').onClick(async (event) => {
 let $item = $w.at(event.context);
        $item('#btnDelete').label = "Espere";
        $item('#btnDelete').disable();
 const data = $w('#repeater2').data;
 let objClickedItemData = data.find(item => item._id === event.context.itemId);
        strCurrentItemId = objClickedItemData._id;
        numCurrentItemIndex = data.findIndex(item => item._id === event.context.itemId); //needed for remove

And after that, you de the splice with the numCurrentItemIndex .

I had to refactor your code a little bit to understand and got to this:

$w.onReady(() => {
 //This is the best way to get the context of a clicked item inside a repeater
    $w("#btnDetail").onClick(event => {
 let clickedItem = findClickedItem(event)
        loadWinkemand(clickedItem)
 })

    $w("#btnDelete").onClick(event => {
 let clickedItem = findClickedItem(event)
 let removedItem = removeItemFromCart(data, clickedItem._id)
        loadWinkemand(removedItem)
 })
})

//Creates the object
//Don't know where this was inserted so I just left it here
//You don't need to check if it is the single product in the cart

let toInsertObject = createObjectToInsert()
winkelmand = toInsertObject
loadWinkemand(winkelmand) //load shoppingcart repeater data
$w("#repeater1").expand()

//Here is the loadWinkemand function (loading the shoppingcart)

function loadWinkelmand(data) {
 //Here you update your repeater, and it has to be done everytime you change something
    $w("#repeater1").data = data
    $w("#repeater1").forEachItem(($item, itemData, index) => {
        $item("#txtPositieDetail").text = winkelmand[index].positie
        $item("#txtAantalDetail").text = winkelmand[index].aantal
        $item("#txtProfielDetail").text = winkelmand[index].profiel
        $item("#txtDoorkijkAfgewerkteMatenDetail").text = winkelmand[index].doorkijkafgewerktematen
        $item("#txtBreedteDetail").text = winkelmand[index].breedte
        $item("#txtHoogteDetail").text = winkelmand[index].hoogte
        $item("#txtKleurDetail").text = winkelmand[index].kleurkader
        $item("#txtPoedercodeDetail").text = winkelmand[index].poedercode
        $item("#txtUitvoeringDetail").text = winkelmand[index].uitvoering
        $item("#txtKlikborstelDetail").text = winkelmand[index].klikborstel
        $item("#txtDikteKlikborstelDetail").text = winkelmand[index].dikteklikborstel
        $item("#txtKleurKlikborstelDetail").text = winkelmand[index].kleurklikborstel
        $item("#txtTypeGaasDetail").text = winkelmand[index].typegaas
        $item("#txtKleurPeesDetail").text = winkelmand[index].kleurpees
        $item("#txtTypeClipsDetail").text = winkelmand[index].typeclips
        $item("#txtSoortbevestigingdetail").text = winkelmand[index].soortbevestiging
        $item("#txtBorstelBovenDetail").text = winkelmand[index].borstelboven
        $item("#txtBorstelRechtsDetail").text = winkelmand[index].borstelrechts
        $item("#txtBorstelOnderDetail").text = winkelmand[index].borstelonder
        $item("#txtBorstelLinksDetail").text = winkelmand[index].borstellinks
        $item("#boxDetail").expand()
        console.log("in forEach")
        $item("#text200").text =
 "Positie : " +
            itemData.positie +
 "     Profiel : " +
            itemData.profiel +
 "\n" +
 "Breedte : " +
            itemData.breedte +
 "   Hoogte : " +
            itemData.hoogte +
 "\n Doorkijk/Afgewerkt : " +
            itemData.doorkijkafgewerktematen
 })
}

//If you separate your functions, the code gets easier to debug.
//Other tip is to attribute less actions to your functions.
//This one only creates the objects to be inserted.
function createObjectToInsert() {
 let obj = {
        _id: winkelmand.length < 1 ? `item1` : `item${(winkelmand.length + 1).toString()}`, //This checks if it is the first item
        positie: $w("#txtPositie").value,
        aantal: $w("#txtAantal").value,
        profiel: $w("#ddDikteKader").value,
        doorkijkafgewerktematen: $w("#ddDoorkijkAfgewerkteMaten").value,
        breedte: $w("#txtBreedte").value,
        hoogte: $w("#txtHoogte").value,
        kleurkader: ralCode,
        poedercode: poedercode,
        uitvoering: uitvoering,
        typegaas: $w("#ddTypeGaas").value,
        kleurpees: $w("#ddKleurPees").value,
        klikborstel: $w("#ddKlikBorstel").value,
        dikteklikborstel: $w("#ddDikteBorstel").value,
        kleurklikborstel: $w("#ddKleurBorstel").value,
        borstelboven: borstelBoven,
        borstelrechts: borstelRechts,
        borstelonder: borstelOnder,
        borstellinks: borstelLinks,
        typeclips: $w("#ddTypeClips").value,
        soortbevestiging: $w("#ddSoortBevestiging").value,
 }
 return obj
}

function removeItemFromCart(data, id) {
 return data.filter(item => item._id !== id)
}

function findClickedItem(event, data) {
 let clickedItem = data.find(item => item._id === event.context.itemId)
 return clickedItem
}

I don’t know if it is working properly cause I don’t have all the elements to test.
Let me know if it helps you.

Hi guy’s,

I will take a look at it when i find the time.

Thanks in advance for taking the time :slight_smile:

Kind regards,
Kristof.