Problems, need help? Have a tip or advice? Post it here.
14 posts Page 1 of 2
Hi,
I have a challenge that I can't quite figure out.
I'm building a site that works with tags, for which I've used a cloneable page - called lexicon.php. And I have one (possibly more in future) cloneable page with articles - called articles.php. The tags should serve as one possible form of navigation for all content on the site. I would like to output, under every article, the full list of entries in lexicon.php, but to be able to use css to style the ones that are related to the current article page.

Basically I want to output a full list of all the lexicon.php tags, and have their relation or non-relation in the classname of the link element.

Is it possible to do this with the related_pages / relations feature to check for the relation and have it output a Y/N or 1/0 boolean that would allow for the setting of a classname? As the pages tag (meaning the Couch tag cms:pages) iterates through all the items in lexicon.php?

Any help appreciated.
I suppose you have already established some relationship.
It will be fairly easy if you learn that <cms:pages> tag can accept negation in its parameters e.g.
Code: Select all
id = "NOT 1,2,3"
id = "NOT <cms:show my_listed_related_ids />"


So, basically step#1 is when you show related tags and build a comma-separated list of those ids in some temporary variable in the same loop. These related tags can be highlighted with your CSS. Next, using that list is step#2 - show all the rest tags excluding the ones that you had already listed in the first step (using the NOT-technique from example above). Apply other CSS for not-related tags here.

In the end there will be 2 loops total - first is <cms:related_pages>, second - separately just <cms:pages>. Hope it makes the task less complicated and does less server load.
Thank you, that does help.

Yes, sorry, I had already established the relation in the articles.php.

I forgot to add another condition, I want to output the list of tags in alphabetical order, and then highlight only the tags used on the current page. So outputting all tags omitting the active ones, and then outputting the active tags would not give me an alphabetical list.

I thought - based on searching the forum for different aspects of the problem - perhaps I should use capture into or turn the output somehow into a json variable, so that it can be resorted alphabetically?

And indeed the server load is relevant, so an approach that activates server side caching would be best.
JSON would definitely help.

In the first loop (the one with related_pages) create a simple couch array (thouroughly described in relevant topic viewtopic.php?f=5&t=10892 Do not output anything just yet.

The second loop should then list all tags in your preferred order with checking if a page is present in the pre-built array. I found this post with a good example (see ex.2 of code) viewtopic.php?f=4&t=12406#p34628 Your tag of choice is <cms:arr_val_exists>.
Excellent, thank you very much.

I need to take a closer look, but to get a rough idea, if I'm correct I'd need to construct it something like this:

1. first create a json variable, with the temporary purpose of matching values (tags) from the first loop with those of the second.

Code: Select all
cms:set tags.current='[]' is_json='1' 


2. first loop with related_pages to fill the json variable with the names of active tags.

Code: Select all
cms:related_pages

iterates through all lexicon.php tags related to the current page of articles.php
for each of the tags, adds it to a json variable tags.current.IDnr

/cms:related_pages


3. run through all tags (all pages belonging to lexicon.php), match them with the values in the json, and output links with or without the classname 'active'

Code: Select all
cms:pages iterates through lexicon.php tags

for each k_page_id, it checks
if current id is found in the created array of active tags, i.e. if tags.current.IDnr has a value
if so, outputs a link with 'active' as the classname; if not: no classname
<a href="k_page_link" class="active">name of the tag</a>

/cms:pages



My only problem is in my earlier tests, I didn't manage to get cms:related_pages to output an ID number for related pages. To my understanding I would need to use the ID (in the third segment of the json variable in loop #1) to pull the right value from the json during the second loop, to match it with the values of all tags that loop #2 produces.
I didn't manage to get cms:related_pages to output an ID number for related pages


OK, I sorted this out, but the remaining issue is how to set a value for the json variable using the ID in the name for the sake of matching.

I had this:

Code: Select all
<cms:set tags.current.<cms:show k_page_id />nr='<cms:show lexicon_item />' />


But this gives me an error for "invalid character '<'" - how instead can I include the ID into the name of the variable?

I included the letters "nr" behind the ID to ensure that this segment of the variable is not just numbers, but I'm not too well versed in json, so this could be wrong?
@Thijs, the <cms:set> tag expects a simple variable whereas you are trying to 'craft' a variable name by concatenating different values.
Please see https://docs.couchcms.com/tags-reference/get.html if the difference is unclear.

Anyway, just like <cms:get> (discussed in the linked thread above) is the counterpart of <cms:show> for cases where simple variable names do not suffice, the <cms:set> tag also has its counterpart - it is the <cms:put> tag.
Code: Select all
<cms:put 'my_variable' value='hello world' />

Using it, your code could become as follows -
Code: Select all
<cms:put "tags.current.<cms:show k_page_id />nr" value="<cms:show lexicon_item />" />

Hope this helps.
KK wrote: @Thijs, the <cms:set> tag expects a simple variable whereas you are trying to 'craft' a variable name by concatenating different values.
Please see https://docs.couchcms.com/tags-reference/get.html if the difference is unclear.

Anyway, just like <cms:get> (discussed in the linked thread above) is the counterpart of <cms:show> for cases where simple variable names do not suffice, the <cms:set> tag also has its counterpart - it is the <cms:put> tag.
Code: Select all
<cms:put 'my_variable' value='hello world' />

Using it, your code could become as follows -
Code: Select all
<cms:put "tags.current.<cms:show k_page_id />nr" value="<cms:show lexicon_item />" />

Hope this helps.


Super, thank you very much for the clarification, just what I needed.
When focus is on code simplicity and better page load times there is no need in complex multi-level arrays. Following is the essential barebone code which works very quickly -

Code: Select all
<cms:set related = '[]' is_json='1' scope='global'/>
<cms:related_pages 'relation_tags' skip_custom_fields='1' >
    <cms:set related. = k_page_id scope='global'/>
</cms:related_pages>


<cms:pages masterpage='tags.php' order='asc' skip_custom_fields='1' >
    <cms:if "<cms:arr_val_exists k_page_id in=related />">
        I found a match
    <cms:else />
        I found no match
    </cms:if>
</cms:pages>
trendoman wrote: When focus is on code simplicity and better page load times there is no need in complex multi-level arrays. Following is the essential barebone code which works very quickly -


Thank you @trendoman, this is definitely much more efficient than my attempted roundabout code, and does perfectly what it's supposed to.

I somehow didn't manage to get cms:put and cms:get to work in adding my crafted values to an array variable. Not sure what went wrong in my code there, but I can't get either to output anything.

This is what I had (some terms/templates here are different from what I posted before, as I tried to strip it down to make it work before applying it). If either of you can easily spot what the problem is, that would help me along for next challenges.

And many thanks for your help, both.

Code: Select all
<cms:set activetags='[]' is_json='1' />

<!-- fetch tags related to this page -->
<cms:related_pages >
<cms:put "activetags.<cms:show k_page_id />nr" value="active" />
 
</cms:related_pages>
   
<h3>Show all tags:</h3>
<cms:pages masterpage='has_tags.php' orderby='one_tag' order='asc'>

<a class="<cms:get 'activetags.<cms:show k_page_id />nr' />" href="<cms:show k_page_link />"><cms:show one_tag /> </a>
</cms:pages>
14 posts Page 1 of 2