Creating a list with a Dynamic Path?

Lambert Chan asked on June 14, 2019 22:30

I'm trying to create a list with a dynamic path, so the links that will show up in this list will be the first child of a first folder as new folder and children get added.

Currently I've tried to use /Year/Month/% to get a specific year and month but that isn't dynamic. I read in another post that /{0}/{0}/% might work but that just leaves me with null values.

I'm not sure what my next step to try to leave the path dynamic would be. Much thanks.

Note: The pages that I am trying to link to are published so that's a non-issue.

Correct Answer

Brenden Kehren answered on June 18, 2019 02:14

The "WHERE" you have elsewhere will NOT apply in the {%Documents%} macro. This is another query independent of the other one you have.

Try this in the Macro Console:

{%Documents["/Home/Folder1"].AllChildren.FirstItem.AllChildren.LastItem.NodeAliasPath%}/%

I belive the problem is you're not using AllChildren. Make sure when entering your path, you're using the macro arrow to enter it. Another issue may be that the path value is being SQL escaped. So you can try to add this macro parameter to the end of it:

|(handlesqlinjection)false

So your full macro would look like:

{%Documents["/Home/Folder1"].AllChildren.FirstItem.AllChildren.LastItem.NodeAliasPath|(handlesqlinjection)false@%}/%

0 votesVote for this answer Unmark Correct answer

Recent Answers


Brenden Kehren answered on June 15, 2019 11:05

Have you checked out the path expression documentation?

Your expression looks incorrect. Assuming your path is:

<root>/2019/june

Your path expression should be:

/{0}/{1}/%

Which will return:

/2019/June/%

What you have is:

/{0}/{0}/%

Which will return:

/2019/2019/%

Now assume your URL path is:

<root>/blog/2019/july

Your path expression should be:

/{0}/{1}/{2}/%

Which will return:

/blog/2019/june/%

1 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 17, 2019 19:16

Ah that makes much more sense on how the path expression works. So the value enclosed in brackets is the value of how far along the tree the child is and that value is also the first child.

Thanks!

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 17, 2019 20:22

It's a zero based index. It's a simple string.Format(). For example:

/{0} / {1} / {2}  

/blog/year/month

The string.Format() call would look like:

string url = string.Format("/{0}/{1}/{2}/%", "blog", "2019", "june");

0 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 17, 2019 21:40

I just retested that and it still doesn't quite work. If it is string format how do I ensure that the path is ("/{0}/{1}/{2}/%", "blog", "2019", "june")? and not ("/{0}/{1}/{2}/%", "blog", "2018", "may")? if the index only takes the index and not the first child?

Unless my understanding of string.format is still wrong. Much thanks, learning lots from your responses Brenden.

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 17, 2019 21:51

My apologies, I was simply explaining what was happening in the background, not for you to change the value in the path property. Keep the value as /{0}/{1}/{2}/%

This: string url = string.Format("/{0}/{1}/{2}/%", "blog", "2019", "june"); is C# code.

Further explanation, is if you're currently on /blog/2019/june/blog-post-1, your path in that repeaters path property will render /blog/2019/june/%. If you're currently on /blog/2018/may/blog-post-1, then the path property will render /blog/2018/may/%.

1 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 17, 2019 23:03

Yeah that's what I understood when I was reading the 'Writing Path Expressions' as the {0}/{1}/{2} is to extract part of the path that the page is currently on but what if the page that I'm currently on is /blog. How would I be able to determine the path to the children of blog dynamically?

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 17, 2019 23:05 (last edited on June 17, 2019 23:05)

Maybe provide a detailed use case of what you're trying to do.

0 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 18, 2019 00:43 (last edited on June 18, 2019 00:47)

I am trying to make the main page of the website have a list of articles that will automatically update itself every time a new 'article' sub page is created.

So if the main page is called Home, then organized into sub folders would be Home/Folder1 and then Folder1 would have sub pages organized by year/month, so Home/Folder1/2019/June and Home/Folder1/2019/May but I only want to show the 'articles' from the most recent (or first child) folder in this case Home/Folder1/2019/June.

I've considered Home/Folder1/{2}/{3}/% however this seems to take all articles under Home/Folder1 alternatively I've tried to use macros that I tested with the macro console such as Substring(DateTime.CurrentDate, 5, 4) to get the current year but that hasn't worked either.

An example with macro would be Home/Folder1/{% Substring(DateTime.CurrentDate, 5, 4) #%}/June/%

Edit: I should mention the path I'm typing this into is part of the repeater web part

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 18, 2019 00:55

Ok. So assuming you're working with dates or parts of dates, do this:

/home/folder1/{%CurrentDateTime.Year%}/{%FormatDateTime(CurrentDateTime, "MMMM")%}/%

1 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 18, 2019 01:06

I wasn't aware of the CurrentDateTime Macro which worked nicely, but if it was in the case that the folder weren't conveniently name after year/month (that you could get from current date time) is there a way to point the path to the first child folder?

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 18, 2019 01:28

In order for this to work:

/{0}/{1}/{2}/%

You have to be navigating to at least that 3rd level. The problem with your setup is you only ever get to the 1st level or /home.

So now you need to get creative and use another macro to find out the child levels and order it all on the node level and node order.

{%Documents["/home/folder1"].AllChildren.Where("ClassName = 'cms.folder'").OrderBy("NodeLevel, NodeOrder, NodeName").TopN(1).NodeAliasPath%}/%

Keep in mind, you might want to cache this webpart a bit more so it's not running every page load. Also, change the WHERE condition to whatever you need to for a classname/page type so you can filter it out a bit more.

If you want to test out your macros, go to System > Macros > Console and test the macro in there to see your expected results.

0 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 18, 2019 02:03

What I've tried so far with the macros to get the first item of the child is with the following /Home/Folder1/{%Documents["/Home/Folder1"].Children.FirstItem#%}/June/%

Alternatively I've attempted a substring through the absolute url but the path doesn't seem to be read.

Substring (Documents["/Home/Folder1"].Children.FirstItem.Children.LastItem.AbsoluteURL, 17, 40)

Both macros which I tested in the macro console and they gave me the values that I were looking for eg. 2019 for the year, June for the month but when I transfer that over to the Path macro field it doesn't work.

On other note I already have a Where statement in place to filter it out more as well as page type and categories.

Thanks once again

0 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 18, 2019 18:11 (last edited on June 18, 2019 18:19)

Thanks Brenden that worked, I modified it a little bit to get the children instead of the AllChildren after the first AllChildren and got what I needed as the second AllChildren.LastItem gave me the last 'article' page type instead of the last month folder which I was looking for!

{%Documents["/BT-(1)/Articles"].AllChildren.FirstItem.Children.LastItem.NodeAliasPath|(handlesqlinjection)false@%}/%

However with this macro it still doesn't restrict the files that are being taken with the SQL statement (eg. I want just 2019/June but if I request top 7 files and 2019/June only has 6 it takes in 2019/May as well) I assume this would be an sql issue?

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 18, 2019 18:15

Correct, this is why you add in the where condition I mentioned earlier. If, then you can look for specific page types in that Documents query.

Regarding the handlesqlinjection parameter, when you concatinate strings together this will be needed. For now, I'd suggest removing it as you're getting a valid URL and not concainating strings.

Interesting how this question evolved and how many answers I provided. :)

0 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 18, 2019 19:10 (last edited on June 18, 2019 19:14)

It's amazing how the question has evolved and I'm really grateful for the help but the core of the issue still doesn't work after testing unfortunately.

I've tried putting in the actual path /Home/Folder1/2019/June/% and that gives me just the pages in that June folder but when the moment I replace any part of that with a macro involving Document or requesting for children it feels as if the system reads null and pulls all the pages available which is why when I request for top 7 articles (even though there's only 6 in June) it'll pull from the previous or older pages as well.

An example: Documents["/Home/Folder1"].AllChildren.Where("ClassName = 'cms.folder'").OrderBy("NodeLevel, NodeOrder, NodeName").TopN(1).NodeAliasPath for example only gives me cms.document(0) when using the macro console.

And when I attempt to try to find just the current year by displaying the name with macro

Home/Folder1/{% CurrentDateTime.Year %}/June/% works as expected but Home/Folder1/{% Documents["/Home/Folder1"].AllChildren.FirstItem.DisplayName %}/June/% doesn't work even though in the macro console it shows up as 2019.

Even when replacing the macro with an additional where statement of

Home/Folder1/ {% Documents["Home/Folder1"].AllChildren.Where("ClassName = 'cms.folder'").OrderBy("NodeLevel, NodeOrder, NodeName").TopN(1).DisplayName %}/June/% doesn't work and just gives me cms.document (0) in the macro console.

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 18, 2019 19:15

Well what are all possible combinations of the folders directly below your main folder structure? I think you're trying to put no ownership on the content editors in which there should be. Simply tell the content editors/owners to order/place the most recent content in the top folder and get your content from that directory using the first child.

Trying to solve the world's problems with a single macro won't work.

0 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 18, 2019 20:07

The possible combinations of folders below the main should be just time and categories. for eg. Home/Folder1/Year/Month/CategoryFolder/Pages

I just want to make life a bit easier for the content editors where possible, they will be given guides on how to add content once the website is complete! I did manage to get something working now so thanks for all the help in this thread!

/Home/Folder1/{%CurrentDateTime.Year#%}/{% Documents["/Home/Folder1"].AllChildren.FirstItem.Children.FirstItem.DisplayName #%}/%

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 18, 2019 20:12

Don't use the DisplayName property as it's not URL friendly (there could be spaces in it). You want to use the NodeAlias property.

I'd say use the one which gets the year and month dynamically then get all the sub items and order by a date field. I'm afraid you're overcomplicating it and it won't work when something unique shows up.

0 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 18, 2019 20:39

Adjusted to using NodeAliasPath instead and for whatever reason this works exactly as intended now. {% Documents["/Home/Folder1"].AllChildren.FirstItem.Children.LastItem.NodeAliasPath #%}/%

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on June 18, 2019 20:47 (last edited on June 18, 2019 20:58)

So you're saying the reply you have marked as the answer works? It looks like the only difference is you're using .Children vs .AllChildren.

0 votesVote for this answer Mark as a Correct answer

Lambert Chan answered on June 18, 2019 20:54

Yup, I'm only getting the pages from that alias path now. I've been playing around with a few other things and something must have fixed whatever issue that may have been interfering with the code.

Learned a lot from this thread though about the macros and the way that the macros are being read. Thank you!

0 votesVote for this answer Mark as a Correct answer

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