Quickadd plugin: Conditional Macro

What I’m trying to do

I am trying to create a macro to add comic issues to my files. I either want to use the insert template choice OR the capture choice, depending on the active file’s tags.

I know I can use conditionals (if current file has tag use the template, otherwise capture) inside macros, but I’m not sure how I could access the tags. I’m not the best with JavaScript, so the idea of creating a script for this seems a bit overwhelming.

I thought I could ask here! TIA for the help :slight_smile:

Hi Theomjones,

When you want to add a Comic Issue to Obsidian, you’re using a pre-defined template.

Can you explain why you would want to introduce a Capture Choice for Tags? Are you wanting to sort the note based on its tag?

If you let us know the steps you would like to take we can provide some advice on some options

From https://zachyoung.dev/posts/templater-snippets#update-frontmatter:

 


Update frontmatter

Instead of reading the contents of the file and parsing it manually, it’s recommended to use tp.app.fileManager.processFrontMatter from the Obsidian public api.

You must mutate the frontmatter object directly, do not try to copy the object first and then do mutations.

<%*
const file = tp.file.find_tfile(tp.file.path(true));
await tp.app.fileManager.processFrontMatter(file, (frontmatter) => {
  frontmatter["status"] = "In progress"; // create a new property or update an existing one by name
  frontmatter["review count"] += 1; // increment the value of an existing property by one
  delete frontmatter["ignored"]; // delete a property
});
-%>

If you want to use this API when creating a file, it won’t work because the file hasn’t been added to Obsidian’s metadata cache yet. You’ll need to wrap it in tp.hooks.on_all_templates_executed to wait for the file to finish being created, then update the newly created file’s frontmatter.

<%*
tp.hooks.on_all_templates_executed(async () => {
  const file = tp.file.find_tfile(tp.file.path(true));
  await tp.app.fileManager.processFrontMatter(file, (frontmatter) => {
    frontmatter["status"] = "In progress";
    frontmatter["review count"] += 1;
    delete frontmatter["ignored"];
  });
});
-%>




 

I think with QuickAdd you use app.fileManager.processFrontMatter instead of tp.app.fileManager.processFrontMatter

Script tempalete is

module.exports = async (params) => {
    // Your code here
};

where params is

{
    app: App,                  // Obsidian app instance - see https://docs.obsidian.md/Reference/TypeScript+API/App
    quickAddApi: QuickAddApi,   // QuickAdd API methods 
    variables: {},              // Variables object for sharing data between scripts and templates
    obsidian: obsidian,         // Obsidian module with all classes and utilities
    abort: (message) => never   // Abort macro execution with optional message
}

More info: https://quickadd.obsidian.guide/docs/UserScripts

 

Note that processFrontMatter is used also to query property values without modification. Second note: you need to use tags property to query tags programmatically. There might be other API features to query tags but the above contains information only about querying properties.

 

Other example (it uses app.metadataCache.getFileCache):

async function start(params, settings) {
    const { app, obsidian } = params;
    
    const file = app.workspace.getActiveFile();
    if (!file) return;
    
    // Get frontmatter
    const cache = app.metadataCache.getFileCache(file);
    const frontmatter = cache?.frontmatter || {};
    
    // Update frontmatter
    await app.fileManager.processFrontMatter(file, (fm) => {
        fm.tags = fm.tags || [];
        fm.tags.push("processed");
        fm.date = new Date().toISOString();
        fm.status = "completed";
        delete fm.oldField;  // Remove a field
    });
}

This was taken from https://quickadd.obsidian.guide/docs/UserScripts#working-with-metadata-and-frontmatter

For context: I add comic book series from MediaDB, and then create individual notes for the issues. I link the issues to one another.

So for example Ultimate Comics Spider-Man (2011) 2, would link to issue 1 and 3. This is all done in my template.

When creating the notes, my workflow goes as follows: I either add an issue note from the series note, or from creating a new note by clicking on the links.

Ideally, the macro would recognise when I’m in the series note and either automatically create issue one (which is just an increment on the series name), or ask me for the name. The only way I thought to do this was through the tags (I tag the notes in frontmatter either as issue or series, for better organisation), but maybe there’s an easier/different way to go about it.

Edit: Right now my workaround is just to have two separate choices (one to add from template, the other to capture to the note).

It’s an older plugin which isn’t being managed but still works

You specify the tag and rule to auto move the note after tag is added

Initially, Houmann gave us only a few examples to play with; this was a long time ago on GitHub.

Meanwhile, he greatly expanded these examples, check out the Advanced tab on: https://quickadd.obsidian.guide/

This was incredibly helpful! Thank you so much :slight_smile:

My script in case anyone is interested/wants to do something similar.

module.exports = async (params) => {  
const {quickAddApi, app, obsidian } = params;

// get active file & respective metadata
const file = app.workspace.getActiveFile();  
if (!file) return; // if no active file, do nothing
const meta = app.metadataCache.getFileCache(file)

// get file tags
const activeTags = meta?.frontmatter?.tags

// check if file contains tags, then run respective choices!
// (replace text in quotes with your own choices/tags)
if (activeTags?.contains('🍿/💭/series')) {
    await quickAddApi.executeChoice("💭 comic")
}
else {
    await quickAddApi.executeChoice('💥 issue')
}
1 Like