Fully Coded Line Item Repeater

Question:
I’m learning how to code and have run into an issue with a repeater that I would love some help with.

Product:
Wix Studio Editor

What are you trying to achieve:
I am trying to create an order form that features a repeater with various text input fields that expands items in the repeater with an add button and removes them (except for the first item) with a remove button. Essentially creating line items for the order and submitting each line item as its own separate entry into the associated database collection.

What have you already tried:
I have tried utilizing the resources available through WIX dev, Google, and ChatGPT and have what I believe is working code, but the repeater does not visually update or refresh either in the editor preview or on the published site. I have included a debug counter in my code which shows the refreshing and adding new items, but that is not reflected visually.

None of the elements within the repeater, or the repeater itself, is connected to a dataset, as I believe the code is handling those connections.

Additional information:
Here is the current code I am working with:

import wixData from ‘wix-data’;

let lineItems = ;

$w.onReady(() => {
console.log(“[onReady] Page is ready”);

// Initialize with one blank item
lineItems = [createEmptyItem()];
console.log(“[onReady] Initialized lineItems with one item:”, lineItems);
refreshRepeater();

// Add new line item
$w(‘#addLineBtn’).onClick(() => {
console.log(“[addLineBtn] Add Line button clicked”);
lineItems.push(createEmptyItem());
console.log(“[addLineBtn] New item added. Total items:”, lineItems.length);
refreshRepeater();
});

// Submit all items to collection
$w(‘#submitBtn’).onClick(() => {
console.log(“[submitBtn] Submit button clicked”);
console.log(“[submitBtn] Submitting items:”, lineItems);
submitLineItems();
});

// Handle each item when the repeater renders
$w(‘#lineItemRepeater’).onItemReady(($item, itemData, index) => {
console.log([onItemReady] Rendering line item ${index}, itemData);

// Set initial values
$item('#graphicNameInput').value = itemData.graphicName;
$item('#qtyInput').value = itemData.qty;
$item('#widthInput').value = itemData.width;
$item('#heightInput').value = itemData.height;
$item('#tileTypeInput').value = itemData.tileType;
$item('#tileColorInput').value = itemData.tileColor;
$item('#pmsCodesInput').value = itemData.pmsCodes;

// Track input updates
$item('#graphicNameInput').onInput((e) => {
  console.log(`[onInput] graphicName changed on item ${index}:`, e.target.value);
  lineItems[index].graphicName = e.target.value;
});
$item('#qtyInput').onInput((e) => {
  console.log(`[onInput] qty changed on item ${index}:`, e.target.value);
  lineItems[index].qty = e.target.value;
});
$item('#widthInput').onInput((e) => {
  console.log(`[onInput] width changed on item ${index}:`, e.target.value);
  lineItems[index].width = e.target.value;
});
$item('#heightInput').onInput((e) => {
  console.log(`[onInput] height changed on item ${index}:`, e.target.value);
  lineItems[index].height = e.target.value;
});
$item('#tileTypeInput').onInput((e) => {
  console.log(`[onInput] tileType changed on item ${index}:`, e.target.value);
  lineItems[index].tileType = e.target.value;
});
$item('#tileColorInput').onInput((e) => {
  console.log(`[onInput] tileColor changed on item ${index}:`, e.target.value);
  lineItems[index].tileColor = e.target.value;
});
$item('#pmsCodesInput').onInput((e) => {
  console.log(`[onInput] pmsCodes changed on item ${index}:`, e.target.value);
  lineItems[index].pmsCodes = e.target.value;
});

// Remove line item
$item('#removeLineBtn').onClick(() => {
  if (index > 0) {
    console.log(`[removeLineBtn] Remove clicked on item ${index}`);
    lineItems.splice(index, 1);
    console.log("[removeLineBtn] Item removed. New length:", lineItems.length);
    refreshRepeater();
  } else {
    console.log("[removeLineBtn] First item cannot be removed.");
  }
});

});
});

function createEmptyItem() {
const blank = {
graphicName: ‘’,
qty: ‘’,
width: ‘’,
height: ‘’,
tileType: ‘’,
tileColor: ‘’,
pmsCodes: ‘’
};
console.log(“[createEmptyItem] Created new empty item:”, blank);
return blank;
}

function refreshRepeater() {
console.log(“[refreshRepeater] Refreshing repeater with items:”, lineItems.length);

const freshCopy = JSON.parse(JSON.stringify(lineItems));
$w(‘#lineItemRepeater’).data = freshCopy;

// Update debug counter text
$w(‘#debugCounter’).text = Total Items: ${lineItems.length};
}

function submitLineItems() {
console.log(“[submitLineItems] Submitting line items:”, lineItems);

const insertions = lineItems.map(item => {
console.log(“[submitLineItems] Inserting item:”, item);
return wixData.insert(“Graphics”, item);
});

Promise.all(insertions)
.then(() => {
console.log(“[submitLineItems] All items successfully inserted.”);
lineItems = [createEmptyItem()];
refreshRepeater();
})
.catch(err => {
console.error(“[submitLineItems] Error submitting items:”, err);
});
}

And here is a link to the order form on the published site: https://www.gomhf.com/orderform

Always go through the code documentation first which mentions any necessary steps and contains example snippets for the element’s functionality - which in your case is Repeaters.

As mentioned in the documentation (The Lifecycle of Repeated Items):

Each object in the array must contain a unique _id property which is used to match the object’s data to the individual repeated items of the repeater as described below. The value of the _id property can only be comprised of alphanumeric characters and hyphens (- ). Other than _id , the objects in the repeater’s data array can contain anything you want.

In your code I don’t see an _id being assigned while creating a new item, which is why your count is increasing, but the repeater isn’t functioning as it should.

2 Likes

Good-catch! :ok_hand:

1 Like

Hey Pratham! Thank you so much for the quick reply to my question. I read through the documentation you sent over and learned a ton from it. I have now implemented new code using unique ID’s and it seems to be working flawlessly. The repeater is expanding/contracting as it should and the data entered in each line item on the repeater is being treated as a separate line item in my collection.

I am still trying to overcome a few hurdles on this page code, but this specific issue has had me stumped for days now. I sincerely appreciate you taking time out of your day to lend a hand and point me in the right direction.

1 Like