<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>nebula.js extension - Qlik Sense - Обучение, учебник, онлайн курс</title>
	<atom:link href="https://qliksense.ivan-shamaev.ru/tag/nebula-js-extension/feed/" rel="self" type="application/rss+xml" />
	<link>https://qliksense.ivan-shamaev.ru/tag/nebula-js-extension/</link>
	<description>Qlik Sense на русском языке. Пошаговые уроки для изучения Клик Сенс</description>
	<lastBuildDate>Fri, 03 Jun 2022 14:39:04 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>

<image>
	<url>https://qliksense.ivan-shamaev.ru/wp-content/uploads/2018/07/QlikSense_ICON2-150x150.png</url>
	<title>nebula.js extension - Qlik Sense - Обучение, учебник, онлайн курс</title>
	<link>https://qliksense.ivan-shamaev.ru/tag/nebula-js-extension/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Создание Extension с помощью qlik nebula.js и D3.js &#8211; Tutorial</title>
		<link>https://qliksense.ivan-shamaev.ru/building-advanced-visualization-extension-nebula-js-d3-js/</link>
					<comments>https://qliksense.ivan-shamaev.ru/building-advanced-visualization-extension-nebula-js-d3-js/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Fri, 11 Feb 2022 21:12:38 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[nebula.js extension]]></category>
		<category><![CDATA[qlik nebula.js и D3.js - Tutorial]]></category>
		<category><![CDATA[Создание Extension nebula.js и D3.js]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2695</guid>

					<description><![CDATA[<p>Создание расширенного расширения визуализации с использованием Qlik Nebula.js и D3.js &#160; В моем последнем посте я рассказал о надежных возможностях API-интерфейсов Qlik Sense (QS) для создания готовых визуальных метафор и способах их интеграции в экосистему Qlik. Естественным выбором для разработчиков при создании расширений QS на протяжении многих лет был Extension API , в  основном использующий<a class="moretag" href="https://qliksense.ivan-shamaev.ru/building-advanced-visualization-extension-nebula-js-d3-js/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/building-advanced-visualization-extension-nebula-js-d3-js/">Создание Extension с помощью qlik nebula.js и D3.js &#8211; Tutorial</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Создание расширенного расширения визуализации с использованием Qlik Nebula.js и D3.js</h1>
<p><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="bed_4-1618230383486.png"><span class="lia-message-image-wrapper lia-message-image-actions-narrow lia-message-image-actions-below"><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_1.jpg"><img fetchpriority="high" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_1.jpg" alt="" width="1280" height="550" class="aligncenter size-full wp-image-2702" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_1.jpg 1280w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_1-300x129.jpg 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_1-1024x440.jpg 1024w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_1-768x330.jpg 768w" sizes="(max-width: 1280px) 100vw, 1280px" /></a></span></span></p>
<p>&nbsp;</p>
<p class="graf graf--p"><span>В моем последнем </span><a href="https://dipankar-tnt.medium.com/leveraging-the-power-of-qlik-sense-saas-extension-api-to-design-a-new-visualization-chart-d54194aaf07f" target="_blank" rel="noopener nofollow noreferrer"><span>посте</span></a><span> я рассказал о надежных возможностях API-интерфейсов Qlik Sense (QS) для создания готовых визуальных метафор и способах их интеграции в экосистему Qlik. Естественным выбором для разработчиков при создании расширений QS на протяжении многих лет был </span><a href="https://qlik.dev/apis/javascript/extensions" target="_blank" rel="noopener nofollow noreferrer"><span>Extension API</span></a><span> , в  основном использующий ванильный JavaScript, jQuery и AngularJS.</span></p>
<blockquote><p><em><span>API расширений состоит из методов и свойств, используемых для создания пользовательских расширений визуализации.</span></em></p></blockquote>
<p class="graf graf--p"><span>Введите… Решение Qlik Sense с открытым исходным кодом — <a href="https://qlik.dev/apis/javascript/nebulajs-stardust" target="_blank" rel="noopener nofollow noreferrer"><strong>Nebula.js</strong></a> !</span><a href="https://qlik.dev/apis/javascript/nebulajs-stardust" target="_blank" rel="noopener nofollow noreferrer"> <strong><span></span></strong></a><span></span></p>
<p><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="bed_0-1618228754457.png"><span class="lia-message-image-wrapper lia-message-image-actions-narrow lia-message-image-actions-below"><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_2.png"><img decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_2.png" alt="" width="1064" height="330" class="aligncenter size-full wp-image-2703" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_2.png 1064w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_2-300x93.png 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_2-1024x318.png 1024w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_2-768x238.png 768w" sizes="(max-width: 1064px) 100vw, 1064px" /></a></span></span></p>
<p>&nbsp;</p>
<p class="graf graf--p"><span>Nebula.js — это набор библиотек и API-интерфейсов JavaScript, не зависящих от продукта и платформы, которые помогают разработчикам интегрировать визуализации и гибридные приложения поверх Qlik Associative Engine в QS Desktop, QS Enterprise для Windows и SaaS-редакции Qlik Sense. Это руководство специально относится к </span><strong><span>выпуску QS SaaS. </span></strong><span>Nebula.js предлагает разработчикам альтернативу API возможностей, которые исторически использовались для создания гибридных приложений. В этом руководстве основное внимание будет уделено разработке новой визуализации на основе пользовательского сценария с использованием Nebula.js и сторонней библиотеки визуализации D3.js. Наша цель — понять, как мы можем использовать Nebula.js для создания объекта расширения QS и реализации готовых возможностей визуализации в рамках </span><strong><span>SaaS .</span></strong><span>Платформа. В этом руководстве не делается акцент на части программирования D3.js, но обсуждается мотивация визуализации.</span></p>
<p class="graf graf--p"><span style="font-size: large;"><strong><span>Сценарий пользователя.</span></strong><span> </span></span><em><span>У организации, использующей Qlik Sense, есть новое требование по разработке визуального представления для понимания многомерного многомерного набора данных для своей организации. Их набор данных состоит из числовых значений, и они хотят сравнить несколько объектов вместе, чтобы проанализировать отношения между ними. Основываясь на этих требованиях, их инженер по визуализации данных представляет им «график с параллельными координатами». </span></em></p>
<h3 id="toc-hId-1261881332"><strong><span>Итак, что такое график с параллельными координатами?</span></strong></h3>
<blockquote><p><em><span>Графики с параллельными координатами (PCP) доказали свою эффективность при эффективной визуализации многомерных наборов данных высокой размерности. В параллельных координатах каждый объект представлен в виде вертикальных полос, а значения нанесены на график в виде серии линий, соединенных по каждой оси. Их преимущество в том, что вертикальные полосы (функции) могут иметь собственный масштаб, поскольку каждая функция работает с разными единицами измерения. PCP дает представление о конкретных скрытых закономерностях в данных, таких как сходства, кластеры и т. д., и позволяет проводить более простой сравнительный анализ.</span></em></p></blockquote>
<h4 id="toc-hId-1952442806"><span style="font-size: medium;"><span>Основываясь на требованиях, давайте начнем с создания расширения QS с помощью </span><a href="https://github.com/qlik-oss/nebula.js" target="_blank" rel="noopener nofollow noreferrer"><span>Nebula.js</span></a><span> .</span></span></h4>
<p class="graf graf--p"><strong><span>Предпосылки</span></strong><span> :</span></p>
<ol>
<li><span>Node.js (версия 10 или новее)</span></li>
<li><span>Терминал (например, Git Bash в Windows или Terminal в Mac)</span></li>
<li><span>IDE на ваш выбор, например, VS Code.</span></li>
<li><span>Существующая </span><a href="https://qlik.dev/basics/authentication-options#web-integrations" target="_blank" rel="noopener nofollow noreferrer"><span>веб-интеграция</span></a><span> или возможность ее создания в вашем арендаторе (особенно это относится к выпуску QS SaaS).</span></li>
<li><span>Приложение Qlik Sense с данными.</span></li>
</ol>
<p class="graf graf--p"><u><strong><span>Шаг 1:</span></strong></u><span> Используйте интерфейс командной строки nebula.js для импорта необходимых пакетов. Команда помещает проект в папку /hello со следующей структурой:</span></p>
<ul>
<li><span>/src</span></li>
<li><span>index.js — основная точка входа этой визуализации</span></li>
<li><span>object-properties.js — свойства объекта, хранящиеся в приложении.</span></li>
<li><span>data.js — конфигурация данных</span></li>
<li><span>/test &#8211; Интеграционные тесты</span></li>
<li>package.json</li>
</ul>
<p class="graf graf--p"><strong><span>Команда</span></strong><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">npx @nebula.js/cli create hello --picasso none</pre>
<p class="graf graf--p"><u><strong><span>Шаг 2:</span></strong></u><span> Запустите сервер разработки, выполнив:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">cd hello
npm run start</pre>
<p class="graf graf--p"><span>Команда запускает локальный сервер разработки и открывает </span><a href="http://localhost:8080/" target="_blank" rel="noopener nofollow noreferrer"><span>http://localhost:8080</span></a><span> в вашем браузере. Преимущество наличия сервера разработки с Nebula.js заключается в том, что он предоставляет интерактивный способ тестирования и редактирования вашего расширения без необходимости итеративного развертывания в QS каждый раз, когда вносится новое изменение.</span></p>
<p class="graf graf--p"><u><strong><span>Шаг 3:</span></strong></u><span> Настройте структуру данных.</span></p>
<p class="graf graf--p"><span>Визуализации в QS основаны на определении гиперкуба (qHyperCubeDef). Следовательно, любой новый визуальный объект, который мы хотим добавить в экосистему QS, должен иметь определенную структуру данных. В Nebula.js у нас есть файл object-properties.js, который позволяет определить структуру нашего объекта.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">const properties = {
  showTitles: true,
  qHyperCubeDef: {
    qInitialDataFetch: [{ qWidth: 30, qHeight: 200 }],
  }
}</pre>
<p class="graf graf--p"><span>Нам также необходимо установить цель данных в файле data.js, чтобы мы ссылались на правильное определение гиперкуба (важно отметить, если у вас есть несколько объектов qHyperCubeDef).</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export default {
  targets: [
    {
      path:'/qHyperCubeDef',
    }
  ],
};</pre>
<p class="graf graf--p"><u><strong><span>Шаг 4:</span></strong></u><span> Разработка расширения визуализации с использованием Nebula.js и D3.js.</span></p>
<p class="graf graf--p"><strong><span>Специальный код QS Nebula.js:</span></strong></p>
<p class="graf graf--p"><span>Теперь, когда у нас все готово, мы начинаем разработку нашего расширения с пользовательским объектом визуализации, используя файл index.js из нашего проекта.</span></p>
<p class="graf graf--p"><span>Обратите внимание, что Nebula.js и его основной пакет @nebula.js/stardust построены на концепции настраиваемых </span><em><span>хуков</span></em><span> . Это может показаться знакомым людям, работающим с </span><a href="https://reactjs.org/" target="_blank" rel="noopener nofollow noreferrer"><span>React.js</span></a><span> . </span><em><span>Хуки</span></em><span> — это концепция, которая делает упор на повторно используемые составные функции, а не на классические объектно-ориентированные классы и наследование. Основные хуки, от которых мы зависим при разработке нашего объекта расширения, описаны ниже:</span></p>
<p><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="bed_1-1618229164557.png"><span class="lia-message-image-wrapper lia-message-image-actions-narrow lia-message-image-actions-below"></span></span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_3.png"><img decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_3.png" alt="" width="1600" height="363" class="aligncenter size-full wp-image-2704" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_3.png 1600w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_3-300x68.png 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_3-1024x232.png 1024w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_3-768x174.png 768w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_3-1536x348.png 1536w" sizes="(max-width: 1600px) 100vw, 1600px" /></a></p>
<p class="graf graf--p"><span>Метод, который помогает нам визуализировать наш объект визуализации, — это функция component(). Функция component() выполняется каждый раз, когда что-то, связанное с рендерингом объекта, изменяется, например, тема, модель данных, выборка данных, состояние компонента и т. д. Эту функцию можно сравнить с функцией paint() в Extension API.</span></p>
<p class="graf graf--p"><span>Чтобы отобразить наши данные, нам сначала нужно получить доступ к </span><em><span>макету</span></em><span> через хук useLayout, а затем использовать его в сочетании с хуком useEffect. qDataPages </span><strong><span>[0].qMatrix гиперкуба</span></strong><span> содержит все данные (измерения и меры), используемые в среде QS, и нам нужно будет передать эти данные в нашу визуализацию на основе D3.js.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">component() {
      const element = useElement();
      const layout = useLayout();
      useEffect(() =&gt; {
        var qMatrix = layout.qHyperCube.qDataPages[0].qMatrix;
      }
                }</pre>
<p class="graf graf--p"><span>Чтобы увидеть значения данных и понять структуру </span><em><span>qHyperCube</span></em><span> , всегда полезно выполнить </span><em><span>console.log(layout)</span></em><span> . Фрагмент показывает значения, характерные для нашего варианта использования. Каждый раз, когда к нашему объекту расширения добавляется новое измерение или мера, </span><strong><span>qDataPages[0].qMatrix</span></strong><span> обновляется этими значениями </span><strong><span>.</span></strong></p>
<p><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="bed_2-1618229293997.png"><span class="lia-message-image-wrapper lia-message-image-actions-narrow lia-message-image-actions-below"></span></span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_4.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_4.png" alt="" width="1070" height="538" class="aligncenter size-full wp-image-2705" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_4.png 1070w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_4-300x151.png 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_4-1024x515.png 1024w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js_4-768x386.png 768w" sizes="(max-width: 1070px) 100vw, 1070px" /></a></p>
<p class="graf graf--p"><span>Затем необходимые значения </span><em><span>измерения</span></em><span> для нашей диаграммы извлекаются из гиперкуба с использованием свойства </span><strong><span>qText</span></strong><span> из </span><strong><span>qDataPages[0].qMatrix,</span></strong><span> как показано ниже.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">var data = qMatrix.map(function (d) {
          return {
            PetalLength: d[0].qText,
            PetalWidth: d[1].qText,
            SepalLength: d[2].qText,
            SepalWidth: d[3].qText,
            Species: d[4].qText,
          };
        });</pre>
<p class="graf graf--p"><span>Наш следующий шаг — определить ширину и высоту объекта визуализации и зафиксировать его </span><em><span>идентификатор</span></em><span> . Мы будем использовать этот </span><em><span>идентификатор</span></em><span> для привязки его к нашему объекту </span><em><span>элемента</span></em><span> из хука useLayout, как показано ниже:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">var width = 1000;
var height = 400;
var id = "container_" + layout.qInfo.qId;
const elem_new = `&lt;div id=${id}&gt;&lt;/div&gt;`;
element.innerHTML = elem_new;</pre>
<p class="graf graf--p"><span>Наконец, мы вызываем функцию D3.js из хука useEffect.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">viz(data, width, height, id);</pre>
<p class="graf graf--p"><strong><span>Специальный код D3.js:</span></strong></p>
<p class="graf graf--p"><span>Функция viz() содержит весь наш код D3.js, который позволяет нам рисовать график в параллельных координатах. Во-первых, нам нужно добавить SVG к </span><em><span>&lt;div&gt;</span></em><span> , содержащему </span><em><span>идентификатор</span></em><span> нашего объекта QS, как показано ниже.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">var svg = d3
          .select("#" + id)
          .append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
          .append("g")
          .attr(
            "transform",
            "translate(" + margin.left + "," + margin.top + ")"
          );</pre>
<p class="graf graf--p"><span>Затем мы получаем все измерения, кроме </span><em><span>Species</span></em><span> , для построения наших осей x и y.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">var dimensions = Object.keys(data[0]).filter(function (d) {
          return d != "Species";
        });

        var y = {};
        for (var i in dimensions) {
          var name_new = dimensions[i];
          y[name_new] = d3.scaleLinear().domain([0, 8]).range([height, 0]);
        }

        var x = d3.scalePoint().range([0, width]).domain(dimensions);</pre>
<p class="graf graf--p"><span>Чтобы нарисовать линии для нашего графика с параллельными координатами, нам нужно построить функцию </span><em><span>пути , которая будет брать строку из нашего </span></em><span></span><em><span>qHyperCube</span></em><span> и возвращать координаты </span><em><span>x</span></em><span> и </span><em><span>y</span></em><span> линии.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">function path(d) {
          return d3.line()(
            dimensions.map(function (p) {
              return [x(p), y[p](d[p])];
            })
          );
        }</pre>
<p class="graf graf--p"><span>И, наконец, мы связываем все с нашим SVG, как показано ниже:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">svg
  .selectAll("myPath")
  .data(data)
  .enter()
  .append("path")
  .attr("class", function (d) {
    return "line " + d.Species;
  })
  .attr("d", path)
  .style("fill", "none")
  .style("stroke", function (d) {
    return color(d.Species);
  })
  .style("opacity", 0.5);</pre>
<p class="graf graf--p"><strong><u><span>Шаг 5:</span></u><span> Развертывание расширения.</span></strong></p>
<p class="graf graf--p"><span>Чтобы создать наш проект, мы используем приведенную ниже команду, чтобы сгенерировать все файлы, доступные для чтения QS, и поместить их в папку /hello-ext. Затем эту папку можно сжать (.zip) и загрузить в раздел </span><em><span>расширений</span></em><span> консоли SaaS для использования в среде QS.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">npm run sense</pre>
<h3 id="toc-hId-1941939702"><span>Dashboard:</span></h3>
<p><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="bed_3-1618229582498.gif"><span class="lia-message-image-wrapper lia-message-image-actions-narrow lia-message-image-actions-below"><img loading="lazy" decoding="async" src="https://community.qlik.com/t5/image/serverpage/image-id/52798iA7421A5218DE8F8B/image-size/large?v=v2&amp;px=999" role="button" title="Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js" alt="Building_an_advanced_Visualization_extension_using_Qlik_Nebulajs_D3js" li-image-url="https://community.qlik.com/t5/image/serverpage/image-id/52798iA7421A5218DE8F8B?v=v2" li-image-display-id="'52798iA7421A5218DE8F8B'" li-message-uid="'1798745'" li-messages-message-image="true" li-bindable="" class="lia-media-image aligncenter" li-bypass-lightbox-when-linked="true" li-use-hover-links="false" li-compiled="true" width="600" height="338" tabindex="0" /></span></span></p>
<p class="graf graf--p"><span>Если вы только начинаете работать с Nebula.js, </span><a href="https://qlik.dev/" target="_blank" rel="nofollow noopener noreferrer"><span>https://qlik.dev</span></a><span> — отличное место для ознакомления с основами и подробного изучения связанных функций.</span></p>
<p class="graf graf--p"><span>Исходный код этого проекта доступен по адресу: </span><a href="https://github.com/dipankarqlik/Nebula" target="_blank" rel="nofollow noopener noreferrer"><span>https://github.com/dipankarqlik/Nebula</span></a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/building-advanced-visualization-extension-nebula-js-d3-js/">Создание Extension с помощью qlik nebula.js и D3.js &#8211; Tutorial</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/building-advanced-visualization-extension-nebula-js-d3-js/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Создание Extensions с помощью nebula.js &#8211; пример Hello World</title>
		<link>https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/</link>
					<comments>https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Fri, 11 Feb 2022 20:33:07 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[Hello World - What is Nebula.js]]></category>
		<category><![CDATA[Hello World nebula.js extension]]></category>
		<category><![CDATA[Making Sense of Qlik APIs – Nebula CLI]]></category>
		<category><![CDATA[nebula.js]]></category>
		<category><![CDATA[nebula.js extension]]></category>
		<category><![CDATA[Qlik Sense Extension]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[What is Nebula.js]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2684</guid>

					<description><![CDATA[<p>В этом уроке мы создадим расширение HelloWorld, используя nebula.js и Qlik Sense Desktop Видео Hello World Extension &#8211; What is Nebula.js? Making Sense of Qlik APIs – Nebula CLI Создайем расширение HelloWorld, используя nebula.js В этом руководстве вы узнаете, как создать простое расширение, отображающее таблицу с использованием nebula.js. В статье будут<a class="moretag" href="https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/">Создание Extensions с помощью nebula.js &#8211; пример Hello World</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<blockquote><p>В этом уроке мы создадим расширение HelloWorld, используя nebula.js и Qlik Sense Desktop</p></blockquote>
<h1 data-testid="docs-header">Видео</h1>
<h2 data-testid="docs-header">Hello World Extension &#8211; What is Nebula.js?</h2>
<p><iframe title="Hello World - What is Nebula.js?" width="750" height="563" src="https://www.youtube.com/embed/MxQVuorsjVc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h2>Making Sense of Qlik APIs – Nebula CLI</h2>
<p><iframe title="Making Sense of Qlik APIs – Nebula CLI" width="750" height="563" src="https://www.youtube.com/embed/oF68t8DPpsE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h1 data-testid="docs-header" class=""><span>Создайем расширение HelloWorld, используя nebula.js</span></h1>
<p><span>В этом руководстве вы узнаете, как создать простое расширение, отображающее таблицу с использованием </span><code class="language-text">nebula.js</code><span>.</span></p>
<p><span>В статье будут пройдены следующие шаги:</span></p>
<ol>
<li><span>Создание проекта</span></li>
<li><span>Настройка структуры данных</span></li>
<li><span>Данные рендеринга</span></li>
<li><span>Выбор данных</span></li>
<li><span>Создание и загрузка расширения</span></li>
</ol>
<blockquote><p><strong><span>Примечание.</span></strong><span> Чтобы загрузить расширение в Qlik Sense SaaS, вам необходим доступ к тенанту Qlik Sense SaaS и либо права администратора тенанта, либо средства для получения ключа API, сгенерированного для вас. Вы можете </span><a href="https://www.qlik.com/us/trial/qlik-sense-business"><span>подписаться на бесплатную пробную версию</span></a><span> , если у вас нет существующего клиента.</span></p></blockquote>
<h2 id="requirements">Требования</h2>
<p><span>Этот учебник требует, чтобы у вас было следующее:</span></p>
<ul>
<li><a href="https://nodejs.org/en/download/"><span>Node.js</span></a><span> (версия 10 или новее)</span></li>
<li><span>Терминал (например , </span><a href="https://gitforwindows.org/"><span>Git Bash для Windows</span></a><span> или Terminal.app для Mac)</span></li>
<li><span>Современный веб-браузер, например Google Chrome</span></li>
<li><span>Текстовый редактор или IDE по вашему выбору, например Visual Studio Code.</span></li>
<li><span>Существующая </span><a href="https://qlik.dev/basics/authentication-options#web-integrations"><span>веб-интеграция</span></a><span> или возможность ее создания. Или клиент Qlik Sense Desktop.</span></li>
</ul>
<h2 id="create-a-project">Создание проекта</h2>
<p><span>Самый быстрый способ начать работу — использовать </span><code class="language-text">nebula.js</code> <span>интерфейс командной строки:</span></p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash" tabindex="0"><code class="language-bash">npx @nebula.js/cli create hello --picasso none</code></pre>
</div>
<p><span>Параметр </span><code class="language-text">--picasso none</code> <span>указывает команде не создавать шаблон визуализации Пикассо, другие параметры &#8211; </span><code class="language-text">minimal</code><span>и </span><code class="language-text">barchart</code><span>.</span></p>
<p><span>Команда формирует проект в папке </span><code class="language-text">/hello</code> <span>со следующей структурой:</span></p>
<ul>
<li><code class="language-text">/src</code>
<ul>
<li><code class="language-text">index.js</code> <span>&#8211; Основная точка входа этой визуализации</span></li>
<li><code class="language-text">object-properties.js</code> <span>&#8211; Свойства объекта, хранящиеся в приложении</span></li>
<li><code class="language-text">data.js</code> <span>&#8211; Конфигурация данных</span></li>
</ul>
</li>
<li><code class="language-text">/test</code> <span>&#8211; Интеграционные тесты</span></li>
<li><code class="language-text">package.json</code></li>
</ul>
<p><span>Папка содержит несколько дополнительных точечных файлов, обеспечивающих проверку и форматирование кода.</span></p>
<h3 id="start-the-development-server">Запуск сервера разработки</h3>
<p><span>Запустите сервер разработки с помощью команды:</span></p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash" tabindex="0"><code class="language-bash">cd hello<span></span>
npm run start</code></pre>
</div>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension.jpg"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension.jpg" alt="" class="aligncenter size-full wp-image-2771" width="1348" height="138" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension.jpg 1348w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension-300x31.jpg 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension-1024x105.jpg 1024w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension-768x79.jpg 768w" sizes="(max-width: 1348px) 100vw, 1348px" /></a></p>
<p><span>Команда запускает локальный сервер разработки и открывает </span><a href="http://localhost:8080/"><span>http://localhost:8080</span></a><span> в вашем браузере.</span></p>
<p><img decoding="async" src="https://qlik.dev/static/hub-connect-f5711011cb5bed761c101f5dce82214a.png" alt="Подключиться к движку" /></p>
<p><span>Сервер разработки должен подключаться к ассоциативному движку Qlik, работающему в любом развертывании Qlik. Введите URL-адрес WebSocket, соответствующий используемому вами продукту Qlik.</span></p>
<p><strong>Чтобы открыть WebSocket для движка, используйте один из следующих URI:</strong></p>
<ul>
<li><strong>Qlik Sense Enterprise:</strong> <code>wss://server.domain.com:4747/</code> или <code>wss://server.domain.com[/virtual proxy]/</code></li>
<li><strong>Qlik Sense Desktop:</strong> <code>ws://localhost:4848/</code></li>
</ul>
<p><span>Затем выберите приложение для подключения.</span></p>
<p><img decoding="async" src="https://qlik.dev/static/hub-app-275f908203b91a5417c556d5d3b50eeb.png" alt="Подключиться к приложению" /></p>
<p><span>Затем вы будете перенаправлены в основной пользовательский интерфейс разработчика, где сможете увидеть отрендеренную визуализацию:</span></p>
<p><img decoding="async" src="https://qlik.dev/static/hub-dev-21416471f69a21ff6e9ed3f07ac66810.png" alt="Сервер разработки" /></p>
<p><span>Любые обновления </span><code class="language-text">/src/index.js</code><span>, влияющие на вывод, автоматически вызывают обновление визуализации, и вы сразу же видите изменения.</span></p>
<h2 id="configure-data-structure">Настроить структуру данных</h2>
<p><span>Простое </span><code class="language-text">Hello</code><span>сообщение на самом деле не так уж полезно, пора добавить некоторые данные.</span></p>
<p><span>Добавьте </span><code class="language-text">qHyperCubeDef</code> <span>определение в </span><code class="language-text">object-properties.js</code><span>:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">const</span> properties <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">qHyperCubeDef</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">qInitialDataFetch</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">qWidth</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token literal-property property">qHeight</span><span class="token operator">:</span> <span class="token number">10</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>Затем добавьте </span><code class="language-text">/qHyperCubeDef</code> <span>в качестве цели данных в </span><code class="language-text">data.js</code><span>:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">targets</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">'/qHyperCubeDef'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>После этих изменений у вас должна появиться возможность добавлять данные на панели свойств справа:</span></p>
<p><img decoding="async" src="https://qlik.dev/static/tutorial-data-targets-f5fb58c59929b6886ccb25aeac35806b.png" alt="Цели данных" /></p>
<p><span>Добавьте измерение, нажав </span><strong><span>Add dimension</span></strong><span> и выбрав значение в появившемся меню. Затем проделайте то же самое с мерой &#8211; <strong>Add measures</strong>.</span></p>
<h2 id="render-data">Данные рендеринга</h2>
<p><span>Чтобы отобразить данные, вам сначала нужно получить к ним доступ через </span><code class="language-text">useLayout</code> <span>хук:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">import</span> <span class="token punctuation">{</span> useLayout<span class="token punctuation">,</span> useElement<span class="token punctuation">,</span> useEffect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@nebula.js/stardust'</span><span class="token punctuation">;</span><span></span>
<span></span>
<span class="token comment">// ...</span>
<span class="token function">component</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">useLayout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</div>
<p><span>Затем вы можете </span><code class="language-text">useLayout</code> <span>в сочетании с </span><code class="language-text">useEffect</code> <span>отображать заголовки и строки данных в </span><code class="language-text">qHyperCube</code><span>:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token function">component</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> element <span class="token operator">=</span> <span class="token function">useElement</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> layout <span class="token operator">=</span> <span class="token function">useLayout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span></span>
<span></span>
  <span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>layout<span class="token punctuation">.</span>qSelectionInfo<span class="token punctuation">.</span>qInSelections<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// skip rendering when in selection mode</span>
      <span class="token keyword">return</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">const</span> hc <span class="token operator">=</span> layout<span class="token punctuation">.</span>qHyperCube<span class="token punctuation">;</span><span></span>
<span></span>
    <span class="token comment">// headers</span>
    <span class="token keyword">const</span> columns <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>hc<span class="token punctuation">.</span>qDimensionInfo<span class="token punctuation">,</span> <span class="token operator">...</span>hc<span class="token punctuation">.</span>qMeasureInfo<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">f</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> f<span class="token punctuation">.</span>qFallbackTitle<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> header <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;thead&gt;&lt;tr&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>columns<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">c</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token template-punctuation string">`</span><span class="token string">&lt;th&gt;</span><span class="token interpolation-punctuation punctuation">${</span>c<span class="token interpolation-punctuation punctuation">}</span><span class="token string">&lt;/th&gt;</span><span class="token template-punctuation string">`</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/tr&gt;&lt;/thead&gt;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><span></span>
<span></span>
    <span class="token comment">// rows</span>
    <span class="token keyword">const</span> rows <span class="token operator">=</span> hc<span class="token punctuation">.</span>qDataPages<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>qMatrix
      <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">row</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;tr&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>row<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">cell</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token template-punctuation string">`</span><span class="token string">&lt;td&gt;</span><span class="token interpolation-punctuation punctuation">${</span>cell<span class="token punctuation">.</span>qText<span class="token interpolation-punctuation punctuation">}</span><span class="token string">&lt;/td&gt;</span><span class="token template-punctuation string">`</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/tr&gt;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span></span>
<span></span>
    <span class="token comment">// table</span>
    <span class="token keyword">const</span> table <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;table&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>header<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;tbody&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rows<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/tbody&gt;&lt;/table&gt;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><span></span>
<span></span>
    <span class="token comment">// output</span>
    element<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> table<span class="token punctuation">;</span><span></span>
<span></span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>element<span class="token punctuation">,</span> layout<span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
</div>
<h3>Выберите данные</h3>
<p><span>Перед выбором данных необходимо добавить метаданные в каждую строку, чтобы значения можно было идентифицировать для выбора:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token comment">// rows</span>
<span class="token keyword">const</span> rows <span class="token operator">=</span> hc<span class="token punctuation">.</span>qDataPages<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>qMatrix
  <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>
    <span class="token punctuation">(</span><span class="token parameter">row<span class="token punctuation">,</span> rowIdx</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;tr data-row="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rowIdx<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">"&gt;
        </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>row<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">cell</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token template-punctuation string">`</span><span class="token string">&lt;td&gt;</span><span class="token interpolation-punctuation punctuation">${</span>cell<span class="token punctuation">.</span>qText<span class="token interpolation-punctuation punctuation">}</span><span class="token string">&lt;/td&gt;</span><span class="token template-punctuation string">`</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">
      &lt;/tr&gt;</span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>Затем добавьте </span><code class="language-text">'click'</code><span>обработчик событий, </span><code class="language-text">element</code><span>который выполняет следующие действия:</span></p>
<ul>
<li><span>Проверяет, что выбранный элемент является </span><code class="language-text">td</code></li>
<li><span>Начинает выбор </span><code class="language-text">/qHyperCubeDef</code><span>, если он еще не активирован</span></li>
<li><span>Извлекает </span><code class="language-text">data-row</code> <span>индекс из</span> <code class="language-text">tr</code></li>
<li><span>Обновления </span><code class="language-text">selectedRows</code> <span>по клику</span> <code class="language-text">data-row</code></li>
</ul>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">const</span> element <span class="token operator">=</span> <span class="token function">useElement</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> selections <span class="token operator">=</span> <span class="token function">useSelections</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>selectedRows<span class="token punctuation">,</span> setSelectedRows<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span></span>
<span></span>
<span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token function-variable function">listener</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>tagName <span class="token operator">===</span> <span class="token string">'TD'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>selections<span class="token punctuation">.</span><span class="token function">isActive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        selections<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token string">'/qHyperCubeDef'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">const</span> row <span class="token operator">=</span> <span class="token operator">+</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>parentElement<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">'data-row'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token function">setSelectedRows</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">prev</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>prev<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>row<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> prev<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">v</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> v <span class="token operator">!==</span> row<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token operator">...</span>prev<span class="token punctuation">,</span> row<span class="token punctuation">]</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span><span></span>
<span></span>
  element<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> listener<span class="token punctuation">)</span><span class="token punctuation">;</span><span></span>
<span></span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    element<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> listener<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>element<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>Затем обновите стиль выбранных строк в таблице всякий раз, когда они изменяются:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>layout<span class="token punctuation">.</span>qSelectionInfo<span class="token punctuation">.</span>qInSelections<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// no need to update when not in selection mode</span>
    <span class="token keyword">return</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  element<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'tbody tr'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">tr</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> idx <span class="token operator">=</span> <span class="token operator">+</span>tr<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">'data-row'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    tr<span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> selectedRows<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>idx<span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token string">'#eee'</span> <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>element<span class="token punctuation">,</span> selectedRows<span class="token punctuation">,</span> layout<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>Наконец, примените выбранные значения через </span><code class="language-text">selections</code> <span>API:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>selections<span class="token punctuation">.</span><span class="token function">isActive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>selectedRows<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      selections<span class="token punctuation">.</span><span class="token function">select</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">method</span><span class="token operator">:</span> <span class="token string">'selectHyperCubeCells'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'/qHyperCubeDef'</span><span class="token punctuation">,</span> selectedRows<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      selections<span class="token punctuation">.</span><span class="token function">select</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">method</span><span class="token operator">:</span> <span class="token string">'resetMadeSelections'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>selectedRows<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">setSelectedRows</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>selections<span class="token punctuation">.</span><span class="token function">isActive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> selectedRows<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</div>
<h2 id="build-and-upload-extension">Создайте и загрузите расширение</h2>
<p><span>До сих пор вы работали в локальной изолированной среде над диаграммой, которая не зависела от какого-либо конкретного продукта Qlik.</span></p>
<p><span>Команда:</span></p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash" tabindex="0"><code class="language-bash">npm run build</code></pre>
</div>
<p><span>генерирует пакет в </span><code class="language-text">/dist</code> <span>папку, и это все, что вам нужно для распространения диаграммы в виде пакета npm.</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/npm_run_build_result.jpg"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/npm_run_build_result.jpg" alt="" class="aligncenter size-full wp-image-2773" width="619" height="167" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/npm_run_build_result.jpg 619w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/npm_run_build_result-300x81.jpg 300w" sizes="(max-width: 619px) 100vw, 619px" /></a></p>
<p><span>Однако Qlik Sense требует некоторых дополнительных файлов и немного другого формата для интерпретации диаграммы как расширения. Чтобы сгенерировать эти файлы, вы можете запустить команду:</span></p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash" tabindex="0"><code class="language-bash">npm run sense</code></pre>
</div>
<p><span>Команда создает все файлы в папку </span><code class="language-text">/hello-ext</code><span>, которую затем можно использовать в качестве расширения в Qlik Sense по вашему выбору.</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_npm_run_sense_result.jpg"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_npm_run_sense_result.jpg" alt="" class="aligncenter size-full wp-image-2774" width="622" height="169" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_npm_run_sense_result.jpg 622w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_npm_run_sense_result-300x82.jpg 300w" sizes="(max-width: 622px) 100vw, 622px" /></a></p>
<p><span>Чтобы загрузить расширение в клиент Qlik Sense SaaS, следуйте инструкциям по </span><a href="https://help.qlik.com/en-US/cloud-services/Subsystems/Hub/Content/Sense_Hub/Admin/mc-extensions.htm"><span>управлению расширениями</span></a><span>.</span></p>
<p><span style="color: #ff6600;"><strong>Важная и неочевидный шаг для использования собранного расширения из директории hello-ext:</strong> </span>Обязательно нужно удалить <strong>&#8220;-ext&#8221;</strong> из директории, иначе экстеншен не будет работать и появится приписка, что экстеншен не найден на сервере. Хотя в списке визуализаций в Qlik Sense он появится.</p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/">Создание Extensions с помощью nebula.js &#8211; пример Hello World</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
