Inability to add extra row to repeater

I really hope someone can help me. I’m trying to add an extra row into a specified place. I retrieve the data from the repeater, added a row and then tried to set the repeater data but it didn’t work.

    $w('#contextAddButton').onClick((event) => {
        officerData=$w('#officerRepeater').data;
        let $item = $w.at(event.context);
        let repeaterId=Number($item('#repeaterId').text);
        repeaterId++;
        idcounter++;
        officerData.splice(repeaterId, 0, {
                _id:            idcounter,
                badgeElement:   badgeElement,
                badgeId:        badges[badgeElement].id,
                office:         badges[badgeElement].title,
                sameOffice:     true,
                }
         );
        officerData[repeaterId].memberId= "new memberId";
        officerData[repeaterId].name= "new member name";
        officerData[repeaterId].phone= "new member phone";
        officerData[repeaterId].email= "new email";
        $w("#officerRepeater").data = officerData;
        $w("#officerRepeater").forEachItem(($item, itemData, index) => {
            initRepeaterRow($item, itemData, index);
        })

    $w("#officerRepeater").onItemReady(($item, itemData, index) => {
        initRepeaterRow($item, itemData, index);
    } );
function initRepeaterRow($item, itemData, index) {
    $item('#repeaterId').text =     itemData._id.toString();
    $item('#badgeId').text =        itemData.badgeId;
    $item('#memberId').text =       itemData.memberId;
    $item('#badgeElement').text =   itemData.badgeElement;
    if(itemData.sameOffice) {
        $item('#officerSeparator').show();
        $item('#office').hide();
    } else {
        $item('#office, #addOfficer').show();
        $item('#roleSeparator').expand();
        $item('#office').text = itemData.office;
        $item('#officerSeparator').hide();
    }
    if (itemData.office=="Past Commodores" && itemData.roleQualifier!==undefined) {
        $item('#roleQualifier').show();
        $item('#roleQualifier').text = itemData.roleQualifier;
    }
    if (itemData.memberId==undefined) {
        //   testing for vacant role
    }
    if (itemData.boatName==undefined) {
        $item('#boatNameGroup').collapse();
    } else {
        $item('#boatNameRepeater').text = itemData.boatName;
    }
    if (itemData.email==undefined) {
        $item('#emailGroup').collapse();
    } else {
        $item('#emailRepeater').text = itemData.email;
    }
    if (itemData.phone==undefined) {
        $item('#phoneGroup').collapse();
    } else {
        $item('#phoneRepeater').text = itemData.phone;
    }
    $item('#name').text = itemData.name;
    $w("#formalPhoto").fitMode = "fit";
    $item('#formalPhoto').src=itemData.formalPhoto;

}

The failure point is where I set $w(“#officerRepeater”).data to the expanded officerData. It simply doesn’t store. If I log the contents of $w(“#officerRepeater”).data it’s unchanged!
Please, please can someone point me in the right direction!
Many thanks in advance

Not good…

$w("#officerRepeater").forEachItem(($w, itemData, index)=>{initRepeaterRow($w,itemData,index);})

Good…

$w("#officerRepeater").forEachItem(($item ,itemData, index)={ 	
	initRepeaterRow($item ,itemData, index);
})

And where is your → initRepeaterRow($item ,itemData, index); ← and what does it do ?

And what about …

$w("#officerRepeater").onItemReady(($item, itemData, index)=>{ ... });

Yep, quite agree about using $w and not $item. Now fixed. I’ve edited my original post to include the two sections you mentioned.

Is it working now? I don’t think so. If I’m right, lets try this. Before the:

$w("#officerRepeater").data=officerData;

do this:

$w("#officerRepeater").data=[];

to clear the repeater first. You need to, it is documented in a somewhere obscure place, I believe in some old example code Yisrael once provided.

If this does not work, let me know, there could be a second problem with the repeater’s internal caching. I ran up to it and there is a solution.

I’ve tried with clearing the repeater as well. The results are exactly the same. Here’s the console.log

officerRepeater length = 24

officerData=$w('#officerRepeater').data;
officerData length=24

$w('#officerRepeater').data=[];
officerRepeater length after clear = 0

Spliced in a new row 
officerData length= 25

$w('#officerRepeater').data=officerData
officerRepeater length =0

I replaced the splice with a push but still no effect. The line $w(“#officerRepeater”).data=officerData; has no effect. I can modify or delete rows but not add a new one.
Any ideas?

Let’s try plan B, to circumvent the repeater’s caching mechanism. I had a similar problem. The idea is to provide new _id’s to every row before handing the array over to the repeater.
In order to generate new _id’s, I use uuid.npm, (it generates same kind of unique id’s as wix-data does) e.g. like so:

//don't forget to add the NPM to your project

//And at the top of your code, put:
import { v4 as uuidv4 } from 'uuid';

//somewhere in a for loop (as in example) or a //forEach, where you got the new array

          let strNewId = uuidv4();
	     officerData[i]._id = strNewId;

//Now hand over array to repeater

Note:
If this works, you have actually changed the _id’s for the repeater, bypassing the caching. I do not know if you want the row to be clickable and zoom in per _id, but if so, you will need some extra coding. You need to put the old _id into the array too, before you change the _id, and onCLick, put in some code which uses the old _id per array entry, not the new one, to retrieve more data about the row/entry.

Does this make sense?

That’s a pretty clever way round it. In the end I gave up trying to manipulate the repeater data and started recreating it from the raw data. Thanks for your help.