Basic questions for the understanding of view models


I try to understand the view model and binding procedure in Octoprint (please note that I´m quite noobish with JavaScript) while I´m coding my own plugin, but I know view models from Qt and they act as a translation part between a UI and a logic part. I assume that JavaScript will use them in the same way.

I read this document for a basic understanding, but I don´t understand it very well.

Let´s assume that my plugin uses the following configuration (I think this configuration isn´t that good, because it´s mine...):

        construct: SpoolscaleViewModel,
        dependencies: [ "settingsViewModel", "navigationViewModel" ],
        elements: [ "#navbar_plugin_SpoolScale", "#settings_plugin_SpoolScale" ]

The first part (construct) is for the construction of my view model. This is clear and without any issues.

The next parts (dependencies and elements) are a little bit unclear for me. The docs write:

"List of dependencies the view model needs injected"

What does this mean? As I know it Octoprint uses a lot of predefined view models and my model injects the listed models. Does it mean that each of the listed models will receive the methods and variables from my model (i. e. the function "tare")?

And what is the difference between the view model and the element? From my point of view, I bind automatically to the navbar when I bind to the navigation model because the navigation model is responsible for the navigation bar. The same scenario is used in the following code:

What are the idea of using the settingsViewModel in the dependencies field and the settings_plugin in the elements field?

And what does the error

Could not bind view model SpoolscaleViewModel to target #navbar_plugin_SpoolScale : Error: You cannot apply bindings multiple times to the same element.

from my model mean? How do I bind my view model to the same element in multiple ways?

It's not only core view models, but also other plugin viewmodels. The way I understand it is that those viewmodels that are included as dependencies make them referenceable from within your plugin. For example in the plugin you linked navbartemp it adds the temperatureViewModel and then has all the functions and references of that view model available in it's js file.

This does not mean your stuff goes into those viewmodels from within your js file, for example

self.temperatureViewModel.my_special_temp_function = function(){
  // do stuff here

This can be handy when you want to inject html into a different view model but be able to control it from your plugin. An example of this can be seen in my thumbnail plugins where I'm adding html code to other parts of the UI (file list and state panel) and have knockout bindings that I send from my code. The click event for pressing the button for example in the file list.

this is cause by the way the template is loaded from If the get_template_configs specifies custom_bindings as True or not. There are a couple of ways to still allow it, setting this to True is the quick way and then you reference things direct in your js observables. The other way is wrapping the element or elements in a container that specifies a allowBindings: false and then a container inside that which specifies allowBindings: true and then you specify your elements as this lower container.

Hope this helps.