Skip to content

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:

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.

VariableDescription
QLIK_TENANT_URLThe domain for the tenant you are accessing. Equivalent to tenant.region.qlikcloud.com.
QLIK_OAUTH_CLIENT_IDThe clientId of the OAuth SPA you configured.
QLIK_REDIRECT_URIThe Redirect URL for the OAuth2 client to provide an access token.
QLIK_APP_IDThe unique identifier of the application.
QLIK_OBJECT_IDThe 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 the qInfo object.
  • title: The title is the value shown in the Qlik Sense user interface when users access bookmarks. Must be part of the qMetaDef object.
  • description: A snippet of text for telling users what the bookmark is going to do. Must be part of the qData 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>

Was this page helpful?