Время прочтения: 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.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-код, который отвечает за визуальную составляющую.

  1. 4. При необходимости можно добавлять другие файлы необходимых форматов. Например, создам файл с расширением .html, для этого захожу в меню в верхнем левом углу, нажимаю «New file»:

В открывшемся окне прописываю название и нужное расширение (в моем случае .html):

После нажатия на кнопку «Create» в визуализации появился еще один файл.

Таким образом можно создавать множество разных файлов с разными форматами и даже подключать библиотеки!

  1. 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, Вы сможете создавать практически любые визуализации под собственные задачи.

Успехов Вам!