Multi-select dropdown, insert multiple attributes

Obsidian is fun. Amazing to what extend the app can be customized. I hope the following script might be useful to somebody. Credit for the original idea for the multi-select dropdown goes to Christian.

Description:
A multi-select drop down box is prefilled with notes that have a given tag assigned (tag can be set in the script). User selects one or more entries in the drop-down. These items will be inserted as links into the current note. If the current Note contains a header “## Tags” the links will be inserted in the line following this header, otherwise at the current cursor position.

Use case: i.e. to quickly insert a collection of attributes into a daily note.

Screenshots:
The drop-down is automatically populated with notes that have a given tag assigned:

After checking the desired attributes and selecting “Done” the values get inserted after the “## Tag” header:

The links have the format: [[Information/9 Meta/Demo/Yoga|Yoga]]

Script code (Templater and DataView plugins are required):

<%*
// Configuration start
const question = "Your tags for today?";
const checkMark = "✅ ";
const searchTerm = "## Tags";
// Configuration end

// Check if there is a line with the searchTerm, if so put the cursor in the following line.
const cm = this.app.workspace.activeLeaf.view.editor;
const count = cm.lineCount();
let line;
for (let i = 0; i < count; i++) {
	line = cm.getLine(i + 1);
	if (line.includes(searchTerm)) {		
		cm.setCursor({line: i+2, ch: 0});		
		break;
	}		
}

// Collect all notes with the tag "Meta". Using DataViewJs for this.
const dv = this.app.plugins.plugins["dataview"].api;
let notes = dv.pages("#meta1").file.sort(n => n.name);
let suggestions = notes.map(n => n.name);
suggestions = ["Done", ...suggestions];
let values = notes.map(n => "[[" + n.folder + "/" + n.name + "|" + n.name + "]]");
values = ["Done", ...values];

// Create object with suggestions and values arrays
const config = {
  "suggestions": suggestions,
  "values": values,
  "responses": []
};

let response;
while (response !== "Done") {
    response = await tp.system.suggester(config.suggestions, config.values, true, question);
    if (response !== "Done") {	
		let rIndex = config.responses.indexOf(response);
		if (rIndex > -1) {
				config.responses.splice(rIndex, 1);					
		} else {				
			config.responses.push(response);
		}
		let vIndex = config.values.indexOf(response);
		let suggestion = config.suggestions[vIndex];
		if (suggestion.startsWith(checkMark)) {
			config.suggestions[vIndex] = suggestion.replace(checkMark,"");
		} else {
			config.suggestions[vIndex] = checkMark + suggestion;
		}
	}
}

// console.log(config);
let result = config.responses.join(", ");
return result
_%>
5 Likes

Very useful, thanks a lot! :clap:

This is exactly what I was looking for in order to quickly populate meeting notes with correctly named attendees. But when I tried adding it to my meeting template, rather than finding the correct heading, it replaced the entire document with the choices I’ve selected. Any idea why that would happen?

I imagine the described scenario would occur if

  • the script doesn’t find the configured searchTerm and
  • the whole content of the note had been selected (ctrl + a) before executing the template