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

New feature released in 1.41.0 !

Support for asynchronous results in dataviewquery and document-block fields!
Now you can await your results and run any other async operation you may need.
Because what I updated is the functionality that runs the sandboxed snippets of code, this feature is not only available in dataview input, but also dataview source for multi input and the document-block input.

Hope people enjoy this, and really excited to see what you came up with!

2 Likes

Yep, I figured TaskEither was the proper way to go after looking through the documentation, though it was beyond me. I was not counting on you to have such a quick turnaround on this, and I am super happy with your plugin, so thank you! I’m glad my pr was still able to help. It’s also pretty neat you can call fetch in there now, you’ve given me many new ideas. I just got the new update and its working great. At some point when I iron out the completion of some of my systems I will revisit this thread and post some of things I’ve built. Modal Forms will definitely play an integral part in what I am building.

1 Like

some showcase examples are long overdue on this thread because it sounds like an important plugin but only a limited number of people know how to use it, i think

1 Like

Someone recently published an excellent walkthrough video: https://youtu.be/L4vxdBGTk_M?si=CYpo32GpHvsQdrhk
Maybe that is what was missing.
That said, will love to know what parts you consider hard, or what you tried to do and we’re not able to do

1 Like

Yeah, it is a different mindset. I have a year of experience with the library and sometimes I still have to think about how to do things.

Hope this enables cool workflows that you share with the community. I’m really curious

hey danny,

i saw somewhere holroy’s solution to get the tags from cache and add them to the templater js script
also, i saw zachatoo/feralflora’s solution to add topic items in a loop
(sorry i cannot find them now and my self teaching vault is out of reach currently to check)

so i was thinking some practical solution could be shown with a templater js, calling modal form api and making use of dataview api to add in custom forms other existing values from metadata cache, e.g. in a media or moviedb setting to add nationality of actor so the user don’t need to input property values by heart - only if the country has not been registered in the cache

Message:

Hello Danielo,

I hope this message finds you well. I am currently using your Modal Form plugin in Obsidian and I have encountered a persistent issue that I hope you can help me with.

Issue Description: When I use the Modal Form plugin and cancel the form (by pressing ESC or otherwise closing the form without submitting), Obsidian automatically creates an empty “Untitled” file in the root directory. This happens every time the form is canceled, and I have been unable to prevent or automatically delete this file through scripting.

Attempts to Resolve: I have tried using Templater scripts to detect when the form is canceled and to then delete any “Untitled” files that appear. I even added delays in the script to handle potential timing issues between the file creation and the cleanup operation. Here is a brief example of what I’ve implemented:

javascript

Copy code

<%*
const modalForm = app.plugins.plugins.modalforms.api;
const result = await modalForm.openForm('Newcontactint');

if (result === null || result.asFrontmatterString() === null) {
    setTimeout(async () => {
        const files = app.vault.getFiles();
        files.forEach(async (file) => {
            if (file.name.startsWith("Untitled")) {
                await app.vault.trash(file, true);
            }
        });
    }, 5000); // Delay to catch the file post-creation
}
-%>
---
name: "<%result.asString('{{name}}')%>"
family_name: "<%result.asString('{{family_name}}')%>"
company: "AGRATI GROUP"
location: "<%result.asString('{{location}}')%>"
mobile: "<%result.asString('{{mobile}}')%>"
email: "<%result.asString('{{email}}')%>"
title: "<%result.asString('{{title}}')%>"
tag: <%result.asString('{{tag}}')%>
company_logo: Logo-Agrati.png
website: www.agrati.com
picture: <%result.asString('{{family_name}}')%>-<%result.asString('{{name}}')%>.png
type: nominativo 
aliases: 
cssclasses:
  - whiteRed-rounded
  - wideTable
  - customname
---

Result after i have pres “esc” from the form :
image

The Untitled.md is completed empty!

Despite these efforts, the “Untitled” file continues to be created each time the form is canceled.

Questions:

  1. Is there a specific configuration or setting within the Modal Form plugin that might be causing this automatic creation of “Untitled” files when a form is canceled?
  2. Do you have any suggestions on how I might modify my script or Obsidian settings to prevent this issue?
  3. Are there any plans to address this behavior in upcoming updates of the plugin?

I appreciate any guidance you can provide, as this issue has been quite challenging to resolve. Thank you very much for your time and for developing such a useful plugin for the Obsidian community.

Best regards,

Here is an screenshot of my workflow in case anyone is interested. In one side the template I’m working on, and in the other side, the list of forms with their fields for my reference. That is one of the reasons why I like having the form settings be part of the main UI and not be hidden deep in the settings of obsidian.

2 Likes

Hey @glvercellone , yes this is a known issue.
Honestly, I never cancelled a form submit in my use daily, so I never implemented ways of cancelling.
However, I paved the road to add it in a future. If you notice, the result has a status field, that tells you if the form was submitted or cancelled. Currently, there is no ‘cance’ scenario, but I am already working in a fix, so before you do anything you can check the submit status and then you will know what to do.
In the initial version, only the cancel button will be probably handled. If you accidentally close the modal form that will be handled in the next release (not sure how, re-opening the form, or doing a deeper integration with obsidian)

Hey @glvercellone

Release 1.42.0

just released version 1.42.0, which closes the form and resolves the value to a form result with the status of cancelled if you click the cancel button or hit the esc key. Directly closing the modal in the X at the top right does not have this safety mechanism, that is a future improvement. This was more a hot-fix.

1 Like

danielo515,
first of all, thank you for addressing my request.
Indeed, your update in version 1.42.0 does exactly what you described.
However, there is an issue I’d like to resolve: I would like to make it possible to intercept the pressing of the ESC key or a “null” input in general to exit the form.
Currently, the script fails to intercept a “null” return signal and consequently creates the file in the specified directory and path as outlined in the script below:

<%*
const file = app.vault.getAbstractFileByPath("New_Contact-Int1.md");
const now = tp.date.now("YYYY-MM-DD");
const modalForm = app.plugins.plugins.modalforms.api;
const result = await modalForm.openForm('Newcontactint');
if (result.asFrontmatterString() === null) {
    await app.vault.trash(file, true);
    return;
}
await tp.file.move("000-Agrati_CRM/Agenda/Nominativi-Interni/" + result.asString('{{name}}_{{family_name}}'));
-%>

Particularly with this code, I am attempting to identify when the result is null… but it is not working:

if (result.asFrontmatterString() === null) {
    await app.vault.trash(file, true);
   return;
}

What do you mean by a null input?
To handle the esc/cancel what you need to do is check the result status:

<%*
const file = app.vault.getAbstractFileByPath("New_Contact-Int1.md");
const now = tp.date.now("YYYY-MM-DD");
const modalForm = app.plugins.plugins.modalforms.api;
const result = await modalForm.openForm('Newcontactint');
if (result.status === 'cancelled') {
    await app.vault.trash(file, true);
    return;
}
await tp.file.move("000-Agrati_CRM/Agenda/Nominativi-Interni/" + result.asString('{{name}}_{{family_name}}'));
-%>

That will ensure that pressing the esc key or cancelling the form submission will go to the cancelled route.
asFrontmatterString will never return null because that will break compatibility. It can return an empty string though.

All is perfect, now thankyou.

Hi everyone,

I’m trying to use Dataview setting in the Modal-forms input cell, to get a unique list of companies (company) from all notes in a specific folder in my vault.

Here’s the code I’m currently using to get all companies:

dv.list(dv.pages('"000-XXX_CRM/Agenda/Nominativi-Esterni"').company);

This lists all companies, including duplicates. I want to modify the code so each company appears only once.

I tried using Set to remove duplicates, but encountered the error “cannot read properties of undefined (reading ‘company’)”. Here’s the code I tried:

const companies = dv.pages('"000-Agrati_CRM/Agenda/Nominativi-Esterni"').company;
const uniqueCompanies = Array.from(new Set(companies));
dv.list(uniqueCompanies);

Can anyone help me correct this code or suggest an alternative method to get a unique list of companies from a specific folder?

Thank you!

Just add .distinct() at the end. Yu don’t need any additional list wrrapper or anything:

dv.pages('"000-XXX_CRM/Agenda/Nominativi-Esterni"').company.distinct()