Select and reorder view template items on a per tiddler basis

Over recent releases we have had options to allow preview and a sticky info tab to be set on a per-tiddler basis. I would like to develop a solution that allows us to;

Show/Hide and reorder view template items on a per tiddler basis

For example:
Imagin you have a range of viewtemplate items that appear on project tiddlers, say a projectify project, it includes new todos, list of todos, a Project references list, a field editing tool etc…

  • What if you have one project where you want the add todo at the top but don’t want the other features visible?
  • It would be nice if you could customise this particular, and any project tiddler, to only show a subset of these features and/or change the order.

But how?

However the view template on tiddlers involves multiple tiddlers with the tag $:/tags/ViewTemplate and this has being the traditional way for plugins and solutions to add features to the view template. Although we have the cascade features the view template is the standard way to introduce features to tiddlers. Similarly the edit template with $:/tags/EditTemplate.

  • It is possible to make items delivered through the view/edit templates display on a conditional basis, however to allow it to be customised for each tiddler, each view template item (from multiple designers) needs to store this toggle state, to do this we have to modify each view template item.

Do you know any design or code patterns we may use to introduce such a feature to apply generally to any view or for that matter edit template?

  • I have some ideas, but they are somewhat complex and wonder if anyone else has considered this?

My first question would be whether you would want to do this by listing the changes to the default template ordering it would otherwise have or to list a completely custom new order for the tiddler. I think the latter would be much easier to work with, but might not be as flexible as you would like.

Although I have no idea what core code would be necessary to handle this, how we might configure it seems clear enough. Right now the templates are ordered according to the list field on $:/tags/ViewTemplate If we added a field view-template-list to specific tiddlers, the core mechanism could check for that field first and if it’s not there, use the default one.

I can imagine a toolbar button that launches a dialog which starts with the default list but lets you add, remove, and rearrange templates, storing the result in such a custom field.

I have a hard time seeing how this could be done without core changes, but somehow better versed in the cascades might be able to suggest something.

1 Like

As an experiment, without regard to any potential performance-related costs, I just tried this:

Edit TWCore shadow $:/core/ui/ViewTemplate, and change this line:

  • <$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem">

to this:

  • <$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]sortby{!!view-template-list}]" variable="listItem">

(i.e., add sortby{!!view-template-list} to the end of the filter)

Next, open TWCore shadow $:/tags/ViewTemplate and copy the contents of the list field to the clipboard.

Then, in the target tiddler (e.g. “HelloThere”) , add a field named view-template-list and paste the list field contents from the clipboard. Re-order this list to place the list items in the desired order (e.g., move $:/core/ui/ViewTemplate/subtitle to the end of the list).

The result is that the order specified in the view-template-list is applied to the target tiddler (e.g., the subtitle content appears at the bottom of the tiddler).

AND… for a more elaborate customization… edit TWCore shadow $:/core/ui/ViewTemplate, and replace these lines:

<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]" variable="listItem">
<$transclude tiddler=<<listItem>>/>
</$list>

with these lines:

<$list filter="[all[shadows+tiddlers]enlist{!!view-template-list-before}]" variable="listItem">
<$transclude tiddler=<<listItem>>/>
</$list>
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]sortby{!!view-template-list}]
   -[enlist{!!view-template-list-before}] -[enlist{!!view-template-list-after}]" variable="listItem">
<$transclude tiddler=<<listItem>>/>
</$list>
<$list filter="[all[shadows+tiddlers]enlist{!!view-template-list-after}]" variable="listItem">
<$transclude tiddler=<<listItem>>/>
</$list>

This provides a similar effect to the previous change, but also lets you specify custom view-template-list-before and view-template-list-after fields.

Thus, if all you want to do is to move particular view template items to the start or end of the tiddler, you just need to provide the appropriate view-template-list-before or view-template-list-after field that contains those view template items, without needing to create a view-template-list field containing all the other template items.

Template items not otherwise listed will appear in their default order, following the view-template-list-before items, and preceding the view-template-list-after items.

enjoy,
-e

2 Likes

Thanks you gentlemen. I have being thinking along those lines. If possible allowing;

  • standard items excluded from display
  • a Standared item be duplicated eg add item above and below a long body
  • additional custom view elements
    • the trickiest bit is to place these an a particular position relative to the above.
  • I would like to handle include and exclude items if possible, rather than copy the entire view template tag field because my core wiki has around 50 items in this list. Most are conditional.
    • but maybe this is unnessasary.

I think a conditional cascade for the story tiddler that triggers a modified view template for only those tiddlers with a customised view template may make sense?

I am also wondering if a list could be built in a variable to which we build with multiple steps?

Still brainstorming

You can use the ViewTemplate Cascades, with which you can do everything without any change to the core. The $:/tags/ViewTemplate mechanism is still working, but a bit outdated.

1 Like

I agree, but one of the issues is I want still to honor the use of the view template tag that other plugins and solution make use of.

  • This would require the Story Tiddler Cascade with the inner ViewTemplate handling modified - which is plausible
  • Or modify $:/config/ui/ViewTemplate to point to an alternate $:/core/ui/ViewTemplate

So “state of play” in my mind;

  • Take a copy of $:/core/ui/ViewTemplate and modify the way it iterates the items transcluded for all tiddlers
  • Design this to honor the default behaviours, yet introduce these new features such as include and exception lists and a sortby field or transclusion.
  • Perhaps the ability to use a set of order operators such as insertbefore or insertafter (New in: 5.2.3) and possible not used much yet.

Thanks all for your new and confirmatory ideas, I am still searching for a fully flexible easy to manage solution.

I have added the following lines to $:/core/ui/ViewTemplate and modified the key list widget as follows;

\define ViewTempateItems() [all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]
\define ViewTempateInclude() [enlist{!!ViewTempateInclude}]
\define ViewTempateExclude() [enlist{!!ViewTempateExclude}]
\define ViewTempateSortby() [sortby{!!ViewTempateSortby}]
...
<$list filter="[subfilter<ViewTempateItems>] [subfilter<ViewTempateInclude>] -[subfilter<ViewTempateExclude>] +[subfilter<ViewTempateSortby>]" variable="listItem">
<$transclude tiddler=<<listItem>>/>
</$list>

@EricShulman using the above if the view-template-list field only contains $:/core/ui/ViewTemplate/tags then it happens to be move to the bottom;

  • If I use $:/core/ui/ViewTemplate/subtitle $:/core/ui/ViewTemplate/tags they too appear in the requested order but at the bottom.
  • I need to understand if I can make better use of sortby without having to include all tiddlers in in its list.
  • Issue here is can we get the sortby to operate from the top down, ie items listed in sortby are placed at the top of the tiddler, so you need to include each item before it, to position it?

More thoughts

  • Perhaps we need to ask if there should be an above body and below body location that tiddlers can be placed and sort these two areas with their own sortby, but perhaps this breaks too much for solutions not aware of these “positions”.
  • In some cases we can use position absolute to position content, one example is in my key wiki I have placed the start rating above the toolbar buttons
    Snag_1d2c940

I’d love to see where this goes, but am worried about how this whole notion will interact with plugins. If you add some field in here for a particular tiddler, and position it to the very top, as you always want it first, what happens when you now add a plugin that also wants to be first. When you wrote the tiddler, it didn’t know about the plugin, so it cannot position itself relative to it. You can go back and do it now, but you’d have to do that for every tiddler that you have altered this way. It sounds ugly. And I’m having a hard time coming up with a generic method that works. before and after help, but they wouldn’t solve the “always put this right after the title”, if the plugin really wants to claim that spot.

I don’t think this is impossible, but it does get tricky rather quickly.

@Scott_Sauyet you have discovered where my question comes from, the core behavior is quick dynamic and flexible but based around application to all tiddlers, although each independent item within the template can contain its own conditions, if you change its position you do so for all tiddlers.

  • It does get tricky quickly, then simplified, then tricky again :nerd_face:

The method I have come up with basically allows you to specify exceptions, inclusions and preferred order for a specific tiddler only. If a new Plugin tiddler is added it still gets it in position at display time then applies the “exceptions, inclusions and preferred order”. It’s not perfect, but is most of the way to a complete solution.

  • I was going to publish a finished solution tonight, but I was getting some unexplained behaviour on one complex wiki, and my focus/energy ran out.
  • The only feature in my current release I am yet to add is to allow you to duplicate an item already in the view template, and place it in another position. At the moment I will have to clone it and wrap it in a condition.

In future I would like a complex set of parameters to be applied programmatically, for example, on all project tiddlers apply a shared list of “exceptions, inclusions and preferred order”.

It will place it in the correct position on tiddlers where you have not changed the sort order, and may often on ones you have. It should however always appear. Although I have not done comprehensive testing. yet.

2 Likes

I am not sure if many, if anyone is interested, but my research effort continues;

Another Idea for a mechanism, at least to toggle elements in the view template from display is for each tiddler so tagged $:/tags/ViewTemplate to specify its own “display-filter” not inside the tiddler, but in a field or qualified tiddler, however allow that display filter to be overridden.

For example
If a view template element had a display-filter field eg [all[current]] it would always display, for a project view it may have [all[current]tag[project]] and only display if tagged project.

  • All tiddlers without any display-filter are also displayed
  • For core tiddlers we could also check for $:/display-filters/tiddlername so we need not edit them.

Whilst the above duplicates the result you get if the viewtemplate wraps its own content with a condition;

<$list filter="display filter" variable=~>
tiddler content

</$list>

the difference I propose means,

  • This is tested in the view template iteration
  • We can then also test for a $:/display-filters/elementname

And we can extend this to allow local tiddler override of the display filter. Thus allowing us to set a different display filter for any viewTemplate element on any tiddler.

  • This may use a test for a <<qualify $:/display-filters/elementname>>