Date Format In A Repeater

Hi folks. I am trying to format a date field in a repeater. I got the code straight from a post Wix published ( Velo: Formatting Dates | Help Center | Wix.com) but support team won’t help as I am “custom coding”. On the surface it seems the code should work, but it’s not. My first inclination is that it has something to do with being within a repeater. The URL for my dev site is:

https://danceconnectionpcfl.wixsite.com/dcdev/team-events

Can someone guide me here? If I link the datestamp field directly, my date comes back like " Sun Nov 18 2018 13:00:00 GMT-0500 (Eastern Standard Time) ". I don’t need all that, and I don’t want to confuse any site visitors so I need it to look like “10/18/2018 1:00PM”.

When I unlink the field to make my code active and preview the page, I get this JavaScript error:

TypeError: Cannot read property ‘event_date’ of null

My code as currently stands:

$w.onReady( function () {
// Get the date from the date field of the current item
const date = $w(“#dataset1”).getCurrentItem().event_date;
// Set the text element to display the date using the user’s settings
$w(“#text21”).text = date.toLocaleDateString()
});

Thanks in advance!!

Nevermind, I came across another post that solved this issue. Thanks!!

Can you post the corrected code? I have the same issue.

@danceconnectionpcfl can you help me see how to solve the problem, or pass me the solution link?

My guess is that the dataset wasn’t ready before trying to access the date field.

I would start by putting the $w(‘#dataset1’).currentItem().event_date assignment in a $w(‘#dataset1’).onReady() call and not access the record until the dataset has finished loading.

If the date was displaying correctly in preview and not on the live site then the data collection probably wasn’t synchronised to live or there was a permissions problem.

I have a code that works for items but it does not work on repeaters, if someone can adapt it to work on repeaters let me know, thanks.

var options = { year: 'numeric', month: 'short', day: 'numeric', weekday: 'long' };

$w.onReady(function () {
 // Get the date from the date field of the current item
 const date = $w("#dynamicDataset").getCurrentItem()._createdDate;
 // Set the text element to display the date using the user's settings
 const option = {
        day: "numeric",
        year: "numeric",
        month: "short",
        weekday: "long"
    };
 // Sets the property of the text element to be a string representing today's date in US English
    $w("#text15").text = date.toLocaleDateString("pt-BR", options);
});

Hi VC:

The primary thing you need to do is read and understand the repeater API docs:

If you think in terms of a web page Document Object Model (DOM) the elements are added to a page in a hierarchical fashion:

<HTML>
    <HEAD>
    </HEAD>
    <BODY>
        <DIV ID='REPEATER_LIST'>
            <LI ID='REPEATER_LIST_ITEM_0'>
                <IMG ID='REPEATER_LIST_ITEM_0_IMAGE_ELEMENT'>
                </IMG>
                <SPAN ID='REPEATER_LIST_ITEM_0_TEXT_ELEMENT'>
                </SPAN>
            </LI>
            <LI ID='REPEATER_LIST_ITEM_1'> 
                <IMG ID='REPEATER_LIST_ITEM_1_IMAGE_ELEMENT'>
                    </IMG>
                <SPAN ID='REPEATER_LIST_ITEM_1_TEXT_ELEMENT'>
                </SPAN>
             </LI>
        </DIV>
    </BODY>
<HTML>

Now Wix manages the DOM using a scope variable which you will know as $w. Think of $w as meaning “all elements contained in the BODY element”. So $w(‘#REPEATER_LIST’) provides a scope for all of the elements contained in the REPEATER_LIST element.

To access the items in the repeater we need to have a function that helps walk through the elements in the REPEATER_LIST. If you read the API docs you will see the following:

Repeated Item Scope
There are two instances where you get a repeated-item-scope selector:
The $item parameter of the forEachItem(), forItems(), and onItemReady() event handlers.
When calling the $w.at() and passing it an event whose context is "COMPONENT_SCOPE". This is usually done in an event handler that handles event on an element inside a repeater.

A selector with repeated item scope can be used to select a specific instance of a repeating element.

For the purposes of this question we need to walk through the repeater list and display the appropriate date. There are three methods for doing this as described above. The easiest one to use is forEachItem().

The forEachItem function syntax looks like this:

function forEachItem(callback: ForItemCallback): void

callback: ForItemCallback($item: $w, itemData: Object, index: number): void

callback is an argument that needs to be a function. The function could be a named function with the arguments described by the callback:

function functionName($item, itemData, index) {
    // Do something with the item passed when we get called
}

// Process repeater items...
$('#REPEATER_LIST').forEachItem(functionName);

OR callback is an anonymous function pass directly as a parameter:

// Process repeater items

$('#REPEATER_LIST').forEachItem(($item, itemData, index) => {
  // Do something with the item passed when we get called
});

So as the repeater iterates through the DOM it creates a context that your code needs to have to process the repeater item. So the arguments do this for us:

$item    -> provides the scope of elements for the current item being processed
itemData -> provides the data from the dataset page that is currently loaded in the dataset
index    -> tells us which item in the dataset we are working with

So as the forEachItem() function walks through the dataset list it essentially creates a short hand for REPEATER_LIST.ITEM_. So when index == 0 the $item scope variable points to $w(‘#REPEATER_LIST_ITEM_0’). Then we can simply work with the elements (‘#IMAGE_ELEMENT’), and (‘#TEXT_ELEMENT’) knowing that we are working with the correct repeater item. Pseudo-code for how this works might look like:

    NOTE: DO NOT USE THIS CODE IT SHOWS CONCEPTUALLY HOW TO THINK ABOUT THE WAY A REPEATER WORKS
    
    let itemList = $w('#dataset1').loadedItems
    for (let index = 0 ; index < itemList.length ; index++ ) {
        let $item = $w('#REPEATER_LIST_ITEM_'+index.toString());
        // Call forEach callback function for this item
        callback($item, itemList[index], index);
    }

So the call to your named function functionName() described above would look like:

functionName($item (= $w('#REPEATER_LIST_ITEM_0')), item (= itemList[0]), index (= 0))

Now when you use $item(‘#IMAGE_ELEMENT’) you are actually accessing $w(‘##REPEATER_LIST_ITEM_0_IMAGE_ELEMENT’) and $item(‘#TEXT_ELEMENT’) is $w(‘#REPEATER_LIST_ITEM_0_TEXT_ELEMENT’);

OK so how do we manipulate the date in a repeater? We use the repeater forEachItem function like this (assumes that dynamicDataset is bound to the repeater1 element in the Wix Editor):

$w.onReady(function () {
    // Wait for the dataset to be ready
    $w("#dynamicDataset").onReady(() => {
        // Dataset has changed or initialized
        // Walk through the loaded dataset in the repeater
        // We'll use a named function for this example
        $w("#repeater1").forEachItem(updateRepeaterItem);
    });
});

// updateRepeaterItem is called by forEachItem to populate a repeater item
function updateRepeaterItem($item, itemData, index) {
    // Get the date from the date field of the current item
    const date = itemData._createdDate;
    // Set the text element to display the date using the user's settings
    const options = {
        day: "numeric",
        year: "numeric",
        month: "short",
        weekday: "long" };
    // Sets the property of the text element to be a string representing today's date in US English
    $item("#text15").text = date.toLocaleDateString("pt-BR", options);
} 

Et voila!

Hope this helps!

Steve