Working with Qlik Sense bookmarks
Introduction
Bookmarks in Qlik Sense are a way to save selections for later use. You can create, interact with, and delete bookmarks using qlik-embed.
A complete example is available at the end of this guide.
Prerequisites
To use the example page in this guide, ensure that you have the following:
- An existing app ID and sheet ID to embed. This example uses this demo app that you can freely download and use.
- A SPA OAuth2 client configured.
Variable substitution and vocabulary
Throughout this tutorial, variables will be used to communicate value placement.
The variable substitution format is VARIABLE_NAME
or <VARIABLE_NAME>
. Here is a list of
variables that appear in the sample code.
Variable | Description |
---|---|
QLIK_TENANT_URL | The domain for the tenant you are accessing. Equivalent to tenant.region.qlikcloud.com . |
QLIK_OAUTH_CLIENT_ID | The clientId of the OAuth SPA you configured. |
QLIK_REDIRECT_URI | The Redirect URL for the OAuth2 client to provide an access token. |
QLIK_APP_ID | The unique identifier of the application. |
QLIK_OBJECT_ID | The unique identifier of the sheet. |
This example loads these values from process.env
, which you can set in a .env
file
and reference when running the example with node.js 20+ using node --env-file=.env server.js
.
You must connect to the Qlik Sense app before applying existing bookmarks
or creating new ones. You do this using the qix.openAppSession
method.
import { auth, qix } from "https://cdn.jsdelivr.net/npm/@qlik/api/index.js";
// Retrieve settings from environmentconst QLIK_TENANT_URL = process.env.QLIK_TENANT_URL;const QLIK_OAUTH_CLIENT_ID = process.env.QLIK_OAUTH_CLIENT_ID;const QLIK_APP_ID = process.env.QLIK_APP_ID;const QLIK_SHEET_ID = process.env.QLIK_SHEET_ID;const QLIK_REDIRECT_URI = process.env.QLIK_REDIRECT_URI;
// OAuth authentication settingsconst hostConfig = { host: QLIK_TENANT_URL, authType: "oauth2", clientId: QLIK_OAUTH_CLIENT_ID, redirectUri: QLIK_REDIRECT_URI};
auth.setDefaultHostConfig(hostConfig);
let app;
async function initQlik() { try { const session = await qix.openAppSession(QLIK_APP_ID); app = await session.getDoc(); console.log("Qlik app initialized:", app); } catch (error) { console.error("Error initializing Qlik:", error); }}
Examples of use
Learn what you can do with the Bookmark API.
Create a new bookmark based on the current selection
Use the createBookmark
method of the Qix Doc object object to create a bookmark based on the
current selection.
let bmkId = null;
async function createBookmarks() { if (!app) { console.error("App is not initialized"); return; }
try { const newBookmark = await app.createBookmark({ qInfo: { qType: "bookmark", }, qMetaDef: { title: "MyBookmark", // You can add more meta properties as needed }, qData: { bookmark: "MyBookmark", description: "This is a sample bookmark", // Add more data properties as needed }, }); console.log("BookmarkId created:", newBookmark.id); bmkId = newBookmark.id; } catch (error) { console.error("Error creating bookmark:", error); }}
The JSON payload provided as a parameter to the createBookmark
method contains these properties:
qType
: The type of object being created. In this case, a bookmark. Must be part of theqInfo
object.title
: The title is the value shown in the Qlik Sense user interface when users access bookmarks. Must be part of theqMetaDef
object.description
: A snippet of text for telling users what the bookmark is going to do. Must be part of theqData
object.
Remove a bookmark that you have applied
Use the destroyBookmark
method to remove an existing bookmark.
async function removeBookmark(bookmarkId) { if (!app) { console.error("App is not initialized"); return; }
if (!bookmarkId) { console.error("bookmarkId is not initialized"); return; }
try { await app.destroyBookmark(bookmarkId); console.log("Bookmark removed:", bookmarkId); } catch (error) { console.error("Error removing bookmark:", error); }}
Full code example
Below is an example built using qlik-api and qlik-embed web components.
Style sheet: web-component-bookmark.css
body,html { margin: 0; padding: 0; font-family: sans-serif; font-size: 14px; background-color: #f5f5f5; color: #333; height: 100%; width: 100%;}
.flex-container { display: flex; flex-wrap: wrap; margin: 0 45px 45px 0;}
.qvobject { flex: 1 1 auto; height: 300px; min-width: 400px; margin: 45px 0 0 45px;}
.buttons-container { position: fixed; top: 10px; left: 10px; z-index: 1000;}
button { margin-right: 10px;}
JavaScript: web-component-bookmark.js
import { auth, qix } from "https://cdn.jsdelivr.net/npm/@qlik/api/index.js";
// Retrieve settings from environmentconst QLIK_TENANT_URL = process.env.QLIK_TENANT_URL;const QLIK_OAUTH_CLIENT_ID = process.env.QLIK_OAUTH_CLIENT_ID;const QLIK_APP_ID = process.env.QLIK_APP_ID;const QLIK_SHEET_ID = process.env.QLIK_SHEET_ID;const QLIK_REDIRECT_URI = process.env.QLIK_REDIRECT_URI;
// OAuth authentication settingsconst hostConfig = { host: QLIK_TENANT_URL, authType: "oauth2", clientId: QLIK_OAUTH_CLIENT_ID, redirectUri: QLIK_REDIRECT_URI};
auth.setDefaultHostConfig(hostConfig);
let app;
async function initQlik() { try { const session = await qix.openAppSession(QLIK_APP_ID); app = await session.getDoc(); console.log("Qlik app initialized:", app); } catch (error) { console.error("Error initializing Qlik:", error); }}
let bmkId = null;
async function createBookmarks() { if (!app) { console.error("App is not initialized"); return; }
try { const newBookmark = await app.createBookmark({ qInfo: { qType: "bookmark", }, qMetaDef: { title: "MyBookmark", // You can add more meta properties as needed }, qData: { bookmark: "MyBookmark", description: "This is a sample bookmark", // Add more data properties as needed }, }); console.log("BookmarkId created:", newBookmark.id); bmkId = newBookmark.id; } catch (error) { console.error("Error creating bookmark:", error); }}
async function removeBookmark(bookmarkId) { if (!app) { console.error("App is not initialized"); return; }
if (!bookmarkId) { console.error("bookmarkId is not initialized"); return; }
try { await app.destroyBookmark(bookmarkId); console.log("Bookmark removed:", bookmarkId); } catch (error) { console.error("Error removing bookmark:", error); }}
document.addEventListener("DOMContentLoaded", async () => { await initQlik(); document.getElementById("toggleBookmark").addEventListener("click", createBookmarks); document.getElementById("removeBookmark").addEventListener("click", () => { removeBookmark(bmkId); });});
HTML: web-component-bookmark.html
<!doctype html><html lang="en">
<head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <link rel="stylesheet" href="<QLIK_TENANT_URL>/resources/autogenerated/qlik-styles.css" /> <link rel="stylesheet" href="web-component-variable.css" /> <script crossorigin="anonymous" type="application/javascript" src="https://cdn.jsdelivr.net/npm/@qlik/embed-web-components@1/dist/index.min.js" data-host="<QLIK_TENANT_URL>" data-client-id="<QLIK_OAUTH_CLIENT_ID>" data-redirect-uri="<QLIK_REDIRECT_URI>" data-access-token-storage="session"></script> <script type="module" src="web-component-bookmark.js"></script></head>
<body> <div class="buttons-container"> <button id="toggleBookmark">Toggle bookmark</button> <button id="removeBookmark">Remove bookmark</button> </div> <div class="flex-container"> <div class="qvobject"> <qlik-embed ui="analytics/chart" app-id="<QLIK_APP_ID>" object-id="<QLIK_OBJECT_ID>" /> </div> </div></body>
</html>