Variables not resolving as expected in SSJS


#1

Matrix Version: 5.5.6.4

I am trying to us SSJS to print out a list of assets. It is not resolving the value of the matrix variables as expected.

If I print out the value of a js variable it shows as expected.

If I print out the length of a js variable is shows the length of the string containing the matrix variable that I used to get the value for js.

If I use any sort of check to see if a variable exists it gives an answer that implies it is using the unresolved string.

I did try using the empty modifier on internal, and then settign it to external if it was empty. That seemed to work and then it didn’t. Like at first it was resolving external first, and then it wasn’t and was trying to resolve internal before it was finished with external. I assume that’s a timing thing and so not something I should rely on anyway.

I would love to just get all the metadata for each link as an object, but I don’t know how to format the SSJS to use a js variable in a matrix variable that is not a string.

I can understand that it would have trouble resolving matrix variables that are replying on js variables, but surely there is some way to do this

This is the code I have currently.

<script runat="server">
    // ssjs helper functions are in #441534
        
        var component = 'quick-links-bar',
            namespace = '%asset_metadata_namespace%',
            asset = %asset_metadata_quick-links-bar.links%;
        
        if(asset.length > 0){
          
            print(`<div class="${component}_list">`);
            
            asset.forEach(function(id){
                var name = `%globals_asset_name:${id}%`,
                    iconId = `%globals_asset_metadata_quick-link-button.icon:${id}%`,
                    attr = `%globals_asset_metadata_quick-link-button.attr:${id}%`,
                    external = `%globals_asset_metadata_quick-link-button.external:${id}%`,
                    internal = `%globals_asset_metadata_quick-link-button.internal:${id}%`,
                    link = (internal) ? `./?a=${internal}` : external,
                    linkHtml = `<div class="${component}_item">
                        <a href="${link}" class="${component}_button">
                            <div class="${component}_button-container">
                                ${iconId ? `<div class="${component}_button-icon ${namespace}_button-icon">${helpers.icons.get(iconId)}</div>` : "" }
                                <div class="${component}_button-title ${component}_title">${name}</div>
                            </div>
                        </a>
                    </div>`;
                    print(linkHtml);
            });
            
            print('</div>');
            
          }
          
    </script>

(John gill) #2

A very common misunderstanding, here’s an earlier answer for the same question.

It’s also covered by the docs at https://matrix.squiz.net/manuals/concepts/chapters/server-side-javascript#processing-order. Everyone goes through this refinement of their mental modal of SSJS. It’s much simpler than you might think at first, but that ends up being a good thing.


#3

Typing out this question made me realise that’s what was going on. So I accept now that this is no the way to do it. But IS there a way to do it?


(John gill) #4

There’s no general solution to the limitations presented by keywords and SSJS being distinct phases, but most of the time you can get a long way with ^as_asset.

Anytime you have an array of assetids, instead of trying to loop over the IDs and construct new keywords, you just need to do all your data fetching up front with the array functionality of ^as_asset (https://matrix.squiz.net/manuals/keyword-replacements/chapters/keyword-modifiers#as_asset)

%asset_metadata_quick-links-bar.links^as_asset:asset_name,asset_metadata_quick-link-button.icon,asset_metadata_quick-link-button.external,asset_metadata_quick-link-button.internal,asset_url%

So instead of SSJS dealing with IDs, it’s dealing with an array of objects that already have the information you want.


#5

ah of course! get all those values instead of just getting the list of ids. So simple yet brilliant. Thanks so much!