I’ve created agents to count the number of pages, elements and questions (pre-and post-login) for a site project I’m working on. In a summary note, I want to pull in the count numbers and include them in the summary note’s $Text. Is there a way to do this? For example, ^value(NoteName,$MyString), where NoteName is the name of the note I want to pull the $MyString attribute value from.
Read, test, and get familiar with ^include()^.
^value()^ takes a expression – the form you suggested is incorrect – and might also be used.
When making complex exports, it is advisable to create small test files to work out the best approach to different parts of the export. Including values from other notes is a powerful feature, but in my experience getting it right takes trial and error.
Thanks, Paul. Took my a while to understand this (see notes below showing my test). Thanks for pushing me to “Read, test, and get familiar…”
The include seems to only return the $Name and $Text for the included note when what I want is a single attribute for the included note, e.g. $ChildCount or $MyString . Is this possible?
^include() can specify a template to use for the include, so you can set up a special template with the values you want.
Alternatively, ^value($ChildCount(/that/other/note)) will fetch the child count of a specified note.
In dashboards, you can include this in display expressions or in rules:
Thanks. That works, but this does not scale well when I want to pull stats from multiple other notes, about eight. This method would require that I create 8 unique attributes for my note for each of the different stats that I want to pull in. I was really hoping that I could just pull them from the other notes directly and not have to use the interim step of the extra attributes. At least, this is how I understand my current situation.
Can an include pull the results of an agent?
Here’s a small example.
/My Data contains the notes and summarizes the value of $MyNumber in those notes into $SumMyNumber
/My Report is the “dashboard”
The template /Templates/My Template is applied to /My Report and uses this export code
Sum of MyNumber: ^value($SumMyNumber(/My Data))^
Note: You could use an agent to collect information – make sure that the agent uses a Rule to summarize the data from the aliases inside the agent. Do not use an Action in the action for that, since Actions apply to the found notes in the agent, not to the agent itself. Here’s the Rule for the agent, or for /My Data
The sample file uses both in /My Report
Export Test.tbx (94.6 KB)
[sorry this coincides with the previous post and without having seen it]
^include(object[,template])^ pulls data, formatted as per the default or specified template, from the specified object: note, container note, separator note, alias, agent, etc. I’ve not explicitly tried including adornment data but whilst they can’t be exported as object (e.g. HTML pages) adornment data should be accessing via include.
Could you illustrate, or most a model test doc showing the case where you think you need 8 unique attributes as I can’t see it from the descriptions posted so far.
Remember, in ^value(expression)^ the expression is action code, so value can be used for the current note:
Or to access, from the current note, the $MyString value from note “Note Name” use:
Indeed—though I’d not recommend it for volume use—you could have a construct like
^value($MyString(find(query-for-a-note)))^. If going that path you might want to use an ^action()^ code at the head of the template to figure out the data or pre-calculate figures into an attribute value to call in export.
Arising from this…
Where I’m confused is that this wasn’t evident from the documentation? I’ll certainly update my page on ^value()^ to include an example using an offset reference with an attribute.
I do wonder if part of the issue here is that even if people understand the concept of an action code expression, that does not translate to a literal understanding such as would self-explain the above. If not the term ‘expression’ (as used in the app’s manual) what word might better be used. We need some descriptor as there are lots of action/export codes that involve expressions so it can’t sensible be explained at length in every context. At the same time although one can link instances of such a word to a canonical source, experience shows many folks are as averse to to following explanatory links as they are opening a paper manual. I’m not sure how to resolve that, but I’m very happy to improve my code listings in aTbRef if there are actionable suggestions.
OK, I’ve updated my notes on ^value()^ to make more explicit the fact action-code-style offset references can be used to pull values from notes other than the current one.
I’ve also updated my article on ^include()^ to give a better explanation of the two input parameters.
Whether one calls several attribute values via an offset reference (the second form as described in this article) or uses the with-template version of ^include^ is a choice. In many cases you can do either. The choice is thus partly personal style, the task at hand and opportunity for re-use. Certainly the fewer hard-coded title/paths in attribute offset references the better. That said, it’s no bad way to start. then, when you think you need a copy of the first code but with ^value()^ calls to different offsets, that’s the point you might migrate from offset ^value^ to an include and template holding the ^value()^ calls without offset.
TL;DR; there isn’t a single right way. The best choice flows from understanding both methods of remote calls (^value()^ and ^include()^) and then seeing what is most effective/flexible for your task. Of course, being Tinderbox, incremental formalisation is not hard so you can start specific and generalise as the re-use pattern emerges.
You don’t need extra attributes at all. You can include ^value() expressions in the template of the included note, or in there text of the included note. Or, you can have ^value() in the text of this note, referring to the attributes of the other note.
I’ve also added this to my page in ^include()^:
Another generalised way to understand this operator is:
^include(which object(s), what content/what form)^
The first parameter resolves to telling where Tinderbox should look to pull data in export template form. The second parameter overrides the template set for/inherited by the object(s) set via the first parameter and allows a different export template to be used to render the data returned via ^include^.
That said, I’m sure even that wording can be made plainer. I’m seeing that as the task gets less trivial it is important to understand both what an operator parameter does and separately nuances as to how that is expressed in code. One sample probably doesn’t cover all bases, butI I hope today’s changes in aTbRef are a start down that road. Lots of things become obvious only in hindsight.
Transclusion can get complex quickly and is probably best understood via a demo. That’s a ‘to do’, but I think tests I’ve been discussing with @PaulWalters might provide the bones of that.
Hey there, all of the above was EXTREMELY useful. As you may have noted in today’s session I’ve put the teaches above to work and got most of it working.
I’m running into a couple of snags, however. I can’t seem to get the syntax right for an include I’m working on. I have Note ABC in one part of my doc, and I want to include the $Name and the $Names of the Children of Note XYZ in the $Text of Nate ABC.
I tried this, and it did note WORK:
I also tried the relative path, and this did not work.
Oh, and one more thing. I tried to figure out how to apply an export template to their include and I’m struggling with the example in the TBX Ref.
$TemplateName looks like a system attribute or user attribute but I don’t see or have one. When I put in a template name, e.g. “Table name”, nothing seems to happen. For example,
If you have any suggestions on what might be wrong with my syntax, I’d be grateful.
^value(expression) returns the result of evaluating its argument. So, you’re asking Tinderbox to return the value of the attribute $ABC, which probably doesn’t exist. In that case, Tinderbox may fall back to the literal “ABC”, which happens to be what you want.
You could get this from
The one-argument form uses each child’s HTML template; the two-argument form instead uses the template you specify for each child.
Ah, this is a complex area and a starting point is to understand the two parameters for ^include^. I recall the way I learned this was to start with everything being literal values and as I showed these work, would substitute more complex expressions in the place of the literals. The benefit of this that literal stings for both parameters
Input #1 tells include from where to source the included data. This may be one or more objects (note, agent, alias, etc.). If you add the default HTML template to a test doc and omit the second parameter, you get back a fully formed HTML page or pages. This helps explain why in initial testing you will want to use a non-default template as the second input to control exactly the result of the object(s) being processed via the template at #2.
Input #2 specifies a template. It must existing in the current document, but does not need to be applied to any notes. This is powerful as the addressed note can still do a normal per-note export whilst parts of it can be included elsewhere.
Next you should note that designators don’t use offsets in the way attribute references may. Thus, $MyString(“ABC”) returns the value of $MyString for note “ABC” (the note can also be specified using an unquoted full path). Although designators can be nested, e.g.
parent(original) you cannot use literal offsets, so this wont work:
. You would need to use
Next, literal syntax errors:
This contains unmatched numbers of left & right parentheses, syntactically - if not functionally, the above should be:
But we know designators can’s use a literal offset and ^value()^ is meaningless unless the the document has an attribute named ‘ABC’. Tinderbox will likely parse this as
^value($ABC)^ looking at the current note for the value of that attribute. Likely not what you want. To get the child notes of ‘ABC’ use
I’m not sure I can make sense of this:
I think it means "I want the body text of the exported page of note “ABC” to include the titles ($Name) of all the child notes of note “XYZ”.
The aTbRef example you quote is the most complex example right at the end of the page. It retrieves the source object from the value of attribute
StringAttribute of a note specified by an offset (the ItemNameOrPath). Likewise, the template to be used to interpret the source object is not a literal value, but the value of a notional attribute
TemplateName (I just called it that to indicate the usage). The example you describe is an abstracted version of this literal string form, i.e. these are essentially the simplest and most complex forms of the same thing:
^include("Some note","some-template")^ ^include(^value($StringAttribute(ItemNameOrPath))^,^value($TemplateName)^)^
Going back to the problem I would suggest the solution is (assuming ‘ABC’ and ‘XYZ’ are unique note titles:
but you’ll need a template (we’ll call it ‘child-names’)
Why the nested ^value()^ call? See my notes on ^include()^ that note that if include is sourced from multiple objects, that list must be wrapped in a ^value()^ code. It isn’t explicitly documented as to why (which is why I don’t explain that further!).
Try this TBX - select note ‘ABC’ and preview it: include-test.tbx (93.4 KB)
Actually, you can’t use ^children^ in the manner suggested in the reply before mine. Why? Because it doesn’t have an offset parameter. As documented here the general syntax is:
^children( [template][,N] )^
This is because ^children()^ is designed for use with the children of the note being processed, in your example ‘ABC’. But you want the children of ‘XYZ’.
This is perhaps explained better in with a demo file: include-test2.tbx (96.4 KB)
It is the same file as before with some changes. Note ‘ABC’ uses the ^children(item,template)^ form suggested above (in template “page”. You will notice the preview fails. However, note ‘XYZ’ uses the correct syntax in template “page2” and works. However, as you see you can’t use ^children()^ with ‘ABC’ as the children you wish to list are children of a different container.
So, you do need ^include()^ after all!
Lastly in case quoted vs unquoted inputs are confusing, the rule is quotes $Name, unquoted $Path. So these (based on my demo file) are functionally the same:
^include("XYZ","child-names")^ ^include(/Test/XYZ, /Templates/child-names)^ ^include(/Test/XYZ,"child-names")^ ^include("XYZ", /Templates/child-names)^
Eureka!!! How awesome is the team at Eastgate? Let me count the ways. Really, guys. You are top-notch. You’re experts ( knowledgable, continuous, teachers, patient…).
I got to where exactly I wanted to be by following the steps above. What I was missing was the idea that I could have an export template without HTML header and body text, e.g. child-names, not saved under a parent HTML note. This makes SOOOO much sense, I’m not sure why this did not occur to me before. Before you say it, let me, “I’m sure this is in the documentation, did you read it?” The answer to this question is “probably, but my brain did not make the connections until just now.”
I made a few tweaks to get to the result I was looking for. I want the children of XYZ to be in a specific location of ABC.
Here is the modified test file.
include-test3.tbx (98.5 KB)
Karmic balance. I’ve never had a day’s tech training in my life, so just returning the kindness of many strangers.
What’s really interesting in you demo is is shows there is more that one way - but also falls into an easily overlooked HTML error - explanation follows.
In the above
include-test3.tbx demo if you look at the ‘page’ template there is no
^include()^ call. Wait, what? But, select note ‘ABC’, you’ll see this inline code in its $Text:
Well done avoiding the trap of default $text behaviour of straight quotes being auto-corrected to typographic ones (that action code then treats differently†). But if you look at the template used note ‘XYZ’ (it is ‘page2’). Here is the error, and why the template second input for `^include()^ is there. Look at template ‘page2’. It exports a fully-formed HTML page.
Guessed the error. Go and look at ‘ABC’ in preview mode. All looks good. Now look at the HTML There are nested HTML pages. the preview shows that the HTML spec is quite forgiving of such errors but they bite if you start to do more with the page.
No foul here—the above isn’t to dump on your solution, but only to flag up it shows the power and nuance‡ of ^include()^.
†. Meh - why can’t Tinderbox ‘just’ treat single/double quotes the same straight, or curly? Well, [a] they are different character values in the raw code (“So what?” you cry) but [b] it turns out this helps when handling $Text (sub-)strings with quotes, and being in the curly ‘typographic’ style they aren’t misinterpreted as string delimiters. I’ve moved from the former view to the latter as I’ve delved deeper into the the nuances available in Tinderbox export, but I accept this thoughtful nuance can appear wrong to the “I just want to” novice user of the app.
‡. Looking back at my email archives I think the ‘group’ -scope source option got added to support a user I’d helped that made a TBX that exported HTML that formed four discrete sub-domains of the users website when uploaded; we hit up ^include()^ pretty hard on that project and did things I didn’t think Tinderbox could do.
Ah, yes. I see the error in the nesting. Thanks for the explanation. Your explanation is a thing of beauty. Interestingly, by deleting the head and body from the page2 template the nested error goes away.
As for the need to use straight quotes, you pounded that in to me pretty well last month.
Well, of couse it would. The whole point of the
^include()^ second parameter is to render all or part of the source note (parameter #1). So, removing unnecessary full-page HTML code from the ‘page2’ template would fix things at code level: garbage-in-garbage-out. As you’ve including content into a page [sic] ot’s most unlikely you want the included content to be parsed as a(n HTML) page.
For those who are used to such things this is no different to inclusion via PHP/ASP/whatever-method templating.