Get Closest Parent's Field Value in Macro Expression

Siavash Mortazavi asked on October 22, 2018 15:48

Hi,

I've added a new HeaderImage field to the Page Menu Item type, and I have a hierarchy of menu item pages in content tree.

I would like to be able to show the HeaderImage on a page, if it is selected for the page, or get the HeaderImage of closest parent (of type PageMenuItem) in the hierarchy of nodes, up to the root.

Is it possible to achieve this in a macro expression? If not, what is my best option?

Thank you very much! :-)

Correct Answer

David te Kloese answered on October 23, 2018 10:29

So you basically want to 'bubble-up' your tree till you find a page that has data in this field?

I would create a dedicated Custom Web Part for this so you can do it directly in code. If it's a macro in generic location you could look into creating a custom macro. This way it's still in code but you can use it throughout the whole system.

In case you can't or won't want to update code you could use a while loop in a macro:

{%
    curDoc = CurrentDocument;
    imgBackground = "";
    while( curDoc != null)
    {  
      imgBackground = curDoc.GetValue("YourField", "");
      if(!String.IsNullOrWhiteSpace(imgBackground))
      {
        return(imgBackground);
      }
      curDoc = curDoc.Parent;
    }
    return "guess it's empty"; 
#%}

Not fool proof yet, but should get you started. Remember this isn't efficient at all and I would recommend to at least cache the page or part of the page this is rendered on.

0 votesVote for this answer Unmark Correct answer

Recent Answers


Brenden Kehren answered on October 23, 2018 01:02

You can use something like

{%CurrentDocument.Parent.GetValue("ColumnName", "")%}

0 votesVote for this answer Mark as a Correct answer

Siavash Mortazavi answered on October 23, 2018 15:13

Thank you all, David te Kloese's answer is very close to what I want. I actually reached almost the same solution as David yesterday, just with little differences:

{%
headerImageSrc = "";
current = CurrentDocument;

while( current != null ) 
{  
    if (current.NodeClass.CodeName == "CMS.MenuItem")
    {
        headerImageSrc = current.GetValue("HeaderImage","");
        if(headerImageSrc != "") {break};
    }
    current = current.Parent;
}

// use the image src here

#%}

Thank you all again, I'm going to mark David's reply as the answer. ;-)

0 votesVote for this answer Mark as a Correct answer

Siavash Mortazavi answered on October 23, 2018 17:41

Here is my final solution, for anyone who wants to do the same:

{%
headerImageSrc = "";
current = CurrentDocument;

// This code bubbles up from current node to the root
// and for nodes of type Page Menu Item, if the header image 
// is not already populated from a more recent note, tries to read it from the current note
while( current != null ) 
{  
  if (current.NodeClass.CodeName == "CMS.MenuItem")
  {           
    if(String.IsNullOrWhiteSpace(headerImageSrc)) 
    {
      headerImageSrc = current.GetValue("HeaderImage","");
    }
  }
  current = current.Parent;
}

// Finally, if header image and header description are empty, read the values from Global Settings node
if(String.IsNullOrWhiteSpace(headerImageSrc))
{
  headerImageSrc = Documents["/Special-Items/Global-Settings"].DefaultHeaderImage;
}

// if you don't add this return, macro will return (and render) the result of last statement as literal, which is headerImageSrc in this case
return null;

#%}
<img src="{% headerImageSrc %}" alt="{% DocumentName %} Header Image">
0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.