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 environment
const 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 settings
const 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 environment
const 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 settings
const 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>