[Plugin] Modal form - integrate forms into QuickAdd, templater, etc

The latest version 1.30.1 has been released, and it includes:

  • forms can have a template associated to them. The template syntax is simple gor now and mimics the one of the built-in templates. It is not a substitute for templater, but you can use templater syntax and, if you have it enabled, templater will pick it up when the file is created
  • there is a simple UI for editing such templates
  • there is a new command that allows the creation of new notes from the forms that have a template. A modal will appear and ask the form you want to use, the festination folder and the name of the new note and then the form will be presented. Then the template will be executed and the new file created.

Hope you find it useful.

1 Like

Thank you for the plugin.
I’m a js-noob and only know a little about it. I keep getting an error when using this code in a Templater file. The error is:

Templater Error: Template parsing error, aborting. 
 Template syntax error: await is only valid in async functions and the top level bodies of modules

What am I doing wrong?

If you copy paste here the content of your template I will be able to point exactly what to change.

In case you can’t or don’t want to share your template, what happens is that you are missing an async keywords in a function.

This is incorrect:

function foo(){ 
   await bar()
}

This is how you fix it:

async function foo(){ 
   await bar()
}

It is this code you provided. I put in an empty Templater file to test it with this note:

---
author: Person (Test)
resting_pulse_bpm: 85
---

The modal form I created is named ‘test-form’. This I put in place of ‘solution feasibility’.
As I said i’m not a programmer, so maybe it is not possible to use a template when a note has already a template in place.

So you are trying to edit frontmatter of a note using a form, right?
The code you posted looks right to me. What is not working?
The steps are

  1. Create the form you wqnt tonuse (you did this):white_check_mark:
  2. Create a templater template with that code :white_check_mark:
  3. Add a shortcut to the template (optional)
  4. When you have the note you want to edit open, either trigger the template hotkey or open command palete, select insert template and select the template from step 2

At what step are you getting the error?

Your code has some erros in the syntax. Next time try to put it in a code editor like VSCode to get hints about the potential syntax errors.

const modalForm = app.plugins.plugins.modalforms.api; 
app.fileManager.processFrontMatter(tp.config.target_file,
  async (frontmatter) => { 
      const result = await modalForm.openForm('solution feasibility', { values: {...frontmatter}});
      Object.assign(frontmatter, result.getData()); 
  })

By the way, reading obsidian documentation the method to edit the frontmatter needs to be synchronous, but waiting for user input (like opening a form) is by nature asynchronous. I need to find a different approach

Thank you for your answer.
Your right, I should use a code editor when working with code. Oops :smiley:

To be honest, I also do this sometimes (code templates directly inside obsidian) :wink:

Are you still looking for a way to edit the metadata? I just fixed the script

2 Likes

This plugin is GOLD. That being said, does anyone know a way to use it in the “Insert after” parameter for quick add?

I wanted to separate new tasks in 3 areas (work/projects/house) and using a selector is the most elegant solution, but I can’t find how or even if it’s possible or planned altogether.

I have a workaround, just use the {{value}} syntax instead of the full form, but if anyone wants a puzzle to work over during the holydays…

Again, awesome plugin!

Thanks for the nice works, glad you are liking it.

Does that “insert after” feature of quick add allow this? : GitHub - danielo515/obsidian-modal-form: Define forms for filling data that you will be able to open from anywhere you can run JS

Not that I found. I’ll test if it works with templater, maybe?

Can you explain a bit more what the final goal is?

1 Like

I wanted the modal form to open as soon as quick add does and then populate the “insert after” parameter with data taken from the form

I wanted something similar, and couldn’t figure out how to make it work.

It’s clear how to get the form to open, but not clear to mea how to pass the data from the form to the quick add plugin.

The quick add plugin allows to use JavaScript in some of it’s areas, but not all. Such parts expect a JavaScript code block that returns a string. So what you need to do is open the form, and then return a string with the form data. Does that make things clearer ?

From their docs Inline scripts | QuickAdd

QuickAdd supports the usage of inline scripts in Template choices and Capture choices.

Hello everybody. Some days ago I released the version 1.33.0 of the plugin.
This one has some quality of life improvements that I’m particularly proud of, because they are simple yet powerful.
This two new features are focused on easing the usage of results within templater templates. Both features build on top of each other, so I will present first the base one, how to use it and then how the second one makes it even better.
The first new feature is a new method on the Result object which returns a smart value:

getValue('field-name') => ResultValue

This method lets you get a single value from the result set, but instead of returning just the value, it will return a “smart object” that has some nice additional methods and features. Let’s see it with some examples.
For the rest of the post, all of the examples here assume the following template header:

<%* 
const modalForm = app.plugins.plugins.modalforms.api;
const result = await modalForm.openForm('simple', {values:{
	list:['1984','Hello'],
	name: 'Fedever',
	number: 55
	}});
%>

Let’s start wit something simple, you want to render the name field of the form, you can do it like this:

<% result.getValue('name') %>

As I said, the returning value is “smart” and can be automatically converted to a string so this will render properly. This method can also be accessed using a sorthand, so the following is exactly the same if you are one of the ones that likes typing less :smile:

<% result.getV('name') %>

What about the more complex value list? There is when things start to get interesting. Let’s say you want to render it as a string of comma separrated values. All you need to do is:

<% result.getV('list') %>

Simple, right? Let’s make it more interesting. What if you want it as a bulleted list? Here you go:

<% result.getV('list').bullets %>

Nice right? Ok, Ok, now I want it all uppercase bullet list! Still nice and short!

<% result.getV('list').upper.bullets %>

Now let’s assume you make a mistake, and try to access a value that does not exist in the result set, what will happen if you do this?

<% result.getV('invalid').upper.bullets %>

As I said, both the method and the resulting the object is smart so nothing will happen! It will just output a empty string, and that is all.
If you want to explore even more available methods, take a look at the specific docs here.

Now time for the second and also esciting new feature:

result values shorthand

The previous examples were nice and short, but you still need to type too much for my taste: the method getValue, the parenthesis, the string opening and closing and only then the field-name you are interested in. We can do better!

the result Data Proxy

Building on the convenience of getValue, I’ve introduced an even more streamlined way to access your form data: a proxy for result data values. This feature marries perfectly with the functionality of ResultValue, enabling tidier and more intuitive template code.
Let’s revisit our examples, this time employing the new proxy access:
For accessing the name field, instead of using getValue or its shorthand getV, you can now directly use:

<% result.name %>

This is not only shorter but also clearer! It directly reflects what you’re trying to access without any additional function calls or string literals.
As for the list field, remember how we got a comma-separated string? Now it’s as simple as:

<% result.list %>

And for those fancier requirements like an uppercase bullet list? Just as easy:

<% result.list.upper.bullets %>

What if you attempt to access a non-existent field like ‘invalid’? No worries there either:

<% result.invalid.upper.bullets %>

You’ll receive an empty string, just as before. No errors thrown, no interruptions—your templating flow remains smooth and error-tolerant.
By employing this proxy to interact with your form data, you can write cleaner and more concise templates that are easier to read and maintain. Say goodbye to unnecessary verbosity!
For further information on how to harness the full potential of this feature, please refer to the documentation here.
That’s all for today! I hope these updates make your work with Obsidian Modal Form plugin more enjoyable. Happy templating!

4 Likes

This plugin is awesome, I’m loving using it to create and populate quick characters for creative writing. A quick question though - in a field when you set its type to ‘Select’ and the source is notes, when specifying a notes source folder, is there a way to make only first level notes show up? e.g., if I specify the source folder for a field named Species as 02 World Descriptors/Races, I want 02 World Descriptors/Races/Flosiler to show up but not 02 World Descriptors/Races/Flosiler/Sketches.