Adding custom properties
You can define custom properties for your visualization extension. Qlik Sense
automatically adds them to the properties panel and takes care of persistence.
You then find the selected values in the layout
parameter.
For every property, you define a JavaScript object with different fields depending on what custom property type you are defining.
The following UI components can be used to display your custom properties in the properties panel:
- Button
- Button group
- Check box
- Color-picker
- Drop down list
- Input box / text box
- Link
- Media
- Radio button
- Range slider
- Slider
- Switch
- Text
- Text area
These can be grouped into sections and headers in the properties panel. Each of them exposes different configuration options to manipulate their behavior.
Improving the maintainability of properties
If you have a lot of different properties defined in the main JavaScript file, you will soon realize that the size of the script file may become quite large and it may be hard to read and maintain. There are different approaches for this:
- Split the definition into several JavaScript variables.
- Create a separate JavaScript file for the definition of your properties and load this file in your visualization extension’s main script file.
Defining properties in a separate JavaScript file
This section shows how to define your properties in a separate JavaScript file. You can start with the following code defined in your main script file.
define( [
'jquery'
],
( $ )=> {
'use strict';
return {
// Define what the properties panel looks like
definition: {
type: "items",
component: "accordion",
items: {
dimensions: {
uses: "dimensions"
},
measures: {
uses: "measures"
},
appearance: {
uses: "settings",
}
}
},
// Paint/Rendering logic
paint: ( $element, layout ) => {
// Main rendering logic goes here
}
};
});
Create a file and name it properties.js
. Save it to the same folder where your
main files of the visualization extension are located. The new properties.js
file should look like this:
define( [], () => {
'use strict';
// *****************************************************************************
// Dimensions & Measures
// *****************************************************************************
const dimensions = {
uses: "dimensions",
min: 0,
max: 1
};
const measures = {
uses: "measures",
min: 0,
max: 1
};
// *****************************************************************************
// Appearance section
// *****************************************************************************
const appearanceSection = {
uses: "settings"
};
// *****************************************************************************
// Main properties panel definition
// Only what is defined here is returned from properties.js
// *****************************************************************************
return {
type: "items",
component: "accordion",
items: {
dimensions: dimensions,
measures: measures,
appearance: appearanceSection
}
};
});
Then you need to load the external definition of properties into your main script file and assign the properties definition.
define( [
// Load properties.js using requireJS
// Note: if you load .js files, omit the file extension
// otherwise requireJS will not load it correctly
'./properties'
],
( props ) => {
'use strict';
return {
definition: props,
// Paint/Rendering logic
paint: ( $element, layout ) => {
// Main rendering logic goes here
}
};
});
Adding a basic custom property
In this section, you will define the most basic but also one of the more common components, a text box.
// Text box definition
const myTextBox = {
ref: "props.myTextBox",
label: "My text box",
type: "string"
};
In the definition of all UI components, there are common properties that can be set.
-
type
Used for all custom property type definitions. Can be string, integer, number or boolean.
-
ref
Name or ID used to reference a property.
-
label
Used for defining the label that is displayed in the properties panel.
-
component
Used for defining how the property is visualized in the properties panel.
Note: In the preceding example, component is not defined. Qlik Sense automatically defaults to a text box if component is not defined for items where type is string or integer.
Adding the component definition to the properties panel
In this section, you will add the newly created string-based text box to the Appearance section.
Before:
// Appearance section
const appearanceSection = {
uses: "settings"
};
// Main properties panel definition
// Only what is defined here is returned from properties.js
return {
type: "items",
component: "accordion",
items: {
appearance: appearanceSection
}
};
After:
const myTextBox = {
ref: "props.myTextBox",
label: "My text box",
type: "string"
};
// Appearance section
const appearanceSection = {
uses: "settings",
items: {
myTextBox: myTextBox
}
};
// Main properties panel definition
// Only what is defined here is returned from properties.js
return {
type: "items",
component: "accordion",
items: {
appearance: appearanceSection
}
};
Result:
Adding a custom section header
In the previous example, you added a text box within a new section. The section header was automatically reusing the label of the component. In this section, you will add a custom section header. To do so, you create a new header (myNewHeader in the example below) into the existing Appearance section and then you add the items there:
const appearanceSection = {
uses: "settings",
items: {
// Definition of the custom section header
myNewHeader: {
type: "items",
label: "My header, containing text box",
items: {
myTextBox: myTextBox
}
}
}
};
// NOTHING CHANGED HERE ...
// Return overall definition of the property accordion
return {
type: "items",
component: "accordion",
items: {
appearance: appearanceSection
}
};
Result:
Adding a custom section
You can also create completely new accordion sections.
// Some components
const header1_item1 = {
ref: "props.section1.item1",
label: "Section 1 / Item 1",
type: "string",
expression: "optional"
};
const header1_item2 = {
ref: "props.section1.item2",
label: "Section 1 / Item 2",
type: "string",
expression: "optional"
};
const header2_item1 = {
ref: "props.section2.item1",
label: "Section 2 / Item 1",
type: "string",
expression: "optional"
};
const header2_item2 = {
ref: "props.section2.item2",
label: "Section 2 / Item 2",
type: "string",
expression: "optional"
};
/// Define a custom section
const myCustomSection = {
// not necessary to define the type, component "expandable-items" will automatically
// default to "items"
// type: "items"
component: "expandable-items",
label: "My Accordion Section",
items: {
dimensions: dimensions,
measures: measures,
header1: {
type: "items",
label: "Header 1",
items: {
header1_item1: header1_item1,
header1_item2: header1_item2
}
},
header2: {
type: "items",
label: "Header 2",
items: {
header2_item1: header2_item1,
header2_item2: header2_item2
}
}
}
}
The key in the preceding code is that you add the component expandable-items
.
The rest of the code works as in the previous examples.
return {
type: "items",
component: "accordion",
items: {
appearance: appearanceSection,
customSection: myCustomSection
}
};
});
Result:
Displaying and persisting custom properties
Once you have defined the custom properties, Qlik Sense takes care of the rest, as:
- Displaying the custom properties together with the built-in properties
- Persistence of property values. If the value of a property is changed, you do not have to take care of persisting, that is saving and loading, the property value.
Referencing property values
Referencing property values of custom properties are similar to referencing values from built-in properties, but with one exception. By using ref, you can define how the property values is exposed in the object tree. This principle applies to all custom property items.
Examples:
By defining a text box:
const myTextBox = {
ref: "myTextBox",
...
};
The value can be referenced in your script:
console.log( layout.myTextBox );
Whereas:
const myTextBox = {
ref: "prop.myTextBox",
...
};
Will be called using:
console.log( layout.prop.myTextBox );
Note: Prefixing your properties, as seen in the latter preceding examples, allows you to easily iterate through all custom properties. It also ensures that there are no naming conflicts with the standard Qlik Sense objects.