| CheckBox A | CheckBox B |
## Connecting Multiple Components
In `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string starting with a lowercase, but it must be unique.
An example is enabling a checkbox if one of two different checkboxes is checked.
Implementation
```qml
CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: checkA}
CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: checkB}
CheckBox { name: "checkboxC"; label: qsTr("Some Label too"); enabled: checkA.checked || checkB.checked }
```
Here we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. This JavaScript expression will be automatically updated each time that the checked values of checkA and checkB changes.
Another example would be setting the visibility of some textfield to invisible if a checkbox is not checked.
Implementation
```qml
CheckBox
{
name: "checkboxA"
label: qsTr("Some label")
id: checkA
TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: checkA.checked}
}
```
Any property can be set with an expression. A title of a Section for example:
Implementation
```qml
DropDown
{
id: estimator
name: "estimator"
label: qsTr("Estimator")
values: ["EBICglasso", "cor", "pcor", "IsingFit", "IsingSampler", "huge", "adalasso", "mgm"]
}
Section
{
title: qsTr("Analysis Options - ") + estimator.currentText
....
}
```
## Configurable Constants
JASP offers a facility to query constants which may be configured by the user in a configuration file.
For example we can create a dropdown with two options, high and low.
Depending on the chosen option we set a PercentField to 100, 50 respectively.
A user or institution may want to change these respective values.
We can facilitate this using the `getConstant` function.
Using the `getConstant` function of the `Form` component we can query the configured values
for constants "high" and "low".
The function takes in two arguments, the constant name and a default value returned when the constant is not configured by the user.
Example:
Code
```qml
DropDown
{
id: cr
name: "cr"
indexDefaultValue: 0
startValue: "high"
values: [
{ label: qsTr("High"), value: "high"},
{ label: qsTr("Low"), value: "low"},
]
}
PercentField
{
name: "crCustom"
defaultValue: form.getConstant(cr.value, cr.value == "high" ? 100 : 50)
}
```
## An Example
We'll create a simple analysis input panel to show the workflow.
Read first the Guide to adding a module in JASP. In this way, when you edit your QML file, the changes made will be automatically seen in JASP. You can play with the components and their properties, and see immediately the output in JASP.
### 1. Specifying Imports
We can begin actual work on the QML file, first we have to tell the engine where to find our resources. To do so, we add a number of imports to the top of our file.
Code
```qml
import QtQuick
import QtQuick.Layouts
import JASP.Controls
import JASP.Widgets
```
If you want to import QML components from another jasp module, you can!
Have a look at [custom imports](#custom-imports).
In the future, we will require using qualified namespace for the import statements for the JASP QML modules [see here](https://doc.qt.io/qt-5/qtqml-syntax-imports.html#importing-into-a-qualified-local-namespace).
Code
```qml
import QtQuick
import QtQuick.Layouts
import JASP.Controls as JC
import JASP.Theme as JT
import JASP.Widgets as JW
```
This means that a JASP control, theme or a widget needs to be prepended with the qualifier, e.g., `JC.CheckBox` instead of just `CheckBox`.
### 2. Adding the Form
At this point we add a `Form` which will hold all our input components:
Code
```qml
import QtQuick
import QtQuick.Layouts
import JASP.Controls
import JASP.Widgets
Form
{
}
```
### 3. Adding the Components
It's now a matter of mixing and matching the previously shown components to create a form to our liking. Of course, if something isn't quite possible, you can also use QML features that were not covered here.
Code
```qml
import QtQuick
import QtQuick.Layouts
import JASP.Controls
import JASP.Widgets
Form
{
VariablesForm
{
AssignedVariablesList { name: "variables"; allowedColumns: ["ordinal", "nominal"] }
}
RadioButtonGroup
{
Layout.rowSpan: 2
name: "hypothesis"
title: qsTr("Hypothesis")
RadioButton { value: "notEqualToTestValue"; label: qsTr("≠ Test value"); checked: true }
RadioButton { value: "greaterThanTestValue"; label: qsTr("> Test value") }
RadioButton { value: "lessThanTestValue"; label: qsTr("< Test value") }
}
DoubleField { name: "testValue"; label: qsTr("Test value: "); defaultValue: 0.5 ; max: 1; decimals: 2}
Group
{
title: qsTr("Plots")
CheckBox
{
name: "descriptivesPlots"
label: qsTr("Descriptive plots")
PercentField { name: "descriptivesPlotsConfidenceInterval"; label: qsTr("Confidence Interval"); defaultValue: 95 }
}
}
}
```

## Advanced Usage
QML is a very flexible format, besides giving you access to all of the built-in components and our JASP-components that are detailed under [components](#components) you can also add your own components! If you add a qml-file to the [qml directory](#/jasp-module-structure.md#qml), for instance `Example.qml`, then it will be treated as a component by all other files in the directory. Make sure to give the file an actual capital as first letter though, otherwise qml will not see it as a component. Then you can use it in another qml file simply by adding `Example { id: yourExampleComponent }` and set any of the properties the root-component of your component if desired.
This will give you the opportunity to create reusable parts, for instance, each of your analyses might share a common core. You could add this to a `Core.qml` and then this could be part of each analysis and be exactly the same everywhere. If you then also make sure to have a common function in R that uses the options specified in the `Core.qml`-component you can reuse that as well.
The possibilities here are rather extended and possibly even endless. See [the Qt QML tutorials](https://doc.qt.io/qt-5/qml-tutorial.html) or the [official documentation](https://doc.qt.io/qt-5/qtqml-index.html) for more information on this.
## Custom Imports
To allow other jasp modules to reuse your qml code you need to turn it into a "QML Module" and you do this by adding a textfile to you `inst` folder called `qmldir`.
This file specifies which qml-components your module makes available to other modules.
For instance, suppose you want to share the entire `Descriptives` analysisform with other modules you can create `jaspDescriptives/qmldir` and that should contain:
```
module
Descriptives 1.0 qml/Descriptives.qml
```
And then suppose you want to use it in any other module you can simply do `import jaspDescriptives 1.0` and use it directly as `Descriptives {}`.
There is only small thing to keep in mind, when your module is loaded in JASP it can only use qml modules from jasp modules that are installed in jasp.
This means that if your jasp module depends on another, like the above `jaspDescriptives`, you will get the r-code from the dependency-rpkg.
But the qml will come from the loaded `jaspDescriptives` in JASP. This is far from ideal because it can lead to conflicts between the r-code and qml.
There is sadly no way around this at the moment though. But this can be worked around once we have an online module library. Then we can just force the dependencies to be installed fully.
If it turns out it is too much of a problem we could also consider using multiple qml-engines or something, but for now that seems overkill.