Help me understand Draft obj vs draft global var

I’m noticing some unexpected behaviour while using different methods on a Draft object stored as a variable vs the same methods on the global draft variable.

As far as i understand:

  • global var ‘draft’ = current draft
  • let d = Draft.create() makes a Draft obj in memory with var d
  • d.update() saves this obj to a draft
  • editor.load(d) brings the new draft into the editor

What I don’t understand:

  • after creating a new draft obj named d, storing it from memory and loading it in the editor, d != draft
  • draft.setTemplateTag() is not available to d, only in the opposite direction
  • why?

Example code

let d = Draft.create();
d.update();
editor.load(d);

d.setTemplateTag('1', '1');
draft.setTemplateTag('2', '2');

console.log(d.getTemplateTag('1'));
// 1
console.log(draft.getTemplateTag('1'));
// 1
console.log(d.getTemplateTag('2'));
// 
console.log(draft.getTemplateTag('2'));
// 2

If I change the editor.load(d) to after the setTemplateTag i get this:

let d = Draft.create();
d.update();

d.setTemplateTag('1', '1');
draft.setTemplateTag('2', '2');

editor.load(d);

console.log(d.getTemplateTag('1'));
// 1
console.log(draft.getTemplateTag('1'));
// 
console.log(d.getTemplateTag('2'));
// 
console.log(draft.getTemplateTag('2'));
// 2

There is a relationship here I don’t understand. Any help would be greatly appreciated, as it will help me debug a longer, more complicated script.

Let’s see if I can explain…

First, you run an action on a draft. The draft global is a reference to the draft you run the action on. In most cases, that is the draft loaded in the editor when you run an action from the action list…but not always. If you use app.queueAction, or run an action on a draft from the draft list, or from Shortcuts, it may never have been loaded in the editor, but be the draft. Changing the draft loaded in the editor has no affect on this variable, or anything else about the context in which the action is running.

Second, template tag functions are on an instance of a draft. Think of it as setting a custom value for the draft you are addressing with the call. If you want to evaluate in script using any particular draft’s tags, use d.processTemplate.

Maybe that helps?

1 Like

Thank you! I think I understand it a little better now.

My problem is that I’m trying to combine scripts that create new drafts with the action step insert text (because I like to do the easy visual formatting of my text template there, rather than to use multiline text strings in my js script). However it seems the insert text action step only can access the template tags of the global draft - is that correct? I also sometimes inadvertently insert text to the wrong draft - does it insert text to the draft global (meaning the draft the action is run on), or to the draft active in editor(as part of an action script)?

The current draft as i run the action is completely irrelevant for the action, so I’m trying to avoid changing parameters on that draft.

It works more or less like this:

Step 1: script

// lots of code to read from other drafts by uuid,
// show prompts and create variables holding all relevant info

d = Draft.create();
d.setTemplateTag(‘stuff’, stuff);
d.setTemplateTag(‘morestuff’, morestuff);
d.update();
editor.load(d);

Step 2: Insert text

This is the drafts insert text action.
Which sometimes inserts text to the «wrong» draft i.e. not the new ‘d’ i created.
I’m struggling to access the template tags assigned to d here.

# Heading
Lorem ipsum [[stuff]]
## [[morestuff]]
more text here...

Do I have to assign the template tags to the draft global to access it in the insert text step?
Is there any way of resetting/redirecting the draft global to a new draft during the action?

The Insert Text step should roughly be the equivalent of calling editor.setSelectedText("value"); in script.

See the note from the Editor scripting docs:

NOTE: Generally speaking, editor methods are best used for quick text manipulations of the type used in the extended keyboard. Most substantial updates to draft content are better applied using the draft object.

It’s really not a great idea to do any substantial manipulation of draft content using it, or go back and forth between drafts objects and the editor in this way. You can hit timing issues and get otherwise unexpected results. Also, “Insert Text” is making some assumptions about a current cursor position which likely do not make sense out of the context of the Action Bar.

A few suggestions…

1. Keep it in the script:

Use ES6 template literals to ease managing your multiline template variable so you don’t need to use \n line feeds, like:

let template = `# Heading
Lorem ipsum [[stuff]]
## [[morestuff]]
more text here...`;

d = Draft.create();
d.setTemplateTag(‘stuff’, stuff);
d.setTemplateTag(‘morestuff’, morestuff);
d.content = d.processTemplate(template);
d.update();
editor.load(d);

2. Use “Define Template Tag” step

Use the Define Template Tag step before your script step to create your template, and use the in-context draft just as a template processor.

So, say you create define template tag step with the name “template”, your script would be:

d = Draft.create();
draft.setTemplateTag(‘stuff’, stuff);
draft.setTemplateTag(‘morestuff’, morestuff);
d.content = draft.processTemplate(template);
d.update();
editor.load(d);

This would work fine as long as you are only using custom template tag, not values from the current draft.

2 Likes

Great! This should be all I need to set it up the way I want. Thanks again!

I had to replace the draft.processTemplateTag(template) with draft.processTemplateTag(“[[template]]”), but even then it didn’t work consistently.

I just created an example action using this as step 1 and the script as step 2, but the template processing only works some of the time. Seems a little buggy. I reran the action 20 or so times, every time with a different result. These 4 results came in random order:

Result 1 (correct)

# Heading
Lorem ipsum this is stuff
## this is more stuff
more text here...

Result 2 (didn’t replace the tags inside the template tag):

# Heading
Lorem ipsum [[stuff]]
## [[morestuff]]
more text here...

Result 3 (only replaced one of the nested tags):

# Heading
Lorem ipsum this is stuff
## [[morestuff]]
more text here...

Result 4 (only replaced the other tag)

# Heading
Lorem ipsum [[stuff]]
## this is more stuff
more text here...

I think I’ll go with the option of putting the template inside the script, to be safe, but I thought you might want to know that the other option seems to be sketchy.

Could you send your example script into support@agiletortoise.com so I can look at it and test. It superficially looks like results you would get if your script is only sometimes setting the template tags for [[stuff]] and [[morestuff]].