Время прочтения: 8 мин.
Всем привет!
Сегодня расскажу, как я расширял стандартные возможности Qlik Sense для управления значениями переменных c помощью extensions, владея основами html, css и JavaScript.
При реализации моей командой на Qlik Sense приложения с большим объемом данных столкнулись с проблемой длительного отображения данных в таблице на листе визуализации. То есть, чем больше объем данных, тем медленнее они отображались в визуализациях и пересчитывались при осуществлении выборок. Один из вариантов увеличения производительности приложения QS — предложить пользователю использовать фильтры, а потом отображать данные в визуализации. Но для выполнения моей задачи, в качестве фильтра, было решено использовать текстовое поле для ввода пользователем данных.
Базовых возможностей и функционала Qlik Sense для его реализации оказалось недостаточно.
В Qlik Sense есть визуализация Variable Input (Input Box) в пакете Qlik Dashboard bundle:
Но, к сожалению, в Variable Input отсутствует возможность задавать «маску» ввода данных, т.е. я не смогу оградить пользователя от случайной или намеренной ошибки. Также, введенные значения мне необходимо передавать в переменную Qlik Sense без перезагрузки данных в приложении.
Поэтому было принято решение создать собственную визуализацию для Qlik Sense, состоящую из текстового поля и кнопки, в которой будет проверяться на корректность введенное значение по «маске корпоративной почты» и всплывать уведомление для пользователя. В документации и в самом приложении Qlik Sense визуализации называются Extension, дальше по тексту буду их называть визуализациями, для упрощения понимания.
- Создание собственной визуализации. Маска ввода данных:
1.1. Для разработки собственной визуализации необходимо войти в режим разработчика, для этого перехожу на главную страницу Hub Qlik Sense, и дальше нажимаю «Dev Hub»:
1.2. Перехожу на вкладку с визуализациями «Visualization extensions»:
Нажимаю на кнопку «Create new extension»:
Выбираю название и шаблон (я бы для начала рекомендовал выбрать шаблон «Basic Visualization template», как показано на рисунке ниже)
1.3. Откроется 2 вкладки [название_визуализации].qext и [название_визуализации].js:
Файл (открытая вкладка – далее файл) с расширением .qext содержит объект json, который определяет метаданные объекта визуализации (имя визуализации, связанные файлы, версия и тд).
Файл с расширением .js содержит js-код, который отвечает за визуальную составляющую.
- 4. При необходимости можно добавлять другие файлы необходимых форматов. Например, создам файл с расширением .html, для этого захожу в меню в верхнем левом углу, нажимаю «New file»:
В открывшемся окне прописываю название и нужное расширение (в моем случае .html):
После нажатия на кнопку «Create» в визуализации появился еще один файл.
Таким образом можно создавать множество разных файлов с разными форматами и даже подключать библиотеки!
- 4.1. Листинг кода созданной визуализации для проверки электронной почты:
qext: //файл формата .qext формируется автоматически при создании визуализации QS
{
"name": "TestExtension",
"description": "Basic empty visualization template",
"type": "visualization",
"version": "1.0.0",
"icon": "extension",
"author": "",
"homepage": "",
"keywords": "qlik-sense, visualization",
"license": "",
"repository": "",
"dependencies": {
"qlik-sense": ">=3.0.x"
}
}
html: //гипертекстовая разметка для отображения элементов веб-страницы
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> //стандартные метаданные страницы
</head>
<body>
<p id="message" >Пожалуйста, заполните форму!</p><br/> // параграф с текстом
<p>E-mail должен быть внутренним </p>
E-mail: <input id="email" name="email" type="text" size="20" /><br /> // поле ввода электронной почты
<input id="elem" name="button" type="submit" value="Проверить"/> // кнопка, вызывающая функцию проверки введенной электронной почты
</body>
</html>;
JS:
define( [ "qlik"], //автоматически сформированный код QS
function ( qlik) {
return {
support : {
snapshot: true,
export: true,
exportData : false
},
//автоматически сформированный код отображения на листе
paint: function ($element, layout) {
//вызов функции проверки почты по нажатию кнопки
elem.onclick = function() {
//регулярные выражения для поиска корпоративной почты сотрудника
var re = /^[A-Z0-9._%+-]+@.ru$/i;
//присвоение переменной введённых пользователем значений
var myMail = document.getElementById("email").value;
//проверка введённых пользователем значений через регулярные выражения (true/false)
var valid = re.test(myMail);
//формирование сообщения, если введен корректный адрес электронной почты
if (valid) output = "Адрес электронной почты почты введен ПРАВИЛЬНО!";
//формирование сообщения если введен некорректный адрес электронной почты
else output = "Адрес электронной почты введен неправильно!";
//вывод всплывающего сообщения на веб-страницы
alert(output);
return valid;
}
return qlik.Promise.resolve();
}
};
} );
1.5. Теперь рассмотрю, как работает визуализация. Выхожу из режима разработчика, возвращаюсь в приложение, захожу на Лист, нажимаю кнопку «Изменить лист», захожу в «Пользовательские объекты» (1), нахожу созданную визуализацию (2) и перетаскиваю на Лист:
Проверяю, как работает «маска» для ввода электронной почты. Для начала введу неверную электронную почту, например, **** или **** и нажму на кнопку «Проверить»:
В обоих случаях выводится сообщение о некорректно введенной почте:
Также ошибка будет выдаваться, если вводить совершенно другие данные (например – номер телефона и т.д.). Теперь для проверки введу реальную корпоративную почту сотрудника:
В результате вышло сообщение:
«Маска» для ввода электронной почты работает корректно, теперь приступаю ко второй части создания собственной визуализации в Qlik Sense.
2. Создание собственной визуализации. Передача данных в переменную Qlik Sense:
2.1. Для демонстрации возможностей передачи значений в переменную Qlik Sense я беру созданную визуализацию в п.1 и дорабатываю код JS:
JS:
//код из п. 1.4.1 до «функции» Paint остается неизменным
…
paint: //дополняем функцию Paint кодом ниже:
…
//асинхронная функция, изменяющая значение переменной на выбранное пользователем значение с изменением проекта
async function setVar(name,val){
let var_id='-';
await qlik.currApp().createGenericObject({ //подключение к API QS
"qInfo": {
"qType": "VariableList"//код свойств визуализации
},
qVariableListDef: {
qType: 'variable',
},
}).then((e) => {
//присваивание id выбранной пользователем переменной
var_id=e.layout.qVariableList.qItems.find((item)=>item.qName===name) ? e.layout.qVariableList.qItems.find((item)=>item.qName===name).qInfo.qId : '-';
})
//ниже код изменяющий значение переменной по найденной id выше
if(var_id!=='-') await app.global.session.rpc({
"handle": app.model.handle,
"method": "GetVariableById",
"params": {
"qId": var_id
}
}).then(function(resp){
app.global.session.rpc({
"handle": resp.result.qReturn.qHandle,
"method": "SetProperties",
"params": {
"qProp": {
"qInfo": {
"qId": var_id,
"qType": "variable"
},
"qMetaDef": {},
"qName": name,
"qComment": "",
"qNumberPresentation": {
"qType": "U",
"qnDec": 10,
"qUseThou": 0,
"qFmt": "",
"qDec": "",
"qThou": ""
},
"qIncludeInBookmark": false,
"qDefinition":val,
"tags": []
}
}
}).then(function(resp1){
})
})
}
if(props.variableName){
app.variable.getContent(props.variableName, (v) => {
document.querySelector(`#${ext_id}_variable_conteiner_value`).innerHTML=v.qContent.qString;
});
document.querySelector(`#${ext_id}_variable_conteiner_bt1`).addEventListener('click',(e)=>{e.stopPropagation();
//Изменение переменной с изменением проекта
setVar(props.variableName,document.querySelector(`#${ext_id}_variable_conteiner_value`).innerHTML);
})
}
return qlik.Promise.resolve();
2.2. Выхожу из режима разработчика, возвращаюсь в приложение, захожу на Лист, нажимаю на кнопку «Изменить лист», нахожу вкладку «Переменные»
и создаю новую переменную TestVariable, пока ей значение не присваиваю, т.е. переменная будет «пустая».
Далее для того, чтобы наша визуализация работала, захожу в свойства созданной визуализации и выбираю в Вид -> VariableName -> из выпадающего списка выбираю созданную переменную, значение которой мы хотим менять (TestVariable):
Выхожу из режима редактирования, нажав на кнопку «Изменение завершено».
Ввожу корректную электронную почту в поле ввода:
После нажатия кнопку «Проверить», захожу во вкладку с переменными и вижу, что наша переменная поменяла значение на введенную электронную почту сотрудника!
Все получилось, теперь давайте рассмотрим поближе на часть кода, который позволил расширить стандартные возможности QS:
define(["qlik","jquery", "css!./test.css"],
function(qlik, $,) {
'use strict';
var app = qlik.currApp();
…
app.variable.getContent(props.variableName, (v) => {document.querySelector(`#${ext_id}_variable_conteiner_value`).innerHTML=v.qContent.qString;
Расшифруем код:
var app = qlik.currApp(); <- это и есть «подключение» к API через визуализацию. Записываем ее в переменную
app.variable.getContent <- присваивание внутренним переменным QS значений (в нашем случае из html-элемента ввода текста)
Выводы:
Таким быстрым и не сложным способом можно расширять возможности Qlik Sense c помощью extensions, например, создавать «маску» для вводимых данных или управлять значениями переменных в QS. Овладев основами html, css и JavaScript, Вы сможете создавать практически любые визуализации под собственные задачи.
Успехов Вам!