Search code examples
javascriptaemhtl

How can I split AEM multifield component results from a string to an array


I created a custom component in AEM using the multifield functionality. However, it automatically places the values in a long string with commas in between.

I have gotten the values in an array using a custom JS file, but still can't figure out how to separate them or list them out.

I'm not sure if I can accomplish this inside the loop in my JS file or in the HTL file that is referencing the JS by using data-sly-repeat or data-sly-list

I would like each value to be a separate link tag with the value from the input as the href.

here's the js file:

"use strict";

use(function() {

  var csspath = properties["csspath"];

  var links = "";

  for(var i = 0; i < csspath.length; i++) { 

      links += csspath[i]
  }

  return {
      linkarray: links
  };

});

and the html that references it:

<sly data-sly-use.csslinks="csslinks.js" />

${csslinks.linkarray}

right now the html prints out simply

test1test2

but I want it to appear as

<link href="test1.css" />
<link href="test2.css" />

without the user having to actually input <link href=.... />

I have tried adding html syntax in the JS file like so...

for(var i = 0; i < csspath.length; i++) { 
    links += '<link href="' + csspath[i] + '.css" />'
}

and even just

for(var i = 0; i < csspath.length; i++) { 
     links += csspath[i] + "<br />"
 }

but it gives errors every time


Solution

  • I generally shun the WCM Use API in favour of Sling Models and I don't have an AEM instance at hand while writing this but here's some general tips you may find helpful.

    In the WCM Use code that you posted:

    "use strict";
    
    use(function() {
    
      var csspath = properties["csspath"];
    
      var links = "";
    
      for(var i = 0; i < csspath.length; i++) { 
    
          links += csspath[i]
      }
    
      return {
          linkarray: links
      };
    
    });
    

    you're building a string based on an array obtained from the page properties binding. Since you're aiming to build HTML elements anyway, this is an unnecessary step.

    Instead, return the array and iterate over it in your HTL script. HTL is where you should be building your presentation layer.

    "use strict";
    
    use(function() {
    
      var cssPaths = properties["csspath"];
    
      return {
          linkArray: cssPaths
      };
    
    });
    

    Then, in your HTL script, iterate over the array, rendering HTML.

    <link data-sly-use.csslinks="csslinks.js"
          data-sly-repeat.link="${csslinks.linkArray}" href="${link}" />
    

    Check out the documentation on data-sly-repeat.

    To make it even more simple, you could use the out-of-the-box properties binding and skip the WCM Use altogether. The type is not explicitly named anywhere in your JS or HTL code but properties saved in the content repository as string arrays (String[]) can be handled by HTL itself. If you're using granite/ui/components/foundation/form/multifield in the dialog, this should be sufficient:

    <link data-sly-repeat.link="${properties['csspath']}" href="${link}" rel="stylesheet" />
    

    Now, that explains how to achieve what you're trying to do in HTL... However, outputting CSS links this way seems like a dubious idea in the first place.

    Including CSS files generally isn't such a manual process on an AEM project. What you should do instead is organize your CSS into clientlibs, declare the dependencies in the component that renders the page and have AEM provide you with the right CSS and JS code.