aemrepeatsightlyhtl

AEM multifield data-sly-repeat ${item} not working


This has been driving me nuts - hoping someone can help me.

I have a multifield component called 'books' with a single textfield: 'title'.

Everything seems to be working; the dialog box contains the multifield then I add two title fields then enter 'title1' and 'title2'.

then in the HTML itself I go:

<div data-sly-repeat="${properties.books}">
  <p>${item}</p>
  <p>${itemList.index</p>
  <p>${item.title}</p>
</div>

What I don't get is, ${item} correctly gives me: {"title": "title1"} {"title": "title2"}

and ${itemList.index} correctly gives me: 0 1

but ${item.title} keeps coming up blank. I also tried ${item["title"]} and that comes up blank too.

What am I doing wrong here? In my desperation I contemplated using

<div data-title="${item}"></div>

and then using JS to process the JSON object but I don't really want to do that.

Someone help, please!


Solution

  • It looks like your books property is either a JSON array string or a multivalued property with each value being a JSON object string;

    The easiest way to parse the property is via a JS model like the following:

    You could simplify this script to match your specific case, I made it general to multi-value and non-multi-value string properties.

    /path/to/your-component/model.js:

    "use strict";
    use(function () {
    
        // parse a JSON string property, including multivalued, returned as array
        function parseJson(prop){
            if(!prop) return [];
            var result =[];
            if(prop.constructor === Array){
                prop.forEach(function(item){
                    result.push(JSON.parse(item));
                });
            }
            else {
                var parsed = JSON.parse(prop);
                if(parsed.constructor === Array){
                    result = parsed;
                }
                else result = [parsed];
            }
            return result;
    
        }
    
        var $books = properties.get("books", java.lang.reflect.Array.newInstance(java.lang.String, 1));
        var books = parseJson($books);
    
        return {
            books: books
        }
    
    });
    

    /path/to/your-component/your-component.html:

    <sly data-sly-use.model="model.js"/>
    <div data-sly-repeat="${model.books}">
      <p>${item}</p>
      <p>${itemList.index</p>
      <p>${item.title}</p>
    </div>