25 | The condition has been evaluated to TRUE
26 |
27 |
28 | The condition has been evaluated to FALSE
29 |
30 | ```
31 |
32 | Now replace the conditions with a reference to the previously created property. The easiest way to achieve that is to use the "Insert" dialog:
33 |
34 | 
35 |
36 | Switch to "Property references" and select "Settings" in the Dropdown list:
37 |
38 | 
39 |
40 | Insert the value inside of `ng-hide` resp. `ng-show`.
41 |
42 | Now your code should be as follows:
43 |
44 | ```html
45 |
46 | The condition has been evaluated to TRUE
47 |
48 |
49 | The condition has been evaluated to FALSE
50 |
51 | ```
52 |
53 | If you now change the value of the property in the property panel, either the hide or show condition will be evaluated to true.
54 |
55 | ## Reference
56 |
57 | - [AngularJS Documentation for ngShow](https://docs.angularjs.org/api/ng/directive/ngShow)
58 | - [AngularJS Documentation for ngHide](https://docs.angularjs.org/api/ng/directive/ngHide)
59 |
--------------------------------------------------------------------------------
/src/recipes/table-with-dynamic-label/images/dynamic-labels-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/recipes/table-with-dynamic-label/images/dynamic-labels-result.png
--------------------------------------------------------------------------------
/src/recipes/table-with-dynamic-label/images/no-dynamic-label.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/recipes/table-with-dynamic-label/images/no-dynamic-label.png
--------------------------------------------------------------------------------
/src/recipes/table-with-dynamic-label/images/prop-custom-labels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/recipes/table-with-dynamic-label/images/prop-custom-labels.png
--------------------------------------------------------------------------------
/src/recipes/table-with-dynamic-label/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Table with dynamic label"
3 | sub-title: "How to create a table with dynamic labels - defined by the user?"
4 | ---
5 |
6 | [Paul Nowicki](https://community.qlik.com/people/pnowicki) is asking the following question on [Qlik Community](https://community.qlik.com/message/1106071):
7 |
8 | > I'm currently trying to create a widget table where I can have dynamic column labels. This is my attempt at a workaround for Qlik Sense's lack of dynamic labels. Has anyone done this before and can share their widget code?
9 |
10 | ## No magic solution
11 |
12 | When defining dimensions and measures in Widgets you actually run into the same situation as when working with native visualizations: The label cannot be defined by using an express:
13 |
14 | 
15 |
16 | ## A proposed solution
17 |
18 | But due to the flexibility of Widgets there is at least a feasible workaround - even if not 100% user-friendly.
19 |
20 | ### Preparation
21 |
22 | - Create a widget, add the data-section to the property panel and define the desired amount of dimensions and measures.
23 | - Next create a header and an input object, configured as follows:
24 |
25 | 
26 |
27 | - Now let's add the basic code snippet for creating a table and add some dimensions and measures:
28 |
29 | Basic table snippet (from the snippet dialog):
30 | ```html
31 |
32 |
33 |
34 |
35 | \{{head.qFallbackTitle}}
36 |
37 |
38 |
39 |
40 |
41 |
42 | \{{cell.qText}}
43 |
44 |
45 |
46 |
47 |
48 | Please add dimensions and measures.
49 |
50 | ```
51 |
52 | - In the `customLabels` input field let's define some custom labels, separated with a semi-colon, e.g.:
53 |
54 | ```
55 | This is header 1;Another header;Third header;Fourth header
56 | ```
57 |
58 | Now all we have to do is to change the section of the code-snippets where the headings of the table are rendered:
59 |
60 | ```html
61 | ...
62 |
63 |
68 |
69 | ...
70 | ```
71 |
72 | So how does this work:
73 | - The content of `settings.customLabels` will first be converted to an array using JavaScript's split method
74 | - Then for each column index, the right one will be taken and rendered
75 |
76 | That's the result:
77 | _(used some stylesheet to make it a bit nicer)_
78 |
79 | 
80 |
81 | ## Better solution
82 |
83 | If you have a better solution for this challenge, please do not hesitate to post your findings in the comment section below!
84 |
--------------------------------------------------------------------------------
/src/subjects/about/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: About
3 | sub-title: About this tutorial, how to use, how to contribute ...
4 | ---
5 |
6 | (TBD)
7 |
--------------------------------------------------------------------------------
/src/subjects/actions/images/sample-actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/actions/images/sample-actions.png
--------------------------------------------------------------------------------
/src/subjects/actions/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Actions
3 | sub-title: "Let your widget interact with Qlik Sense using actions."
4 | ---
5 |
6 | The following actions can be used to make your widget more interactive with Qlik Sense:
7 |
8 |
9 | - `app.clearAll` - Clear all selections.
10 | - `app.back()` – Back to the previous selection
11 | - `app.forward()` – Forward to the next selection
12 | - `navigation.nextSheet()` – Jump to the next sheet
13 | - `navigation.prevSheet()` – Jump to the previous sheet
14 | - `navigation.gotoSheet()` – Jump to a sheet, defined by Id
15 | - `navigation.gotoStory()` – Jump to a story, defined by Id
16 |
17 | *This is just an excerpt of the available actions, for a full list, have a look at the {{#hl}}App API{{/hl}} or the {{#hl}}Navigation API{{/hl}}*
18 |
19 | ## Usage
20 | Bind your widget with an action using e.g. `ng-click` (in case of a button):
21 |
22 | **Html:**
23 | ```html
24 |
25 |
26 |
27 | ```
28 |
29 | Note: To apply styles, e.g. use the Leonardo-UI styles.
30 |
31 |
32 | ## Example
33 |
34 | This example uses Leonardo-UI styles an some of the predefined actions:
35 |
36 | **Html:**
37 | ```html
38 |
39 | Back
40 | Clear All
41 | Forward
42 |
43 | ```
44 |
45 | ```css
46 | & {
47 | padding:10px 10px 10px 10px;
48 |
49 | .lui-button {
50 | min-width:100px;
51 | }
52 | }
53 |
54 | ```
55 |
56 | **Result:**
57 |
58 | 
59 |
60 |
61 | ## FAQ:
62 |
63 | **Q: Is it possible to define custom actions?**
64 | A: Right now, this is not possible, but on the roadmap for future versions.
65 |
--------------------------------------------------------------------------------
/src/subjects/concept/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Widget concept"
3 | ---
4 |
5 | The main goal of the Widget concept (introduced in Qlik Sense 3.0) can be described as follows:
6 |
7 | > **Allow users to create new visualizations for Qlik Sense without the need of having any programming skills.**
8 |
9 | Widgets are best suited for creating simple visualizations, such as KPI objects, tables or any other kind of simple information representation.
10 | Widgets can also be used to add simple actions to objects, such as buttons to clear selections, to jump to a different sheet, or to add other visual elements.
11 |
12 | To make it even easier to create widgets, Qlik Sense provides a powerful development environment to create and maintain widgets: **The Widget editor**
13 |
--------------------------------------------------------------------------------
/src/subjects/data-binding-hypercubes/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Data binding: Hypercubes"
3 | draft: true
4 | ---
5 |
6 | Dimensions and measures defined in your widget object result in an internal data table, a so-called hypercube, that is being exposed to the object, just like for any other standard Qlik Sense object. This data table can be used in your widget.
7 |
8 | There are some basic objects exposed to the current scope of your widget that you can use.
9 |
10 | Object | Description
11 | ------------------------------------------------| ------------------------------
12 | `layout.qHyperCube` | Returns the representation of the hypercube, that is, the data table exposed to your widget.
13 | `layout.qHyperCube.qDimensionInfo` | Gets the object array of defined dimensions.
14 | `layout.qHyperCube.qMeasureInfo` | Gets the object array of defined measures.
15 | `layout.qHyperCube.qDataPages[0].qMatrix` | Gets the object array of the data table.
16 | `layout.qHyperCube.qDataPages[0].qMatrix[0]` | Gets the object array of the first row of the data table.
17 | `layout.qHyperCube.qDataPages[0].qMatrix[0][0]` | Gets the object array of the first column in the first row of the data table.
18 |
19 | ### Example: Iterating through dimensions and measures
20 |
21 | ```html
22 |
23 |
24 |
25 |
{{dim.qFallbackTitle}}
26 |
{{mea.qFallbackTitle}}
27 |
28 |
29 |
30 |
31 |
32 | {{col.qText}}
33 |
34 |
35 |
36 |
37 | ```
38 |
39 |
40 | ## Shorthand Notation
41 | Since the above described notation is very powerful, but hard to memorize, there is also a second API available to work with the HyperCube. From within widgets you can also access the [Table API](http://help.qlik.com/en-US/sense-developer/2.2/Subsystems/APIs/Content/TableAPI/qlik-table-interface.htm).
42 |
43 | Object | Description
44 | -------------------------------------- | -------------------------------------------------
45 | `data.rows` | Get the object array of all rows (including measures and dimensions).
46 | `data.headers` | Get the object array of all headers (including measures and dimensions).
47 | `data.totals` | Get the total information for headers.
48 | `data.rowCount` | Returns the total number of rows of the `qHyperCube`, including rows not fetched from the server.
49 | `data.colCount` | Returns the total number of columns for the `qHyperCube`
50 |
51 | For more information how to use the Table API, please visit the [Table API reference](http://help.qlik.com/en-US/sense-developer/2.2/Subsystems/APIs/Content/TableAPI/QHeader.htm).
52 |
53 | ### Example: Iterating through dimensions and measures using the shorthand notation
54 |
55 | ```html
56 |
57 |
58 |
59 |
{{head.qFallbackTitle}}
60 |
61 |
62 |
63 |
64 |
{{cell.qText}}
65 |
66 |
67 |
68 | ```
69 |
--------------------------------------------------------------------------------
/src/subjects/debugging/images/qw-console-output-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/debugging/images/qw-console-output-settings.png
--------------------------------------------------------------------------------
/src/subjects/debugging/images/settings-output-pre.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/debugging/images/settings-output-pre.png
--------------------------------------------------------------------------------
/src/subjects/debugging/images/settings-output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/debugging/images/settings-output.png
--------------------------------------------------------------------------------
/src/subjects/debugging/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Debugging Widgets
3 | sub-title: Some tips and tricks how to debug Widgets.
4 | draft: false
5 | ---
6 |
7 | When working with data resp. properties in your widgets, it's quite often useful to get the current state of the AngularJS scope, so that you can validate the output or just to get a better understanding of the underlying data-structure.
8 |
9 | ### Just Render it ...
10 |
11 | The easiest way to get some insights of the internal data-structures is to just render it using pure AngularJS functionality and data binding:
12 |
13 | ```html
14 |
15 | ```
16 | returns the following in the preview area
17 | 
18 |
19 | *The AngularJS filter `json` ([> docs](https://docs.angularjs.org/api/ng/filter/json)) actually converts and object to JSON and therefore allows you to see all properties of the given object.*
20 |
21 | This becomes even more useful if you use `pre` for a better readable output:
22 |
23 | ***Html***
24 |
25 | ```html
26 |
27 | ```
28 |
29 |
30 | ***CSS***
31 |
32 | ```css
33 | .json {
34 | font-family: monospace;
35 | }
36 | ```
37 |
38 | ***Result***
39 |
40 | 
41 |
42 |
43 | ### Using Chrome's DevTools & `qw-console`
44 |
45 | *If you are not familiar with Chrome DevTools or development tools available in nearly every browser, then [the official documentation](https://developer.chrome.com/devtools) is a good starting point.
46 | But basically just press `F12` and you'll see a developer tool appearing in your browser***
47 |
48 | There is an experimental component available (as of Qlik Sense 3.0) which allows you to output some information in the developer's console: ``.
49 |
50 | Just use it anywhere in the Html area as follows:
51 |
52 | ***Example:***
53 |
54 | ```html
55 |
56 | ```
57 | returns then
58 |
59 | 
60 |
61 | ## Usage
62 |
63 | Log the given object to the console:
64 |
65 | ```html
66 |
67 | ```
68 |
69 | Log the path property of the given data object
70 |
71 | ```html
72 |
73 | ```
74 |
75 | Log the parent scope of the targeted element using a querySelector:
76 |
77 | ```html
78 |
79 |
80 |
81 |
82 |
83 | ```
84 |
--------------------------------------------------------------------------------
/src/subjects/faq/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: FAQ
3 | sub-title: "Frequently asked questions"
4 | ---
5 |
6 | {{> toc}}
7 |
8 |
9 | ## How to use external chart libraries in widgets?
10 | It's definitely not the idea of widget to use this concept to programmatically create your visualization objects. Widget is a concept focused on declarative languages like Html and CSS. Create a visualization extension if you want to leverage the full power of JavaScript an existing libraries instead.
11 |
12 | ## How can qWidget and widgets be compared?
13 | qWidget was a prototype developed in the early beginning of Qlik Sense and you will recognise that Widgets for Qlik Sense were developed based on the ideas of qWidget.
14 | Having said that, the biggest different between these solutions (as of Qlik Sense 3.0) are:
15 |
16 | - qWidget is just an experimental prototype (and therefore not supported at all!!!)
17 | - Widgets are fully integrated into Qlik Sense and therefore this concept is also fully supported and it is planned to extend the concept in the future.
18 | - Right now (as of Qlik Sense 3.0 and Widget 1.0) there is especially a gap when it comes to use several components, like
19 | - A date-picker
20 | - A (range-)slider
21 | - Some convenience tools like a debugging-helper
22 | - Inline charts (minicharts)
23 | - etc.
24 |
25 | So Widgets for Qlik Sense are the future, qWidget is (unofficial) legacy.
26 |
27 | ## What's the plan for qWidget
28 | Right now, as there is still a gap between qWidget and Widgets for Qlik Sense, the plan is to make qWidget work with Qlik Sense and as soon as we can offer similar functionality in Widgets for Qlik Sense qWidget will be removed.
29 |
30 |
31 | ## qWidget offers more features ...
32 | Yes, as of Qlik Sense 3.0 there are is some gap between qWidget and widgets in Qlik Sense. As long as as the widget concept will not be in par of the qWidget concept, you can still use qWidgets.
33 |
34 | ## Can I continue to use qWidgets
35 | Yes, certainly you can, but (see above) qWidget is not officially supported and there is no additional development work planned for qWidget. It is planned to make qWidget work with Qlik Sense 3.0, though.
36 |
--------------------------------------------------------------------------------
/src/subjects/good-citizen/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: What makes a Widget a good citizen
3 | ---
4 |
5 | A Widget should be:
6 |
7 | - Generic
8 | - Responsive
9 | - Declarative Only
10 |
11 | ## Generic Widgets
12 |
13 | - Don't hard-code values within widgets, use properties instead and bind to properties as much as you can.
14 | - Test your widgets with different apps, widgets should work independently from the data model.
15 |
16 | ## Responsive Widgets
17 |
18 | - Test your widget in the Widget editor for different object sizes.
19 | - Use the resize gripper in the "Preview" pane for testing different object sizes.
20 |
21 |
22 | ## Declarative Only
23 | One of the core concepts of widgets is that only Html and CSS/Less should be used.
24 | If you have to use some JavaScript code to create your custom visualization, use the concept of visualization extensions.
25 |
--------------------------------------------------------------------------------
/src/subjects/personas/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Widget Personas
3 | ---
4 |
5 | ## Personas
6 |
7 | The following typical personas are involved in the Widget concept.
8 |
9 | ### Widget creator
10 |
11 | > The Widget creator creates and maintains widgets.
12 |
13 | **Required skills:**
14 | - Html
15 | - Css (+ optionally Less)
16 | - Basic concepts of data-binding with AngularJS
17 |
18 | ### Widget consumer
19 |
20 | > The Widget consumer uses existing widgets within Qlik Sense - in the same way as any other object type.
21 |
22 | **Required skills:**
23 | Nothing special, Widgets can be used as any other object type in Qlik Sense.
24 |
25 | ### Administrator
26 |
27 | > An Administrator can manage widget libraries by using the QMC.
28 |
29 | **Required skills:**
30 | Nothing special, widgets are managed in the QMC in exactly the same way as for example visualization extensions.
31 |
--------------------------------------------------------------------------------
/src/subjects/responsiveness/images/less-300px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/responsiveness/images/less-300px.png
--------------------------------------------------------------------------------
/src/subjects/responsiveness/images/more-300px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/responsiveness/images/more-300px.png
--------------------------------------------------------------------------------
/src/subjects/responsiveness/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Responsive Widgets"
3 | sub-title: "How to make your widgets fully responsive."
4 | ---
5 |
6 | When working with web pages, the most common concept to make web pages responsive is to use [CSS media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries).
7 | Media queries can be used to define different styles for different media types/devices based on the width and height of a device, the orientation, etc.
8 |
9 | Media queries is a very useful concept, but in case of widgets (and also visualization extensions) it is not really sufficient respectively does not really help.
10 |
11 | Let's review why this is the case:
12 |
13 | - Media-Queries allow you to style parts of your web page depending on the current screen size (also called viewport)
14 | - In case of custom objects for Qlik Sense, we have to apply different styles depending on the object size and is therefore defined by the screen size + the amount of columns and cells an object is spanned over in Qlik Sense' grid system.
15 |
16 | Therefore an additional concept, called element queries has been provided for styling widgets according to its object size. Widget uses a [CSS element queries polyfil](https://github.com/marcj/css-element-queries) to add support for element based media-queries.
17 |
18 | ## Usage
19 |
20 | ***Html:***
21 |
22 | ```html
23 |
24 |
25 | /* Your Content */
26 |
27 |
28 | ```
29 |
30 | ***CSS:***
31 |
32 | ```css
33 | .kpi-widget .inner {
34 | /* default style for the inner element */
35 | }
36 |
37 | .kpi-widget[max-width~="300px"] .inner {
38 | /*
39 | default style for the inner element
40 | if .kpi-widget has a width of less than 300px
41 | */
42 | }
43 | ```
44 |
45 | ## Example
46 |
47 | ***Kpi-Widget with >= 300px***
48 | 
49 |
50 |
51 | ***Widget with less than 300px***
52 | 
53 |
54 | ```html
55 |
56 |
57 | My responsive widget.
58 |
59 |
60 | ```
61 |
62 | ```css
63 | .kpi-widget .inner {
64 | font-weight:bold;
65 | color:darkgray;
66 | font-size:30px;
67 | }
68 |
69 | .kpi-widget[max-width~="300px"] .inner {
70 | color:red;
71 | font-size:16px;
72 | }
73 | ```
74 |
75 |
76 |
77 | ## Reference
78 |
79 | The following attributes are supported:
80 |
81 | - `min-width`
82 | - `max-width`
83 | - `min-height`
84 | - `max-height`
85 |
--------------------------------------------------------------------------------
/src/subjects/styling-widgets-recommendations/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Styling Widgets - Recommendations"
3 | sub-title: Use Cascading Style Sheets (CSS) to make your widgets just looking great. Go one step further and use the full power of Less to create even more maintainable and re-usable styles.
4 | todos:
5 | - Less explanation
6 | ---
7 |
8 | You can use the full functionality of CSS when styling your widgets. In addition to standard CSS, you can also style your widgets using LESS.
9 |
10 | There are two ways of styling your widgets:
11 |
12 | - Inline styling
13 | - Separated styling
14 |
15 | ## Some Ground Rules & Recommendations
16 | There are only a few rules you should consider when styling your widgets:
17 |
18 | - [Never use Ids](#rule-#1-never-use-ids), always use CSS classes to style your widgets
19 | - [Use separated styles](#recommendation-#1-use-separated-styles) over inline style-attributes as much as you can
20 | - Try to [parametrize your CSS styles](#recommendation-#2-parametrized-css-styles)
21 |
22 | ## Rules & Recommendations
23 |
24 | ### Rule #1: Never use IDs
25 |
26 | **This is bad and not recommended**
27 |
28 | ***Html:***
29 | ```html
30 |
31 | Your custom content ...
32 |
33 | ```
34 |
35 | ```css
36 | #my-object {
37 | /* your custom styling */
38 | }
39 | ```
40 |
41 | Since the Id attribute of Html objects are supposed to be unique on a single page, this can lead to problems if your widget is used several times on a single sheet.
42 |
43 | Use CSS classes instead:
44 |
45 | **This is OK**
46 |
47 | ```html
48 |
49 | Your custom content ...
50 |
51 | ```
52 |
53 | ```css
54 | .my-object {
55 | /* your custom styling */
56 | }
57 | ```
58 |
59 | ### Recommendation #1: Use Separated Styles
60 |
61 | You can style all your HTML elements using inline style-attributes, but it is recommended to separate your styling code from your HTML code. Separated styling is preferred because:
62 |
63 | - It is easier to maintain
64 | - It is easier to reuse
65 | - It makes it easier for others to understand and read the HTML
66 |
67 | #### Inline Style-Attributes
68 |
69 | Inline styling can be used but is not recommended because of the reduced maintainability and readability of your HTML.
70 |
71 | ***Example: Inline style-attributes***
72 |
73 | ```html
74 |
75 | This is my Widget
76 |
77 | ```
78 |
79 |
80 | #### Separated styling
81 |
82 | If you use the separated styling approach, you achieve the same result as in the inline styling example above by declaring the styling in the CSS editor.
83 |
84 | ***Example: Separated styling: HTML***
85 |
86 | ```html
87 |
88 | This is my Widget
89 |
90 | ```
91 |
92 | ***Example: Separated styling: CSS***
93 |
94 | ```css
95 | .myClass {
96 | color:red;
97 | font-weight:bold;
98 | }
99 | ```
100 |
101 |
102 | ### Recommendation #2: Parametrized CSS Styles
103 |
104 | You can use dynamic data binding inside the CSS/Less definition.
105 |
106 | #### Dynamic CSS properties
107 |
108 | ***CSS/Less:***
109 | ```css
110 | /* settings.foreColor = #efefef */
111 | .myClass {
112 | color: {{settings.foreColor}};
113 | }
114 | ```
115 |
116 | #### Styling with Less variables
117 |
118 | ***CSS/Less:***
119 | ```css
120 | /* layout.property1 = #efefef */
121 | @color: {{settings.foreColor}};
122 |
123 | .myClass {
124 | color: @color; /* Use the Less variable */
125 | }
126 | ```
127 |
128 | ## References & further readings
129 |
130 | - [Less](http://lesscss.org/)
131 |
132 |
--------------------------------------------------------------------------------
/src/subjects/styling-widgets/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Styling widgets"
3 | ---
4 |
5 | (TBD)
6 |
--------------------------------------------------------------------------------
/src/subjects/sys-info/images/result_dimensions_measures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/sys-info/images/result_dimensions_measures.png
--------------------------------------------------------------------------------
/src/subjects/sys-info/images/result_sheets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/sys-info/images/result_sheets.png
--------------------------------------------------------------------------------
/src/subjects/sys-info/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: The sys-info component
3 | sub-title: "Work with meta-data from Qlik Sense and use them in your widget."
4 | ---
5 |
6 | ## Introduction
7 |
8 | You can retrieve system meta-information to support the development process of widgets or you can add system meta information to custom visualizatons using the qw-sys-info component. The following system metadata information can be retrieved:
9 |
10 | - All apps.
11 | - Sheets and objects in the current app.
12 | - Visualizations in the current app.
13 | - Dimensions and measures in the current app.
14 | - All visualization extensions available.
15 | - All widgets available.
16 | - All bookmarks available.
17 | - All current selections.
18 | - All master objects.
19 |
20 | ## Usage
21 |
22 | **Html:**
23 | ```html
24 |
25 |
26 |
28 |
29 |
30 | ```
31 |
32 | **Result:**
33 | (when Helpdesk Management app is selected)
34 |
35 | 
36 |
37 | ## Properties
38 |
39 | The following properties can be used, separated by commas to fetch system information:
40 |
41 | - apps
42 | - sheets
43 | - fields
44 | - measures
45 | - dimensions
46 | - extensions
47 | - bookmarks
48 | - currentselections
49 | - masterobjects
50 | - visualizations
51 |
52 | ## Multiple information
53 |
54 | You can not only fetch one entity but you can combine multiple as shown in the example below:
55 |
56 | ```html
57 |
58 | Dimensions:
59 |
60 |
61 |
62 | Measures:
63 |
64 |
65 |
66 |
67 | ```
68 |
69 | 
70 |
--------------------------------------------------------------------------------
/src/subjects/widget-editor/images/distraction-free-mode.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/widget-editor/images/distraction-free-mode.gif
--------------------------------------------------------------------------------
/src/subjects/widget-editor/images/distraction-free-mode.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/widget-editor/images/distraction-free-mode.mp4
--------------------------------------------------------------------------------
/src/subjects/widget-editor/images/insert-icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/widget-editor/images/insert-icons.png
--------------------------------------------------------------------------------
/src/subjects/widget-editor/images/insert-properties.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/widget-editor/images/insert-properties.png
--------------------------------------------------------------------------------
/src/subjects/widget-editor/images/insert-snippets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/widget-editor/images/insert-snippets.png
--------------------------------------------------------------------------------
/src/subjects/widget-editor/images/resizable-code-areas.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/widget-editor/images/resizable-code-areas.gif
--------------------------------------------------------------------------------
/src/subjects/widget-editor/images/resizable-code-areas.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/widget-editor/images/resizable-code-areas.mp4
--------------------------------------------------------------------------------
/src/subjects/widget-editor/images/resize-font.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/subjects/widget-editor/images/resize-font.png
--------------------------------------------------------------------------------
/src/subjects/widget-editor/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: The Widget Editor
3 | sub-title: "Get to know the new Widget editor and how it works."
4 | ---
5 |
6 | ## The Widget Editor
7 |
8 | The Widget editor is the main tool for a [Widget creator](../personas/#widget-creator) to design, create and develop a widget.
9 |
10 | ### Launch the Widget editor
11 |
12 | Access the Widget editor through Dev Hub either by opening an existing Widget library or by just opening the tool.
13 |
14 | ### The structure
15 |
16 | It seems to be unnecessary to describe a UI, but it is on the other hand important to understand some basic concepts of the Widget editor.
17 |
18 | First of all the UI of the Widget editor is separated into different areas:
19 |
20 | 1) Asset panel
21 | 2) Editor
22 | 3) Immediate preview
23 | 4) Property panel / Property panel builder
24 |
25 | ### Insert dialogs
26 |
27 | Use the insert dialog to easily insert
28 |
29 | - Code snippets
30 | - Icons
31 | - Properties
32 |
33 | **Code snippets**
34 |
35 | 
36 |
37 | **Icons**
38 |
39 | 
40 |
41 |
42 | **Properties**
43 |
44 | 
45 |
46 |
47 |
48 | ### Little convenience helpers
49 |
50 | The Widget editor includes some nice little helpers to make the work with Widget more enjoyable:
51 |
52 | **Adapt coding areas**
53 |
54 | 
55 |
56 | **Distraction free mode & resizable preview**
57 |
58 | Focus on what you are working on, all-together, only Html, only CSS, etc.
59 | 
60 |
61 | **Resizable font size**
62 |
63 | Adjust the font size of the code areas. Especially useful if you present Widget on stage or in a presentation.
64 |
65 | 
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/subjects/widget-organization/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Widget organization
3 | sub-title: "Widgets can be organized in Widget libraries."
4 | ---
5 |
6 | ## What makes a Widget unique?
7 | When you create a widget in the Widget editor (Dev Hub), a unique Id (Global Unique Identifier) will be created, this makes the widget unique.
8 | This unique Id will be kept, regardless you move or export the widget. The unique Id will also be used to check for duplicates if you import a Widget library.
9 |
10 | **Attention:**
11 | Although widget libraries can be imported either in the QMC or in Dev Hub, the check for the uniqueness of a widget will (as of Qlik Sense 3.0) only be performed in Dev Hub.
12 | It his therefore highly recommended that - if you are not 100% sure that a widget does not exist - you only use the Dev Hub import for widget libraries.
13 |
14 |
15 | ## Organizing widgets in libraries
16 |
17 | {{#hl}}(TBD){{/hl}}
18 |
--------------------------------------------------------------------------------
/src/subjects/widgets-vs-visualization-extensions/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Widgets vs. Visualization extensions"
3 | ---
4 |
5 | Widgets and visualization extensions try to achieve the same goal: **_Bring new custom visualizations to Qlik Sense_**.
6 | It is therefore a very legitimate question, when to use which of those two approaches.
7 |
8 | Here are some guidelines:
9 |
10 | **Use the concept of widgets if:**
11 |
12 | - You have no (web-)programming skills and don't want to investigate too much time.
13 | - You have decent Html/CSS skills or you want to invest 1-2 days to learn those fundamental building-blocks of the web.
14 | - You have some Html/CSS code-snippets resulting into a custom visualization and you'd just like to bring those into Qlik Sense.
15 | - You (as a partner) would like to share a library of custom visualizations with your customer.
16 | - You would like to create a set of Corporate Design aligned visualization which can then be used by all Qlik Sense users.
17 | - Time to value is key for you.
18 |
19 | **Use the concept of visualization extensions if:**
20 |
21 | - You have decent skills (web-)programming skills, especially covering JavaScript.
22 | - You need to include an external library (e.g. charting-library) into your custom visualization.
23 | - You need to add (whatever) piece of JavaScript to your custom visualization.
24 |
--------------------------------------------------------------------------------
/src/tutorial/00-toc/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Tutorial: Getting Started with Widgets"
3 | ---
4 |
5 | ## About
6 |
7 | If you don't want to read a lot of theory and documentation about the widget concept, then you are at the right place.
8 | Welcome to the widget tutorial, a step by step guide to learn the basic concepts of widgets in Qlik Sense.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/tutorial/01-prerequisites/downloads/widget-exercises.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/01-prerequisites/downloads/widget-exercises.zip
--------------------------------------------------------------------------------
/src/tutorial/01-prerequisites/images/dev-hub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/01-prerequisites/images/dev-hub.png
--------------------------------------------------------------------------------
/src/tutorial/01-prerequisites/images/open-dev-hub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/01-prerequisites/images/open-dev-hub.png
--------------------------------------------------------------------------------
/src/tutorial/01-prerequisites/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Prerequisites
3 | sub-title: "What's needed running this tutorial."
4 | ---
5 |
6 | All you need for the following exercises are
7 |
8 | - Qlik Sense Desktop 3.x or
9 | - Qlik Sense Server 3.x
10 |
11 | - [The widget library "widget-exercises"](downloads/widget-exercises.zip)
12 |
13 | In case of Qlik Sense Server open [http[s]://server-name/hub](http[s]://server-name/hub), in case of Qlik Sense Desktop open [http://localhost:4848/hub](http://localhost:4848/hub)
14 |
15 | ## Open Dev Hub
16 | In the hub go to the menu and open Dev Hub:
17 |
18 | 
19 |
20 | *Note: In case of Qlik Sense Desktop a new browser window will be opened, minimize the instance of Qlik Sense Desktop while working in the newly opened browser window.*
21 |
22 | In **Dev Hub** you will not only see a new link pointing you to the Widget editor, but also all existing Widget libraries will be shown:
23 |
24 | 
25 |
--------------------------------------------------------------------------------
/src/tutorial/02-basic-concept/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "The Basic Concept"
3 | sub-title: "Make yourself familiar with the basic concepts of the Widget editor."
4 | ---
5 |
6 | ## Exercise
7 |
8 | - Open the Widget library "widget-exercises"
9 | - Create a new widget in the Widget library “widget-exercises”
10 | - Add some “Hello world” in the HTML area and add some formatting in the CSS/Less area
11 | (Always use CSS classes instead of IDs, so `.my-formatting` instead of `#my-object`)
12 | - Save the Widget
13 | - Move your widget to a new library
14 | - Make some modifications (e.g. just add a space) and move the copy back to the library “widget-exercises”
15 | - Use your newly created Widget in an existing app
16 | (do not forget to refresh the browser to get the updated list of Widgets)
17 | - etc.
18 |
--------------------------------------------------------------------------------
/src/tutorial/actions/images/example-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/actions/images/example-1.png
--------------------------------------------------------------------------------
/src/tutorial/actions/images/example-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/actions/images/example-2.png
--------------------------------------------------------------------------------
/src/tutorial/actions/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Actions"
3 | sub-title: "Leverage the power of actions in widgets"
4 | ---
5 |
6 | ## Exercise
7 |
8 | - Start with a new widget (in your existing library)
9 | - Use the insert dialog to insert nicely formatted buttons from the Leonardo UI library
10 | - Add one of the predefined actions by using `ng-click`
11 | - Add some buttons and test the functionality by adding a Widget instance to one of your sheets.
12 |
13 | ## Solution Path
14 |
15 | This shows a sample widget using several actions:
16 |
17 | **Html**
18 |
19 | ```html
20 |
21 | Back
22 | Clear All
23 | Forward
24 |
25 | ```
26 |
27 |
28 | **CSS**
29 |
30 | ```css
31 | & {
32 | padding:10px 10px 10px 10px;
33 |
34 | .lui-button {
35 | min-width:100px;
36 | }
37 | }
38 | ```
39 |
40 | **Result**
41 |
42 | 
43 |
44 |
45 | And another sample widget using actions:
46 |
47 |
48 | **Html**
49 | ```html
50 | Prev Sheet
51 | Next Sheet
52 | ```
53 |
54 |
55 | **CSS**
56 | ```css
57 | & {
58 | padding:10px 10px 10px 10px;
59 |
60 | .lui-button {
61 | min-width:100px;
62 | }
63 | }
64 | ```
65 |
66 | **Result**
67 |
68 | 
69 |
70 |
71 | ## Sample Solution
72 |
73 | By opening the widget "Result: Actions" (widget library "widget-exercises") you can have a look at a proposed solution.
74 |
75 |
76 | ## Bonus Exercise
77 |
78 | - Use the newly created widget in combination with a KPI tile to see changes made in selections.
79 |
--------------------------------------------------------------------------------
/src/tutorial/angularjs-basic/readme.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/angularjs-basic/readme.md
--------------------------------------------------------------------------------
/src/tutorial/angularjs-binding/images/create-property.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/angularjs-binding/images/create-property.gif
--------------------------------------------------------------------------------
/src/tutorial/angularjs-binding/images/create-property.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/angularjs-binding/images/create-property.mp4
--------------------------------------------------------------------------------
/src/tutorial/angularjs-binding/images/result.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/angularjs-binding/images/result.gif
--------------------------------------------------------------------------------
/src/tutorial/angularjs-binding/images/result.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/angularjs-binding/images/result.mp4
--------------------------------------------------------------------------------
/src/tutorial/angularjs-binding/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: AngularJS Binding
3 | sub-title: "Use AngularJS to make your widgets more dynamic."
4 | ---
5 |
6 | We have already touched some very basic concepts of AngularJS in previous chapters.
7 |
8 | Now let's work on an example how to bind some logic to a property in the property panel. We want to show some conditional content, depending on whether a checkbox is checked or not.
9 |
10 | Let's start with the exercise "Exercise: AngularJS Binding", then follow these steps:
11 |
12 | - Create a checkbox property, give it a label "Show Details" and a reference named "`showDetails`"
13 | - Create some nicely formatted content which
14 | - is only displayed if `showDetails` is not checked
15 | - is only displayed if `showDetails` is checked
16 |
17 |
18 | ## Solution
19 |
20 | First create the property:
21 |
22 | 
23 |
24 | Then let's add some Html code
25 |
26 | ```html
27 |
33 | ```
34 |
35 | ... and the corresponding CSS code
36 |
37 | ```css
38 | .details {
39 | ul {
40 | margin-left:30px;
41 | }
42 | }
43 | .eof {
44 | color: #990000;
45 | font-weight: bold;
46 | }
47 | ```
48 |
49 | Not really exciting so far, let's add the magic stuff.
50 | We are now using a - so called - AngularJS directive which removes or adds a portion of the HTML shown in the browser depending on a condition - in our case the value of the property `showDetails` (which can either be `true` or `false`).
51 |
52 | ***Modified Html:***
53 |
54 | ```html
55 |
56 |
57 | ...
58 |
59 |
60 |
61 |
62 | ...
63 |
64 | ```
65 |
66 |
67 | OK, much better, we have now a working conditional rendering, based on the value of the property `showDetails`:
68 |
69 | 
70 |
71 |
72 | **Finally:**
73 | A proposed solution can be found in the widget "Result: AngularJS Binding" (widget library "widget-exercises").
74 |
75 | ## References
76 |
77 | - [AngularJS: ngIf](https://docs.angularjs.org/api/ng/directive/ngIf)
78 | - [AngularJS: ngShow](https://docs.angularjs.org/api/ng/directive/ngShow)
79 | - [AngularJS: ngHide](https://docs.angularjs.org/api/ng/directive/ngHide)
80 |
--------------------------------------------------------------------------------
/src/tutorial/containers/images/result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/containers/images/result.png
--------------------------------------------------------------------------------
/src/tutorial/containers/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Bonus: Creating Containers"
3 | ---
4 |
5 | Create a Widget using several containers and a simple navigation between these containers as shown in the solution “Result-Simple-Container”:
6 |
7 | 
8 |
9 | ## Solution
10 |
11 | By opening the widget "Result: Simple Container" (widget library "widget-exercises") you can have a look at one proposed solution.
12 |
--------------------------------------------------------------------------------
/src/tutorial/css-less/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Using CSS & Less"
3 | sub-title: "Leverage the power of Less & properties to make widgets generic."
4 | ---
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/3-properties.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/3-properties.png
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/3-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/3-result.png
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/add-reference.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/add-reference.gif
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/add-reference.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/add-reference.mp4
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/create-header.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/create-header.gif
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/create-header.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/create-header.mp4
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/custom-property-result.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/custom-property-result.gif
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/custom-property-result.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/custom-property-result.mp4
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/dropdown-props.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/dropdown-props.png
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/dropdown-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/dropdown-result.png
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/new-input-property.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/new-input-property.gif
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/new-input-property.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/new-input-property.mp4
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/images/open-property-panel-builder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/custom-properties/images/open-property-panel-builder.png
--------------------------------------------------------------------------------
/src/tutorial/custom-properties/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Custom properties
3 | ---
4 |
5 | As we now know how to bind properties to the widget output, let's create some custom properties (using the Property Panel builder).
6 |
7 | One of the essential concepts behind widgets is that the widget creator can define how the widget instance can be configured by the end-user. Therefore - as a widget creator - you can define properties, which define the behavior of your widget and which can then be used by the user.
8 |
9 | ## Helper for the following exercises
10 |
11 | As a little helper for the following exercises use the existing widget called "Exercise: Custom Properties" from widget library "widget-exercises".
12 |
13 | This provides some CSS and a little code snippet which makes it easier to output some values:
14 |
15 | ***Html:***
16 | ```html
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | ```
32 |
33 | ***CSS:***
34 | ```css
35 | .widget-properties {
36 |
37 | padding: 10px 10px 10px 10px;
38 |
39 | h2 {
40 | font-size:18px;
41 | color: #999;
42 | margin-bottom:20px;
43 | }
44 |
45 | .row {
46 | border-bottom: 1px solid #ccc;
47 | padding-top:2px;
48 | padding-bottom:2px;
49 | }
50 |
51 | .row:after {
52 | content: ".";
53 | display: block;
54 | height: 0;
55 | clear: both;
56 | visibility: hidden;
57 | }
58 |
59 | .row .label {
60 | font-weight: bold;
61 | min-width: 100px;
62 | display:inline-block;
63 | padding-right:20px;
64 | }
65 |
66 | .row .val {
67 | display:inline-block;
68 | }
69 |
70 | .row:nth-child(2n) {
71 | background-color:#F7F7F9;
72 | }
73 | }
74 | ```
75 |
76 |
77 |
78 | ## Exercise 1: Create a basic input field
79 |
80 | - Create a basic input field using the Property Panel builder
81 | - Render the value of the input field in your widget
82 |
83 | ## Exercise 2: Create a drop-down
84 |
85 | - Create a property using the drop-down type
86 | - Render the selected value in your widget
87 |
88 | ## Exercise 3: Create a drop-down and create a binding in CSS
89 |
90 | - Create another drop-down field
91 | - Add some values, representing the background-color of your widget
92 | - Bind the value not to Html, but use it in your CSS declaration
93 |
94 | ---
95 |
96 | {{#hl}}Don't proceed, first try it, then have a look at the solution ;-){{/hl}}
97 |
98 |
99 | ## Solution exercise #1: Create a basic input field
100 |
101 | Assuming that you are using the existing widget "Exercise: CustomProperties" you can succeed with exercise #1 by following these steps:
102 |
103 | **1) Open the Property Panel builder**
104 |
105 | 
106 |
107 | **2) Create a new property**
108 | **2a) First create a new header**
109 | Drag and drop the header to the Property Panel.
110 |
111 | 
112 |
113 | **2b) Add a new item to the new header**
114 |
115 | 
116 |
117 | **2c) Finish the editing mode of the Property Panel builder**
118 |
119 | **3) Create a reference to the property in your HTML**
120 |
121 | 
122 |
123 | **4) Test the property**
124 |
125 | Now you can change the value of the property and you'll get an updated widget depending on what you've entered in the property object.
126 |
127 | 
128 |
129 |
130 | A proposed solution can be reviewed in the widget "Result: Custom Properties"
131 |
132 | ## Solution exercise #2: Create a drop-down
133 |
134 | A proposed solution can be reviewed in the widget "Result: Custom Properties II":
135 |
136 | 
137 |
138 | 
139 |
140 |
141 | ## Solution exercise #3: Create a drop-down and create a binding in CSS
142 |
143 | A proposed solution can be review in the widget "Result: Custom Properties III" (widget library "widget-exercises"):
144 |
145 | 
146 |
147 | 
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/src/tutorial/data-binding/images/result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/data-binding/images/result.png
--------------------------------------------------------------------------------
/src/tutorial/data-binding/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Basic Data Binding"
3 | sub-title: "Data binding is the essential concept to make your Widgets useful and re-usable."
4 | ---
5 |
6 | ## Exercise
7 |
8 | - Create a new widget, call it “Data-Binding” or use the existing widget “Exercise: DataBinding” from the widget library “widget-exercises”.
9 | - Now let's visualize the default properties which are always available, for every widget:
10 | - Title (`settings.title`)
11 | - Subtitle (`settings.subtitle`)
12 | - Footnote (`settings.footnote`)
13 | - Use the “Insert” dialog to insert references to the properties in your HTML area using the double curly braces syntax, e.g. `\{{settings.title}}`
14 | - Alternatively use AngularJS’ directive `ng-bind` which is a bit harder to read, but from a performance perspective the preferred option.
15 | (there is an example in the widget “Exercise: DataBinding”)
16 | - Save the widget and double-check if rendering works properly in an existing app.
17 |
18 | The final result should render a table with some properties in a format similar like the following one:
19 |
20 | 
21 |
22 | {{#hl}}Don't proceed, first try it, then have a look at the solution ;-){{/hl}}
23 |
24 | ## Solution
25 |
26 | By opening the widget "Result: DataBinding" (widget library "widget-exercises") you can have a look at the proposed solution.
27 |
28 |
29 | ## References and further readings
30 |
31 | - [Debugging widgets](../../subjects/debugging)
32 | - [AngularJS ngBind](https://docs.angularjs.org/api/ng/directive/ngBind)
33 |
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile-advanced/images/result.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/kpi-tile-advanced/images/result.gif
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile-advanced/images/result.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/kpi-tile-advanced/images/result.mp4
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile-advanced/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Create an advanced KPI tile"
3 | sub-title: "The goal is to create an advanced KPI tile using the Widget concept."
4 | ---
5 |
6 | Now we have learned the basics. Let's use all the concepts together to create an advanced KPI tile.
7 |
8 | ## Goal
9 |
10 | The KPI tile should offer the following functionality:
11 |
12 | - The user can add one or more (up to three) measures to be displayed
13 | - In the first view only the most important KPI will be shown, the user has the possibility to show more KPIs on demand
14 | - The user should be able to add an explanatory description
15 | - The user can select the style in the property panel
16 | - The style also includes an icon displayed next to the KPIs
17 | - The user should be able to define a URL, which will represent a web-page, containing more details about the KPIs
18 | - The KPI tile should be fully responsive
19 |
20 | 
21 |
22 | ## Solution
23 |
24 | Have a look into the "Drill KPI", part of the sample widgets, delivered with Qlik Sense.
25 |
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile/images/property-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/kpi-tile/images/property-color.png
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile/images/property-comparison-kpi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/kpi-tile/images/property-comparison-kpi.png
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile/images/property-kpi-title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/kpi-tile/images/property-kpi-title.png
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile/images/property-kpi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/kpi-tile/images/property-kpi.png
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile/images/result.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/kpi-tile/images/result.gif
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile/images/result.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/kpi-tile/images/result.mp4
--------------------------------------------------------------------------------
/src/tutorial/kpi-tile/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Simple KPI tile"
3 | sub-title: "The goal is to create a simple KPI tile using the widget concept."
4 | ---
5 |
6 | ## Exercise
7 |
8 | Start by using the existing widget template “Exercise: Minimalistic KPI” in the widget library “widget-exercises”.
9 | - Create a new header in the property panel called “Settings”
10 | - Create the following custom properties using the Property Panel editor
11 | - Title (Input, name “Title”, reference `kpiTitle`)
12 | - KPI (Input, name “KPI”, reference `kpi`)
13 | - Color, containing the values “red”, “green” & “orange” as keys, choose appropriate labels (reference `color`)
14 | - Comparison KPI (Input, reference `comparisionKPI`)
15 | - First extend the existing Widget to make it fully dynamic
16 | - Title, KPI and the color should be bound to the properties defined by the user.
17 | - Test the KPI extensively in an existing app
18 |
19 | {{#hl}}Don't proceed, first try it, then have a look at the solution ;-){{/hl}}
20 |
21 | ## Solution
22 |
23 | First create the properties:
24 |
25 | **`kpiTitle`**
26 |
27 | 
28 |
29 | **`kpi`**
30 |
31 | 
32 |
33 | **`color`**
34 |
35 | 
36 |
37 | **`comparisonKPI`**
38 |
39 | 
40 |
41 | Now let's add bind the HTML output to some of the properties:
42 |
43 | ```html
44 |
45 |
\{{settings.kpiTitle}}
46 |
\{{settings.kpi}}
47 |
\{{settings.comparisonKPI}}
48 |
49 | ```
50 |
51 | So far we have bound all properties, except the `color` property.
52 | And here comes a nice trick:
53 |
54 | - If you have a look at the CSS, you'll find some classes there:
55 | - `.bar-green`
56 | - `.bar-orange`
57 | - `.bar-red`
58 | - Now let's bind to these classes, depending on the selected color:
59 |
60 | ```html
61 | ...
62 |
\{{settings.comparisonKPI}}
63 | ...
64 | ```
65 |
66 | ## The Final Result
67 |
68 | 
69 | A proposed solution can be review in the widget "Result: Minimalistic KPI" (widget library "widget-exercises").
70 |
--------------------------------------------------------------------------------
/src/tutorial/leonardo-ui/images/result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stefanwalther/widget-tutorial/03594ea3491842c1dfbce208beaaadc2d9d42916/src/tutorial/leonardo-ui/images/result.png
--------------------------------------------------------------------------------
/src/tutorial/leonardo-ui/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Using Leonardo-UI"
3 | sub-title: "Bring the typical Look & Feel of Qlik Sense into your widgets."
4 | ---
5 |
6 | ## Exercise
7 |
8 | - Create a new widget and call it “Leonardo-UI”
9 | - Use the “Insert” dialog to add code snippets using Leonardo-UI
10 |
11 | ## Bonus exercise
12 |
13 | - Make e.g. a ButtonGroup dynamic by combining Leonardo-UI and AngularJS
14 |
15 | ## Solution
16 |
17 | This is how your widget could look like:
18 |
19 | 
20 |
21 | A possible result can be seen in “Result: Leonardo-UI” as part of the widget library “widget-exercises”.
22 |
23 |
--------------------------------------------------------------------------------
/src/tutorial/working-with-data/readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Working with Data"
3 | sub-title: "Create a widget and render a hyperCube with custom formatting"
4 | ---
5 |
6 | ## Exercise
7 |
8 | - Open the widget „Exercise: FormattedTable“ from the widget library „widget-exercises“.
9 | - Create a data section using the Property Panel editor. Choose some meaningful settings for the data section.
10 | - Iterate through dimensions and measures to render the output (use e.g. the code snippet "Table created based on dimensions and measures" )
11 |
12 | ## Bonus Exercise
13 |
14 | - Create buttons (e.g by using Leonardo-UI) in every row, linking dynamically to an external website.
15 |
16 |
--------------------------------------------------------------------------------
/widget-exercises/0448b7cd-0943-7f5b-9da6-445df9557354.html:
--------------------------------------------------------------------------------
1 |
47 |
--------------------------------------------------------------------------------
/widget-exercises/0448b7cd-0943-7f5b-9da6-445df9557354.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Exercise: Formatted Table",
3 | "description": "",
4 | "author": "",
5 | "library": "widget-exercises",
6 | "meta": {
7 | "type": "table"
8 | },
9 | "properties": {}
10 | }
--------------------------------------------------------------------------------
/widget-exercises/04ccf2f4-1e29-6e75-7c92-911ff797d4ce.html:
--------------------------------------------------------------------------------
1 |
15 |