Using procedure parameters in calls to my own javascript function

I have created a simple Javascript function “addDays” to play with dates which I am calling with an offset parameter from a procedure. “addDays” works just fine. <<addDays 1>> returns the string I want.

\procedure myProc(myOffset)
<$list filter="[prefix<addDays $myOffset$>]" />
\end

I want to use “addDays” in a myProc with myOffset as a parameters. I have tried <<>> <> $()$ and nothing around myOffset and I cannot get it to work.

Sorry, I am early on the TiddlyWiki coding learning curve and hope I have provided enough information to get a simple answer.

Thanks

\procedure definitions do not perform “lexical substitutions” (i.e., the $someparam$ and $(somevariable)$ syntax).

To use $myOffset$, try the older \define (aka “macro”) syntax, like this:

\define myProc(myOffset)
<$list filter="[prefix<addDays $myOffset$>]" />
\end

-e

Thanks Eric for the quick response. I had read that functions and procedures were preferred to define macros. Did I miss something?

You didn’t miss anything. Functions and procedures are generally preferred and typically result in cleaner/simpler code syntax that is easier to read. Nonetheless, there are still some use-cases where the $param$ and $(var)$ macro substitution syntax comes in handy.

-e

Hi Angus,

on a side note, I have recently implemented my chores in Tiddlywiki, which requires me to work with dates (due-/done-date) a lot.

I ended up writing my own filters to work with dates in YYYY-MM-DD format (which is the format used by <input type="date">-tags), which take a date, and calculate a new date from it.

As a simple example, with my filters this became possible (here: from today, find the next Thursday and set the due date accordingly; there’s a lot more filters, like delta_days[N] for what you’ve described above):

<$button>
  <$action-setfield done_date={{{ [today[]] }}} />
  <$action-setfield due_date={{{ [<today>next_weekday[4]] }}} />
  Task done!
</$button>

Not sure if that would fit what you’re looking for, but maybe it’s close enough to serve as an example or basis for your own work.
It required some JavaScript, though, and the plugin I’ve written is still quite rough around the edges (it works fine, but I feel it may need some optimization and finetuning). You could find my plugin on Github, if you want to have a look.

s.

if you want to avoid the deprecated methods substitution and or concatenation can be done inside the backticks, “substituted attribute values” or inside filters and functions using the substitute operator. of course in addition to other longstanding filter operators like addprefix, join etc…

personally I still use define to set static values as a self documention tool.

Thanks - my challenge is that I want to pass a date (I use YYMMDD format (number or string)) to a procedure/function and then use that parameter in a filter. I just don’t seem to be able to do it.

I actually want to call a function to return a function that takes a date as its parameter and then apply that returned values as my filter.

1 Like

Hmm. I just can’t wrap my head around this.

So, you have the JS function <<addDays 1>> already implemented, which would convert input “251118” to “251119”. So far so good.

Now you’re trying to call that in a procedure within a filter, but it does not work as you cannot pass the parameter into it, which, looking at the docs, only seems to be OK doing it the <<…>> way, which might not work inside the filter you’ve stated (I haven’t tried, as I don’t have a JS function lying around to play with).

If you plan to use addDays in a filter, you could instead make it a filter (like I did), which allows you to put it in there with a parameter, which probably can come from a function, like so:

"use strict";

exports.addDays = function(source, operator, options) {
  var result = [];
  source(function(tiddler, title) {
    var inDate = …; // convert input string to a date
    if (isNaN(inDate.valueOf())) {
      result.push(`Not a date: ${title}`);
    } else {
      var n = $tw.utils.getInt(operator.operand, 0); // here's where you retrieve the parameter for the filter
      result.push(…); // add calculation for the target date here, and push the result as a string
    }
  });
  return result;
};

You could then use that in a filter directly ({{{ [……addDays[1]…] }}}).

Continuing your original route, something like this MAY work:

\define myProc(myOffset) <$text text="[prefix<addDays $myOffset$>]" />

<<myProc 1>>

(shows [prefix<addDays 1>])

…, though I’m not exactly sure why you have a procedure building part of a filter for something else, when you could work with <set>, or maybe directly with a filter instead. Maybe if you tell a bit more about your use case I could try come up with a less guesswork-y answer, as I’m (as you may have guessed already :slight_smile: ) fishing a bit in the dark here.

Hope that helps at least somehow?

Sadly, using indirect parameters in macros in filters is currently not supported. Related issue:

As eric pointed out @Angus9LN using a procedure (rather than /define macro) means using $myOffset$ to represent the parameter value will not work. It is really simple to change it to a macro and use it that way.

The first solution that comes to mind is calling addDays outside the filter

With the new procedures the parameters are only available as variables, <<paramname>> or in filters [<paramname>] and in your case you want to pass this into another macro <addDays <paramname> > and this nesting is not valid. It is important to know that this apparent loss of functionality in procedures were you don’t have the ability to apply the value via substitution, just replace $paramname$ with the value. The fact it is it more than addressed with other features introduced to tiddlywiki.

  • Substitute operator
  • Substituted attribute values
  • Functions
\procedure myProc(myOffset)
<$let offsetprefix=<$macrocall $name=addDays paramname=<<myOffset>> >
<$list filter="prefix<offsetprefix>]" />
</$let>
\end

Notes;

  • Macrocall permits the use of different sources for parameter values
    • You can still use macrocall for basic calls to \define macros or procedures otherwise use transclude $variable
  • I use the paramname because I don’t know what it is
  • With let setting the value I can now use the simple variable in the filter
  • Personally I would not use compound titles, rather a fieldname
1 Like