Skip to content

2024

Release notes for 1.52.0

Markdown block

This release introduces a new input, the "markdown block". Just like the existing "document block" this is not a real input, but more a building block for richer forms. The definition is expected to contain a function body returning a markdown string. This markdown string will then be rendered into the form and the user filling it will be able to see it.

To illustrate with an example, imagine a simple form with a single text input, we can define a markdown block with this content:

return `# hello
- line 1
- ${form.text}
- ![[image.png]]`

Have you noticed the image syntax? Yes, images are supported too. This is how it looks once rendered: form containing markdown block

Updates to the existing document block

Both Markdown block and document block now have access to the dataview API (along with the form data itself). This allows to build much complex and data packed information panels. To access the dataview API, you do normally just like in any other place using a special variable named dv. For example, and continuing with the markdown example, we could render a list of all the people (in markdown) using dataview like this:

return dv.markdownList(dv.pages('#person').map(x => x.file.name))

That will render something like this: markdown using dataview

Release notes for 1.51.0

Hidden fields

This release introduces the concept of hidden fields. The intended usage of this feature is to provide values to the form that are not visible to the user. This has some applications such as:

  • providing variables to the form-runtime that your dataview functions can use
  • having certain fields deactivated using the conditional without any user interaction
  • having certain values be part of the generated result, and used in the templates

I bet the community will be able to figure out some other interesting use-cases. The reason I like this approach to much is a) because it is a web standard (this is common practice to communicate between backend and frontend in forms) and b) it plays nicely with all the existing form mechanisms without having to complicate the logic at all: formatting the output, reading the value from dataview functions, conditional rendering other fields, etc.

Hope you like it and find it useful.

Release notes for 1.48.0

This is a very exciting release for me, because it includes one of the features that I have been wanting to implement for a long time, and also one of the most requested features. But it also includes some minor improvements, so let's take those first:

  • The placeholder of the label is set by default to the name of the field. This will make it easier for people to understand that the default label value is the name of the field. name as label placeholder

Now the big feature:

Conditional fields

As with every new feature, I like to start small, so this first version is very simple. It just settles the basic foundation and works only with the most basic field types. This will allow me to gather feedback and improve it in the next releases after making sure that the basic functionality is working as expected.

In this first approach there are not many safeguards either, so you can end up in forms that don't show any field, for example because of fields that are excluding each other. I don't think this is going to be a big problem in practice, but I will be monitoring the feedback to see if it is necessary to add some kind of validation, or at least some kind of warning. The reason I am not adding it any limitations in this first version is because flexibility: forms can be called with parameters to omit fields, default values, etc. and I don't want to limit that flexibility.

Here are some screenshots of the feature in action.

Form builder: boolean condition text condition

Form in preview mode with the condition met condition met with the condition not met condition not met

This first iteration is purely visual: just because a field is hidden it does not mean that, if it has a value, is not going to be included in the result. If you fill a field, and then do something that makes it hidden, the value will still be included in the result. I think in practice most people just needs a way to start with several fields hidden, and then show them based on the value of other fields, so I think this is a good first approach.

The wording of the feature is not final, I'm not very satisfied with the current wording, so I'm open to suggestions. I hope you like it, that it does not introduce too many inconveniences and that it is useful to you.

Please let me know your thoughts and suggestions.

Release notes for 1.47.0 and a statement of intent

Release notes for 1.47.0

This is mostly a technical release that also includes some minor improvements.

The technical part of it is that now the fields of the form are rendered using svelte rather than manually calling DOM manipulation methods or the obsidian Setting class. I made this because it simplifies the creation of the view, it will be more maintainable, but the most important reason is that it will make much much easier to implement functionalities that require atomic re-renders of the form. The most important and requested feature this will enable is the ability to have dynamic fields that depend on the value of other fields. This is not implemented yet, but it will be much easier to do now and I will start working on it soon.

For the minor improvements, I added some more color to the form fields, so now the stars that indicate required fields are colorful.

colorful stars

I also improved the error messages when submitting a form with errors. Now the error message appears below the field in red color:

better field errors

Also related to errors, the notifications that appear when submitting a form with errors are now grouped in a single notification containing all the errors:

grouped notification errors

Statement of intent

When I started this project, I had not much experience with Obsidian and absolute no experience with Obsidian plugin development. Also, my initial idea was to create a very simple plugin, basically something wrapping some basic existing Obsidian functionality and glueing it with some other tools I like to use (templater mainly) while making the process streamlined and more user friendly. Since then, the plugin has gained a lot of popularity, it has some thousand of installs, making it my most popular project by far. Coming from a web development background, I was imposing myself some limitations that I learned that do not make any sense in Obsidian. For example, at first I was very worried about the bundle size of the plugin (which is still very small) and I was trying to avoid using external libraries as much as possible. However, some of the most popular plugins weight several MBs and nobody seems to care. Also, many plugins diverge significantly from the Obsidian default appearance, and that is not a problem at all. What does that mean for modal form? That I will try to build better functionalities, always trying to keep the plugin simple and focused, but I will no longer limit myself to what Obsidian offers out of the box, and I will not be afraid of using external libraries if they make sense.

Hope you like the direction I'm taking with the plugin. I'm very excited about the future of it.

Release notes for 1.46.0

This release contains one little change that was easy to make, but I think that it unlocks a very interesting use case for modal forms. There is a not very well documented feature in the FormEditor that allows to define a specific (and simple) template linked to that form. I implemented it partially for fun, because I love coding parsers but also partially because many times I only need very basic templating functionality and I don't want to have to write another templater template. Also, I find very appealing the idea of having both the form and the template visible and linked in the same place, which is not the case when you use templater templates. Up until now, the only thing you can use this templates for was for creating new notes from that template. You trigger a command, select the form to use, fill it and the template is used to create the note.

But I find myself many times defining a very simple for for easier the insertion of certain data in an existing note. However, for that I was forced to first create the form then create a templater template that uses that form (whith all the boilerplate it entails) and then either tell templater to create a command for that template or use the insert template from templater command. When I saw how easy is to create commands that insert text in the current note I thought it was a no brainer to not take advantage of that with the form templates.

So that is the little but big improvement in this release. You can now use the form templates to insert text in the current note at the cursor position.

To give an example, I have a very simple form for inserting an external link. While the experience of doing this in the Obsidian desktop app is fine, it is a bit tedious to do on mobile.

My form looks as simple as this: External link form

And the template is also very simple, just:

[{{title}}]({{url}})

Now, I can trigger a command that will insert the template in the current note at the cursor position after filling and submitting the form.

Hope you find this useful. I'm already using it a lot.