<?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>mashup - Qlik Sense - Обучение, учебник, онлайн курс</title>
	<atom:link href="https://qliksense.ivan-shamaev.ru/tag/mashup/feed/" rel="self" type="application/rss+xml" />
	<link>https://qliksense.ivan-shamaev.ru/tag/mashup/</link>
	<description>Qlik Sense на русском языке. Пошаговые уроки для изучения Клик Сенс</description>
	<lastBuildDate>Wed, 02 Dec 2020 20:04:56 +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>mashup - Qlik Sense - Обучение, учебник, онлайн курс</title>
	<link>https://qliksense.ivan-shamaev.ru/tag/mashup/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>nebula.js &#8211; Qlik Sense API Javascript библиотека. Примеры</title>
		<link>https://qliksense.ivan-shamaev.ru/nebula-js-qlik-sense-api-javascript-library-examples/</link>
					<comments>https://qliksense.ivan-shamaev.ru/nebula-js-qlik-sense-api-javascript-library-examples/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Wed, 25 Nov 2020 20:03:24 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[mashup]]></category>
		<category><![CDATA[nebula.js]]></category>
		<category><![CDATA[qlik api]]></category>
		<category><![CDATA[qlik sense]]></category>
		<category><![CDATA[qlik sense api]]></category>
		<category><![CDATA[Qlik Sense Mashup]]></category>
		<category><![CDATA[qliksense]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2440</guid>

					<description><![CDATA[<p>Введение в nebula.js nebula.js представляет собой набор библиотек JavaScript, визуализаций и интерфейсов командной строки, которые помогают разработчикам создавать и интегрировать визуализации поверх ассоциативного движка Qlik. Коллекция организована в @nebula.jsрамках области в виде пакетов npm. Основной пакет @nebula.js/stardustсодержит API-интерфейсы для интеграции существующих визуализаций с гибридными приложениями, а также API-интерфейсы для создания пользовательских визуализаций. EMBEDDING VISUALIZATIONS.<a class="moretag" href="https://qliksense.ivan-shamaev.ru/nebula-js-qlik-sense-api-javascript-library-examples/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/nebula-js-qlik-sense-api-javascript-library-examples/">nebula.js &#8211; Qlik Sense API Javascript библиотека. Примеры</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1 id="introduction-to-nebulajs"><span>Введение в nebula.js</span></h1>
<p><code class="language-text">nebula.js</code><span> представляет собой набор библиотек JavaScript, визуализаций и интерфейсов командной строки, которые помогают разработчикам создавать и интегрировать визуализации поверх ассоциативного движка Qlik.</span></p>
<p><span>Коллекция организована в </span><code class="language-text">@nebula.js</code><span>рамках области в виде пакетов npm. Основной пакет </span><code class="language-text">@nebula.js/stardust</code><span>содержит API-интерфейсы для интеграции существующих визуализаций с гибридными приложениями, а также API-интерфейсы для создания пользовательских визуализаций.</span></p>
<h1><strong>EMBEDDING VISUALIZATIONS. ВСТРАИВАНИЕ ВИЗУАЛИЗАЦИЙ</strong></h1>
<h2>Configuration. Конфигурация</h2>
<p><span>Когда вы создаете веб-сайт, будь то сайт всей компании или небольшой личный проект, у вас, скорее всего, есть свои собственные рекомендации по дизайну, шаблоны и требования UX, и вы захотите применить эти рекомендации к тому, что вы с ним интегрируете; диаграммы должны использовать ваши цветовые схемы, шрифты, языковой стандарт и уважать любые ограничения, которые могут быть у вас на интерактивность. Вы также можете контролировать, как загружаются диаграммы и темы, в зависимости от того, подключено ли ваше решение к сети или нет.</span></p>
<p><span>Вы можете управлять большинством из них через </span><code class="language-text">Configuration</code><span>объект.</span></p>
<h3 id="temporary-config">В<span>ременный конфиг</span></h3>
<p><span></span><code class="language-text">Configuration</code><span>Объект является необязательным аргументом , который вы можете предоставить при инстанцировании </span><code class="language-text">embed</code><span>экземпляра:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">import { embed } from '@nebula.js/stardust';

const n = embed(enigmaApp, {
  context: {
    theme: 'dark',
  },
  types: [
    /* types */
  ],
});

n.render(/* chart 1*/);
n.render(/* chart 2*/);</pre>
<h3 id="reusable-config"><span>Многоразовая конфигурация</span></h3>
<p><span>Если вы работаете с несколькими приложениями или хотите иметь несколько разных конфигураций, вам может быть проще сначала создать конфигурации, а затем повторно использовать их.</span></p>
<p><span>Создайте файл, </span><code class="language-text">baseConfig</code><span>который выполняет тяжелую работу по регистрации типов и тем:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">const baseConfig = embed.createConfiguration({
  types: [
    /* register type once*/
  ],
  themes: [
    /* register themes once*/
  ],
});</pre>
<p><span>Создайте другую конфигурацию, которая наследуется от </span><code class="language-text">baseConfig</code><span>, примените </span><code class="language-text">'dark'</code><span>тему и установите ограничение, запрещающее выбор:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">const noSelectionDark = baseConfig.createConfiguration({
  context: {
    theme: 'dark',
    constraints: { select: true },
  },
});

// render chart with dark theme with no selections allowed
noSelectionDark(enigmaApp).render(/*chart config*/);
noSelectionDark(anotherEnigmaApp).render(/*chart config*/);</pre>
<p><span>Вы также можете напрямую привязать конфигурацию к приложению:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">const swedishPink = baseConfig(enigmaApp, {
  context: {
    theme: 'pinkish',
    language: 'sv-SE',
  },
});

swedishPink.render(/* chart config */);</pre>
<h3 id="registering-types"><span>Регистрация типов</span></h3>
<p><span>Перед визуализацией визуализации ее модуль необходимо загрузить и зарегистрировать. Вы можете загрузить необходимые модули из npm:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">$npm install @nebula.js/sn-bar-chart @nebula.js/sn-pie-chart</pre>
<p><span>А потом зарегистрируйте каждого </span><code class="language-text">type</code><span>индивидуально:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import barchart from '@nebula.js/sn-bar-chart';
import piechart from '@nebula.js/sn-pie-chart';

embed.createConfiguration({
  types: [
    {
      name: 'bar',
      load: () =&gt; Promise.resolve(barchart),
    },
    {
      name: 'pie',
      load: () =&gt; Promise.resolve(piechart),
    },
  ],
});</pre>
<h3 id="loading-on-the-fly"><span>Загрузка на лету</span></h3>
<p><span>Если вы точно не знаете, какие типы вам нужны, и не хотите устанавливать все, чтобы уменьшить размер вашего пакета, вы можете загрузить визуализации во время выполнения, используя облегченный загрузчик определений асинхронных модулей, например </span><a href="https://github.com/d3/d3-require"><span>d3-require</span></a><span> .</span></p>
<p><span>Начнем с установки модуля:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">npm install d3-require</pre>
<p><span>а затем настройте его для загрузки модулей из CDN, например </span><code class="language-text">https://unpkg.com</code><span>, а также укажите псевдоним для использования локальной версии </span><code class="language-text">@nebula.js/stardust</code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">import { requireFrom } from 'd3-require';
import * as stardust from '@nebula.js/stardust';

const loadSnType = requireFrom((name) =&gt; `https://unpkg.com/@nebula.js/sn-${name}-chart`).alias({
  '@nebula.js/stardust': stardust,
});</pre>
<p><span>Затем вы можете настроить все типы, которые вы ожидаете использовать:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">const types = ['bar', 'line', 'pie', 'sankey'].map((t) =&gt; ({
  type: t,
  load: () =&gt; loadSnType(t),
}));
const baseConfig = stardust.embed.createConfiguration({ types });</pre>
<p><span>Тип загружается с удаленного URL-адреса при первом отображении:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">baseConfig(enigmaApp).render({
  type: 'bar',
  fields: ['Product', '=sum(Sales)'],
});</pre>
<h3 id="context"><span>Контекст</span></h3>
<p><span>При настройке конфигурации вы можете применить, </span><code class="language-text">context</code><span>который контролирует язык, тему и ограничения в каждой визуализации, которую вы визуализируете:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">embed.createConfiguration({
  context: {},
});</pre>
<h4 id="constraints"><span>Ограничения</span></h4>
<p><span>Ограничения позволяют указать визуализации на отключение определенных типов взаимодействий и поведения.</span></p>
<p><span>Вы можете применить три различных ограничения:</span></p>
<ul>
<li><code class="language-text">passive</code><span>: отключить такие взаимодействия, как всплывающие подсказки.</span></li>
<li><code class="language-text">active</code><span>: отключение взаимодействий, влияющих на состояние визуального представления, таких как масштабирование, прокрутка и т. д.</span></li>
<li><code class="language-text">select</code><span>: выключить выделение.</span></li>
</ul>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  context: {
    constraints: {
      active: true,
      passive: true,
      select: true,
    },
  },
};</pre>
<p><code class="language-text">stardust</code><span> никоим образом не навязывает эти ограничения, вместо этого разработчик визуализации должен соблюдать и реализовывать их.</span></p>
<h4 id="language"><span>Язык</span></h4>
<p><code class="language-text">stardust</code><span> поддерживает 15 языков:</span></p>
<ul>
<li><code class="language-text">'en-US'</code><span> &#8211; Американский английский</span></li>
<li><code class="language-text">'sv-SE'</code><span> &#8211; шведский</span></li>
<li><code class="language-text">'it-IT'</code><span> &#8211; итальянский</span></li>
<li><code class="language-text">'zh-CN'</code><span> &#8211; Упрощенный китайский</span></li>
<li><code class="language-text">'zh-TW'</code><span> &#8211; Традиционный китайский</span></li>
<li><code class="language-text">'ko-KR'</code><span> &#8211; Корейский язык</span></li>
<li><code class="language-text">'de-DE'</code><span> &#8211; Немецкий</span></li>
<li><code class="language-text">'es-ES'</code><span> &#8211; Испанский</span></li>
<li><code class="language-text">'pt-BR'</code><span> &#8211; Бразильский португальский</span></li>
<li><code class="language-text">'ja-JP'</code><span> &#8211; Японский</span></li>
<li><code class="language-text">'fr-FR'</code><span> &#8211; Французкий язык</span></li>
<li><code class="language-text">'nl-NL'</code><span> &#8211; Голландский</span></li>
<li><code class="language-text">'tr-TR'</code><span> &#8211; Турецкий</span></li>
<li><code class="language-text">'pl-PL'</code><span> &#8211; польский</span></li>
<li><code class="language-text">'ru-RU'</code><span> &#8211; Русский</span></li>
</ul>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  context: {
    language: 'sv-SE',
  },
};</pre>
<h4 id="theme"><span>Тема</span></h4>
<p><span>Из коробки доступны две основные темы: </span><code class="language-text">'light'</code><span>и </span><code class="language-text">'dark'</code><span>.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">{
  context: {
    theme: 'dark',
  }
};</pre>
<p><span>Светлая тема</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_light_nebulajs.png"><img fetchpriority="high" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_light_nebulajs.png" alt="" width="524" height="436" class="aligncenter size-full wp-image-2442" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_light_nebulajs.png 524w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_light_nebulajs-300x250.png 300w" sizes="(max-width: 524px) 100vw, 524px" /></a></p>
<p><span>Темная тема</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_dark_nebulajs.png"><img decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_dark_nebulajs.png" alt="" width="523" height="434" class="aligncenter size-full wp-image-2443" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_dark_nebulajs.png 523w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_dark_nebulajs-300x249.png 300w" sizes="(max-width: 523px) 100vw, 523px" /><span></span></a></p>
<p><span>Вы также можете зарегистрировать собственные темы и применить одну из них в контексте:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  themes: [{
    id: 'pinkish',
    load: () =&gt; Promise.resolve({
      palettes: {
        data: [{
          scale: [
            '#fac6e5',
            '#ff95d6',
            '#e76eb1',
            '#b44772',
          ],
        }]
      }
    })
  }],
  context: {
    theme: 'pinkish'
  }
};</pre>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_pinkish_nebula.png"><img decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_pinkish_nebula.png" alt="" width="500" height="359" class="aligncenter size-full wp-image-2445" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_pinkish_nebula.png 500w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/theme_pinkish_nebula-300x215.png 300w" sizes="(max-width: 500px) 100vw, 500px" /></a></p>
<h2>Embedding visualizations. Встраивание визуализаций</h2>
<h3 data-testid="docs-header"><span>Встраивание визуализаций</span></h3>
<p><span>Вы можете встроить визуализацию двумя способами:</span></p>
<ol>
<li><span>На лету</span></li>
<li><span>Из существующего объекта</span></li>
</ol>
<p><span>Рендеринг выполняется с использованием </span><code class="language-text">render()</code><span>метода экземпляра, возвращаемого </span><code class="language-text">embed</code><span>функцией, который, как минимум, требует того, в который </span><code class="language-text">HTMLElement</code><span>вы хотите выполнить рендеринг:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { embed } from '@nebula.js/stardust';

const n = embed(enigmaApp);
n.render({
  element,
  // rest of the config
});</pre>
<h3 id="render-on-the-fly"><span>Рендеринг на лету</span></h3>
<p><span>При рендеринге визуализации на лету вам необходимо указать, что </span><code class="language-text">type</code><span> вы хотите визуализировать:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">n.render({
  element,
  type: 'barchart',
});</pre>
<p><span>Некоторые визуализации предъявляют минимальные требования к различным свойствам и / или данным, которые необходимо отображать, и в этом случае вы можете увидеть что-то вроде этого:</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/supernova_incomplete_nebulajs.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/supernova_incomplete_nebulajs.png" alt="" width="747" height="489" class="aligncenter size-full wp-image-2447" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/supernova_incomplete_nebulajs.png 747w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/supernova_incomplete_nebulajs-300x196.png 300w" sizes="(max-width: 747px) 100vw, 747px" /></a></p>
<p><span>Чтобы предоставить визуализацию исходные данные, добавьте в </span><code class="language-text">fields</code><span>свойство измерения и меры данных :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">n.render({
  element,
  type: 'barchart',
  fields: ['Region', '=sum(Sales)'],
});</pre>
<p><span>Вы также можете изменить начальные свойства:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">n.render({
  element,
  type: 'barchart',
  fields: ['Product', '=sum(Sales)'],
  properties: {
    title: 'Sales by region',
  },
});</pre>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/barchart_nebula.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/barchart_nebula.png" alt="" width="773" height="529" class="aligncenter size-full wp-image-2448" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/barchart_nebula.png 773w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/barchart_nebula-300x205.png 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/barchart_nebula-768x526.png 768w" sizes="(max-width: 773px) 100vw, 773px" /></a></p>
<h2 id="render-from-existing-objects"><span>Рендеринг из существующих объектов</span></h2>
<p><span>Если вы уже создали общий объект в своем приложении и хотите его отобразить, вы можете сделать это, предоставив объекту </span><code class="language-text">id</code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">n.render({
  element,
  id: '&lt;ObjectID&gt;',
});</pre>
<h2>Current app selections. Выборки текущего приложения</h2>
<p><span>Важной частью Qlik является фильтрация данных с помощью выборок. Большинство диаграмм поддерживают выбор в данных, которые они отображают, которые затем отфильтровывают данные и влияют на другие диаграммы, подключенные к той же модели данных.</span></p>
<h3 id="current-app-selections-bar"><span>Панель выбора текущего приложения</span></h3>
<p><span>На панели выбора текущего приложения отображаются активные в данный момент выборки в указанном приложении. Для рендеринга этого бара вам сначала понадобится </span><code class="language-text">HTMLElement</code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">&lt;div class="curr-selections"&gt;&lt;/div&gt;</pre>
<p><span>Затем вы можете </span><code class="language-text">mount</code><span>выбрать пользовательский интерфейс в этом элементе:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">const n = embed(enigmaApp);

(await n.selections()).mount(document.querySelector('.curr-selections'));</pre>
<p><span>Без каких-либо выделений должно получиться так:</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/nebulajs_selectbar.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/nebulajs_selectbar.png" alt="" width="790" height="57" class="aligncenter size-full wp-image-2449" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/nebulajs_selectbar.png 790w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/nebulajs_selectbar-300x22.png 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/nebulajs_selectbar-768x55.png 768w" sizes="(max-width: 790px) 100vw, 790px" /></a></p>
<p><span>Когда вы начинаете применять выборки в различных диаграммах, пользовательский интерфейс обновляется, чтобы отразить текущее состояние:</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/selections_update.gif"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/selections_update.gif" alt="" width="792" height="520" class="aligncenter size-full wp-image-2450" /></a></p>
<h3 id="multiple-bars"><span>Несколько баров</span></h3>
<p><span>Если вы подключены к нескольким приложениям, вы можете отобразить текущий выбор в каждом из них, установив панель в разные элементы:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">(await embed(enigmaApp).selections()).mount(document.querySelector('.curr-selections'));

(await embed(anotherApp, { context: { theme: 'dark' } }).selections()).mount(
  document.querySelector('.another-curr-selections')
);</pre>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/selections_multiple_barchart_nebulajs.gif"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/selections_multiple_barchart_nebulajs.gif" alt="" width="1020" height="428" class="aligncenter size-full wp-image-2451" /></a></p>
<h1>DEVELOPING VISUALIZATIONS. РАЗРАБОТКА ВИЗУАЛИЗАЦИЙ</h1>
<h2>Visualization. Визуализация</h2>
<h3 id="whats-a-visualization"><span>Что такое визуализация</span></h3>
<p><span>Визуализация в контексте этого API представляет собой визуальный вывод некоторых базовых данных, хранящихся в ассоциативной модели данных Qlik. Это может быть почти все, что вы хотите, и оно традиционно разработано для отображения данных в форме диаграммы, таблицы, kpi и т. Д.</span></p>
<p><strong>Визуализация состоит из двух основных частей: </strong></p>
<ul>
<li><span>backend <em>Generic Object</em></span><span>, который описывает </span><em><span>свойства</span></em><span> этого визуализация и сохраняется в модели данных, </span></li>
<li><span>и внешний интерфейс визуальной части, которая производит рендеринг <em>layout</em>  </span><span>из <em>Generic Object</em></span><span>.</span></li>
</ul>
<h4 id="definition"><span>Определение</span></h4>
<p><span>Минимальная визуализация, которая не содержит никаких данных и ничего не отображает, выглядит так:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export default function () {
  return {
    qae: {
      /* */
    },
    component() {},
  };
}</pre>
<p><span>Здесь </span><code class="language-text">component()</code><span>вы визуализируете визуальную часть, а </span><code class="language-text">qae</code><span>здесь вы определяете свойства и данные, обрабатываемые ассоциативным механизмом Qlik (QAE).</span></p>
<h2>Rendering. Рендеринг</h2>
<p><span>В </span><code class="language-text">component</code><span>части определения происходит весь рендеринг, это просто функция, которая ничего не возвращает:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export default function () {
  return {
    component() {
      // rendering logic goes here
    },
  };
}</pre>
<p><span>Чтобы отрендерить что-то, что вам нужно для доступа к элементу DOM, которому назначена визуализация, вы можете сделать это, импортировав </span><code class="language-text">useElement</code><span> функцию:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useElement } from '@nebula.js/stardust';</pre>
<p><span>Эта функция возвращает простой HTMLElement, который является вашей точкой входа в визуальный мир:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">component() {
  const element = useElement();
  element.innerHTML = 'Hello!';
}</pre>
<p><code class="language-text">useElement</code><span>&#8211; это одна из многих функций, которые удовлетворяют наиболее распространенные требования при разработке визуализации, они позволяют </span><em><span>подключаться</span></em><span> к ресурсам, предоставляемым обеими </span><code class="language-text">stardust</code><span>сторонами и ассоциативным движком Qlik.</span></p>
<h3 id="hooks">Hooks</h3>
<p><span>Если вы работали с </span><a href="https://reactjs.org/"><span>React,</span></a><span> вы могли узнать это как </span><em><span>хуки</span></em><span> . Хуки &#8211; это концепция, в которой упор делается на многократно используемые составные функции, а не на классические объектно-ориентированные классы и наследование. Хотя реализация полностью настраивается с использованием настраиваемых хуков, концепция и правила очень похожи, настолько, что вы можете прочитать </span><a href="https://reactjs.org/docs/hooks-intro.html"><span>документацию</span></a><span> по <a href="https://reactjs.org/docs/hooks-intro.html">крючкам React,</a> чтобы понять, как использовать собственные хуки stardust.</span></p>
<h4 id="useelement">useElement</h4>
<p><span>Вы уже видели </span><code class="language-text">useElement</code><span>крючок, его единственная цель &#8211; предоставить HTMLElement, к которому вы должны прикрепить свои собственные элементы, чтобы сделать ваш контент видимым, в следующем примере для элемента </span><code class="language-text">innerHTML</code><span>установлено значение </span><code class="language-text">Hello!</code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">component() {
  // get the element
  const element = useElement();
  // set element content
  element.innerHTML = 'Hello!';
}</pre>
<p><span>Однако статическая строка не даст многого, в большинстве случаев вы обновляете контент на основе ввода данных, состояния компонентов и взаимодействия с пользователем.</span></p>
<p><span></span><code class="language-text">component()</code><span>Функция выполняется каждый раз , когда что &#8211; то , что может быть связано с вашими изменениями рендеринга; тема, модель данных, выбор данных, состояние компонента и т. д. Таким образом, добавление и удаление прослушивателей событий, обновление узлов DOM и выборка данных не идеальны и могут быть довольно тяжелыми для производительности, если делать это каждый раз при </span><code class="language-text">component()</code><span>запуске. Вместо этого вы должны выполнять пакетные обновления с </span><code class="language-text">useEffect</code><span>.</span></p>
<h4 id="useeffect"><span>useEffect</span></h4>
<p><code class="language-text">useEffect</code><span>&#8211; это ловушка, которая принимает функцию обратного вызова, которая запускается только при изменении указанного вами значения. Это позволяет не только выполнять пакетные обновления, но и реализовывать собственную форму управления жизненным циклом в вашем компоненте.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useEffect } from '@nebula.js/stardust';
// ...
component() {
  const element = useElement();

  useEffect(() =&gt; {
    // run only once when the component is created
    console.log('created');
  }, []);
}</pre>
<p><span>Добавление слушателей событий к элементу обычно выполняется только при запуске компонента, а затем удаляется при его уничтожении:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">component() {
  const element = useElement();

  useEffect(() =&gt; {
    const listener = () =&gt; {
      console.log('clicked');
    };

    element.addEventListener('click', listener);

    return () =&gt; {
      // clean-up
      element.removeEventListener('click', listener);
    };
  }, [element]);
}</pre>
<p><span>В предыдущем примере </span><code class="language-text">element</code><span>в качестве второго аргумента предоставляется наблюдаемое значение, поэтому эффект запускается только при </span><code class="language-text">element</code><span>изменении. Однако, поскольку </span><code class="language-text">element</code><span>никогда не изменяется для одного и того же компонента, обратный вызов запускается только один раз при создании компонента. Таким образом </span><code class="language-text">listener</code><span>, экземпляр может быть создан только один раз, и </span><code class="language-text">click</code><span>добавляется только один прослушиватель событий. Обратный вызов также возвращает функцию в конце, это функция очистки, которая выполняется при изменении любого из наблюдаемых значений или при уничтожении компонента. Здесь вы должны очистить все добавленные побочные эффекты, в этом случае прослушиватель событий удаляется, чтобы избежать утечки памяти.</span></p>
<h4 id="usestate"><span>useState</span></h4>
<p><span>Поскольку </span><code class="language-text">component()</code><span>это функция, а не экземпляр класса или объекта, вы не можете использовать его </span><code class="language-text">this</code><span>для хранения значений экземпляра, как в противном случае. Способ хранения состояния </span><code class="language-text">useState</code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useState } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const [count, setCount] = useState(0);
    },
  };
}</pre>
<p><code class="language-text">useState</code><span>возвращает кортеж, в котором первый элемент совпадает с начальным значением, указанным в качестве аргумента </span><code class="language-text">useState</code><span>, а второй элемент является функцией установки, с помощью которой вы можете изменить значение.</span></p>
<p><span>В следующем примере </span><code class="language-text">count</code><span>увеличивается на 1, когда пользователь нажимает </span><code class="language-text">element</code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">component() {
  const element = useElement();
  const [count, setCount] = useState(0);

  useEffect(() =&gt; {
    const listener = () =&gt; {
      setCount(count + 1);
    };

    element.addEventListener('click', listener);

    return () =&gt; {
      element.removeEventListener('click', listener);
    };
  }, [element]);
}</pre>
<p><span>Чтобы отобразить обновленное значение, вы можете добавить другое, </span><code class="language-text">useEffect</code><span>которое будет запускаться при </span><code class="language-text">count</code><span>изменении:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">const [count, setCount] = useState(0);
useEffect(() =&gt; {
  element.innerHTML = `Count: ${count}`;
}, [count]);</pre>
<h2>Configuring data. Конфигурирование данных</h2>
<p><span>В </span><code class="language-text">qae</code><span>разделе определения вы определяете свойства универсального объекта и форму данных, которые вы ожидаете использовать.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  "qae": {
    "properties": {}
  }
}</pre>
<h3 id="generic-object"><span>Общий объект</span></h3>
<p><span>Каждая визуализация связана со всей моделью данных и ассоциативным механизмом Qlik через </span><em><span>универсальный объект</span></em><span> . Это объект JSON, содержащий </span><em><span>свойства, в</span></em><span> результате которых создается </span><em><span>макет</span></em><span> , описывающий состояние внутренней части визуализации.</span></p>
<p><span>Каждый раз, когда кто-то хочет визуализировать вашу визуализацию, в модели данных создается экземпляр универсального объекта. Если у создателя есть необходимые разрешения, он может сохранить и сохранить этот объект в своей модели данных.</span></p>
<h3 id="properties"><span>Свойства</span></h3>
<p><span>Какие свойства вы устанавливаете, полностью зависит от вас, однако это должен быть действительный объект JSON. Большинство свойств &#8211; это просто настройки, которые вы, возможно, захотите сохранить с течением времени. Если вы разрабатываете гистограмму, вы можете сохранить настройку, которая указывает, следует ли ее складывать или какой цвет должны иметь столбцы:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  "isStacked": true,
  "barColor": "red"
}</pre>
<p><span>Эти свойства </span><em><span>статичны</span></em><span> , то, что входит, выходит точно так же. Истинная сила универсального объекта &#8211; это </span><em><span>динамические</span></em><span> свойства, которые вы можете установить, что позволяет вам использовать ассоциативный механизм Qlik и получать доступ к данным внутри него.</span></p>
<p><span>Динамические свойства имеют особую структуру, которая позволяет серверной части различать динамические и статические свойства. У них также есть соглашение об именах: все они начинаются с </span><code class="language-text">q</code><span>буквы, за которой следует заглавная буква, что позволяет людям и машинам легко различать два типа свойств.</span></p>
<p><span>Существует множество различных </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas"><span>предопределенных</span></a><span> динамических свойств для различных целей, например, вы можете использовать </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FValueExpression"><span>ValueExpression</span></a><span> для выполнения простых вычислений:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  "simpleMath": {
    "qValueExpression": {
      "qExpr": "1+1"
    }
  }
}</pre>
<h4 id="layout">Layout (Макет/Слой)</h4>
<p><span><em>layout </em>из Generic Object является результатом статических и динамических свойств. layout предыдущих свойств выглядит следующим образом:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  "isStacked": true,
  "barColor": "red",
  "simpleMath": 2
}</pre>
<p><span>Обратите внимание, что статические свойства остаются точно такими же, в то время как динамическое свойство </span><code class=" language-text">simpleMath</code><span>теперь содержит вычисленный результат ValueExpression.</span></p>
<p><span>Большинство динамических свойств имеют определение ввода и соответствующий вывод макета; а </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FListObjectDef"><span>ListObjectDef</span></a><span> приводит к </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FListObject"><span>ListObject</span></a><span> , а </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FSelectionObjectDef"><span>SelectionObjectDef</span></a><span> результаты в </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FSelectionObject"><span>SelectionObject</span></a><span> , и так далее.</span></p>
<h3 id="data"><span>Данные</span></h3>
<p><span>Наиболее часто используемым определением свойства является </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FHyperCubeDef"><span>HyperCubeDef</span></a><span> , это динамическое свойство, которое предоставляет вам данные из внутренней модели данных. Вы можете разместить это в корне объекта свойств или на более глубоком уровне, и у вас может быть столько, сколько вам нужно:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  "qHyperCubeDef": {},
  "anotherOne": {
    "qHyperCubeDef": {},
    "andAThird": {
      "qHyperCubeDef": {}
    }
  }
}</pre>
<p><span>Основными входными данными HyperCubeDef являются </span><em><span>измерения</span></em><span> и </span><em><span>меры</span></em><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  "qHyperCubeDef": {
    "qDimensions": [{ "qLibraryId": "hdg534" }],
    "qMeasures": [{ "qLibraryId": "gt5dgd" }]
  }
}</pre>
<p><span>В этом случае измерения и меры жестко запрограммированы на предопределенное значение, которое может существовать в определенной модели данных, что редко бывает тем, что вам нужно. Если вы разрабатываете диаграмму для использования другими с какой-либо моделью данных, которая вам нужна, чтобы можно было добавлять их динамически, вы можете сделать это, указав </span><em><span>целевые объекты данных</span></em><span> .</span></p>
<h4 id="data-targets"><span>Цели данных</span></h4>
<p><span>Целевой объект данных &#8211; это способ определить, где расположены динамические HyperCubeDef в свойствах универсального объекта. Хотя вы </span><code class=" language-text">stardust</code><span>можете просматривать свойства и находить все их использования </span><code class=" language-text">qHyperCubeDef</code><span>, вы можете не захотеть, чтобы все они были динамическими, или вы можете сгенерировать их только для внутреннего использования.</span></p>
<p><span>Вы указываете целевые объекты данных с помощью </span><code class=" language-text">data.targets</code><span>ключа </span><code class=" language-text">qae</code><span>, каждая цель должна иметь </span><code class=" language-text">path</code><span>ключ, который указывает путь JSON к HyperCubeDef из корня объекта свойств:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">qae: {
  properties: {
    qHyperCubeDef: {},
    my: {
      nested: {
        qHyperCubeDef: {}
      },
    }
  },
  data: {
    targets: [
      { path: '/qHyperCubeDef' },
      { path: '/my/nested/qHyperCubeDef' },
    ];
  }
}</pre>
<p><span>Вы можете для каждого целевого объекта данных указать дополнительные сведения, такие как максимальное / минимальное количество измерений и мер, и внести изменения при их добавлении.</span></p>
<p><span>Это полезно, когда вы знаете ограничения того, что может отображать диаграмма. Например, круговая диаграмма в основном используется, когда у нее есть ровно одно измерение и одна мера, но вы также можете реализовать поддержку второй меры. Это также избавляет вас от некоторой логики кода, поскольку </span><code class=" language-text">stardust</code><span>не пытается отобразить диаграмму, ограничения которой не были выполнены, а вместо этого показывает, что некоторые поля отсутствуют.</span></p>
<h4 id="field-limitations">Field limitations. <span>Ограничения поля</span></h4>
<p><span>Чтобы указать ограничения для измерений или показателей, добавьте каждый соответствующий тип поля как объект как часть целевого объекта данных:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">targets: [
  {
    path: '/qHyperCubeDef',
    dimensions: {
      min: 1,
      max: 1,
    },
    measures: {
      min: 1,
      max: 2,
    },
  },
];</pre>
<h3 id="field-modifications">Field modifications</h3>
<p><span>Вы также можете изменить добавленное или удаленное поле непосредственно перед тем, как изменение будет применено и отправлено на серверную часть, это полезно для таких вещей, как настройка сортировки при добавлении измерения или добавление дополнительных свойств, которые, как вы знаете, всегда необходимы.</span></p>
<p><span>Если вы, например, хотите убедиться, что нулевые значения подавляются, поскольку это не то, что вы можете визуализировать или представить в хорошем виде, вы можете установить, </span><code class=" language-text">qNullSuppression: true</code><span>когда добавляется измерение:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">dimensions: {
  added(dimension) {
    dimension.qNullSuppression = true;
  }
}</pre>
<h2>Consuming data. Потребление данных</h2>
<h3 id="access-layout">Access layout</h3>
<p><span>Вы можете получить доступ к <em>layout</em> Generic Object</span><span> через набор предопределенных hooks.</span></p>
<h4 id="uselayout">useLayout</h4>
<p><code class="language-text">useLayout</code><span> возвращает </span>evaluated layout свойств Generic Object:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useLayout } from '@nebula.js/stardust';

export default function () {
  return {
    qae: {
      properties: {
        qHyperCubeDef: {},
        simpleMath: {
          qValueExpression: {
            qExpr: '1+1',
          },
        },
      },
    },
    component() {
      const layout = useLayout();
      console.log(layout); // { qHyperCube: {/* HyperCube Layout */}, simpleMath: 2 }
    },
  };
}</pre>
<p><span>Вы должны </span><code class="language-text">useEffect</code><span>при наблюдении изменений на </span><code class="language-text">layout</code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">const layout = useLayout();

useEffect(() =&gt; {
  // do some heavy update
}, [layout]);</pre>
<h4 id="useapplayout">useAppLayout</h4>
<p><code class="language-text">useAppLayout</code><span>возвращает </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FNxAppLayout"><span>NxAppLayout,</span></a><span> к <a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FNxAppLayout">которому</a> вы в данный момент подключены:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useAppLayout } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const appLayout = useAppLayout();
      console.log(appLayout); // { qTitle: 'App title', qLocaleInfo: {/* */ } }
    },
  };
}</pre>
<p><span>Наиболее распространенный вариант использования макета приложения &#8211; это доступ, </span><code class="language-text">qLocaleInfo</code><span>который содержит сведения о локали, выбранные владельцем приложения и должен использоваться для форматирования чисел.</span></p>
<h3 id="models">Models. <span>Модели</span></h3>
<p><span>Помимо макетов приложения и универсального объекта, у вас есть полный доступ к API, созданным с помощью </span><code class="language-text">enigma.js</code><span>. Эти API-интерфейсы генерируются из схемы JSON-RPC и раскрывают всю мощь Associate Engine Qlik.</span></p>
<h4 id="usemodel"><span>useModel</span></h4>
<p><code class="language-text">useModel</code><span>возвращает сгенерированный API </span><a href="https://qlik.dev/apis/json-rpc/qix/genericobject#%23%2Fentries%2FGenericObject"><span>Generic Object</span></a><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useModel } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const model = useModel();
      model.getInfo().then((info) =&gt; {
        console.log(info);
      });
    },
  };
}</pre>
<p><span>Общие операции в этом API:</span></p>
<ul>
<li><span>делать выбор с помощью </span><code class="language-text">beginSelections</code><span>,  </span><code class="language-text">selectHyperCubeValues</code> и <code class="language-text">endSelections</code></li>
<li><span>получить больше данных с </span><code class="language-text">getHyperCubeData</code></li>
</ul>
<h4 id="useapp"><span>useApp</span></h4>
<p><code class="language-text">useApp</code><span>возвращает сгенерированный API <a href="https://qlik.dev/apis/json-rpc/qix/doc#%23%2Fentries%2FDoc">Doc</a>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useApp } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const app = useApp();
      app.clearAll();
    },
  };
}</pre>
<p><span>Общие операции в этом API:</span></p>
<ul>
<li><span>изменять стек выбора с </span><code class="language-text">clearAll</code><span>,  </span><code class="language-text">back</code><span>,</span><code class="language-text">forward</code></li>
<li><span>создавать и применять закладки с помощью </span><code class="language-text">createBookmark</code> и <code class="language-text">applyBookmark</code></li>
</ul>
<h3 id="useglobal"><span>useGlobal</span></h3>
<p><code class="language-text">useGlobal</code><span>возвращает сгенерированный API </span><a href="https://qlik.dev/apis/json-rpc/qix/global#%23%2Fentries%2FGlobal"><span>Global</span></a><span> :</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useGlobal } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const g = useGlobal();
      g.engineVersion().then((v) =&gt; {
        console.log(v);
      });
    },
  };
}</pre>
<p><span>Общие операции в этом API:</span></p>
<ul>
<li><span>получить список приложений с </span><code class="language-text">getDocList</code></li>
</ul>
<h2>HyperCube introduction. Введение в HyperCube</h2>
<p><span>Это </span><code class="language-text">HyperCubeDef</code><span>фундаментальная структура, которую вы настраиваете, прежде чем вам будет предоставлен результат в виде файла </span><code class="language-text">HyperCube</code><span>. Не позволяйте имени пугать вас, хотя оно содержит множество свойств и может быть настроено разными способами, в своей основной форме оно напоминает простую таблицу со строками и столбцами.</span></p>
<h3 id="hypercubedef-configuration"><span>Конфигурация HyperCubeDef</span></h3>
<p><span>Не все свойства одинаково важны, и есть несколько ключевых, о которых нужно помнить при настройке </span><code class="language-text">HyperCubeDef</code><span>.</span></p>
<h4 id="qmode"><span>qMode</span></h4>
<p><span>Хотя вам может не потребоваться </span><code class="language-text">qMode</code><span>явно устанавливать, поскольку по умолчанию используется простейший режим </span><code class="language-text">'S'</code><span>, важно знать, какое влияние он оказывает на структуру данных.</span></p>
<p><code class="language-text">qMode: 'P'</code><span>, или </span><em><span>режим</span></em><span> сводной таблицы, дает вам структуру, подходящую для представления сводных таблиц с группами как в вертикальном, так и в горизонтальном направлениях, а также группы для всех показателей.</span></p>
<p><code class="language-text">qMode: 'T'</code><span>, или </span><em><span>древовидный режим</span></em><span> , дает вам структуру, напоминающую дерево и подходящую для визуализации древовидных визуализаций; древовидная карта, упаковка кругов, солнечные лучи, дендрограмма, решётка и т. д.</span></p>
<p><code class="language-text">qMode: 'S'</code><span>, или </span><em><span>прямой режим</span></em><span> , является самым простым из них и дает вам структуру данных, которая выглядит как простая таблица со строками и столбцами. Для простоты объяснения остальной части гиперкуба можно предположить, что он используется.</span></p>
<h4 id="qdimensions-and-qmeasures"><span>qDimensions и qMeasures</span></h4>
<p><code class="language-text">qDimensions</code><span>и </span><code class="language-text">qMeasures</code><span>являются столбцами вашей «таблицы», нет явного ограничения на их количество, которое вы можете добавить, но часто существует ограничение на количество измерений и мер, которые может обрабатывать определенная диаграмма, и вам нужно сохранить это количество из них в виду, когда вы укажете </span><code class="language-text">qInitialDataFetch</code><span>.</span></p>
<h4 id="qinitialdatafetch"><span>qInitialDataFetch</span></h4>
<p><span>Ассоциативный движок Qlik &#8211; это решение на основе памяти, что означает, что объем данных, которые он может обрабатывать, полностью зависит от ресурсов памяти, к которым у него есть доступ. Таким образом, он может содержать миллиарды значений данных, и поэтому количество строк в гиперкубе также потенциально может достигать миллиардов.</span></p>
<p><span>Чтобы избежать случаев, когда такие огромные объемы данных передаются в интерфейсную часть, гиперкуб по умолчанию вообще не включает никаких строк. Чтобы контролировать это, вы можете установить количество строк и столбцов, которое вы хотите изначально </span><code class="language-text">qInitialDataFetch</code><span>. Это свойство позволяет вам установить </span><em><span>страницы данных, которые</span></em><span> вы хотите извлечь из всего гиперкуба, поэтому вы можете, например, выбрать получение первых 50 строк:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">qHyperCubeDef: {
  qInitialDataFetch: [{ qLeft: 0, qTop: 0, qHeight: 50, qWidth: 4 }];
}</pre>
<p><span>Если вы думаете о прямой таблице как о сетке, из которой вы хотите извлечь некоторые данные, тогда </span><code class="language-text">qLeft</code><span>и </span><code class="language-text">qTop</code><span>&#8211; это верхний левый угол подмножества, которое вы хотите извлечь, а </span><code class="language-text">qHeight</code><span>и </span><code class="language-text">qWidth</code><span>&#8211; количество строк и столбцов.</span></p>
<p><span>Однако существует максимальный предел в 10 000 ячеек, которые вы можете извлечь за один раз, и это количество вызывает ошибку. Поэтому вам нужно следить за количеством столбцов может потребоваться для обеспечения общей не превышает 10 000. Если вы, например , знаете , что вы никогда не нужно больше , чем 4 колонки, то вы можете установить </span><code class="language-text">qHeight</code><span>на </span><code class="language-text">10000/4</code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">qInitialDataFetch: [{ qLeft: 0, qTop: 0, qHeight: 2500, qWidth: 4 }];</pre>
<p><span>Первоначальная выборка данных указывает только самую большую возможную часть всего гиперкуба в макете, если в гиперкубе всего 7 строк, вы не получите больше 7. Вы также можете динамически получать больше данных позже.</span></p>
<h3 id="consuming-the-hypercube"><span>Потребление HyperCube</span></h3>
<p><span>Выход, или </span><em><span>компоновка</span></em><span> , из </span><code class=" language-text">HyperCubeDef</code><span>является </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FHyperCube"><span>гиперкубом</span></a><span> . В макете он расположен в том же месте, что и вы определили в своих свойствах, но без </span><code class=" language-text">Def</code><span>, например ввода:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  properties: {
    qHyperCubeDef: {},
    another: {
      one: {
        qHyperCubeDef: {}
      }
    }
  }
}</pre>
<p><span>приводит к выводу:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
  layout: {
    qHyperCube: {},
    another: {
      one: {
        qHyperCube: {}
      }
    }
  }
}</pre>
<p><span>Рядом с </span><code class=" language-text">qDimensionInfo</code><span>и </span><code class=" language-text">qMeasureInfo</code><span>свойствами , которые содержат ваши размеры и меры, наиболее важную часть гиперкуба являются </span><em><span>страницы данных</span></em><span> .</span></p>
<h4 id="data-pages"><span>Страницы данных</span></h4>
<p><span>На страницах данных содержатся фактические значения данных гиперкуба, где именно и какая структура они имеют, зависит от </span><code class=" language-text">qMode</code><span>значения, которое вы установили ранее. Для режима </span><code class=" language-text">'S'</code><span>это место </span><code class=" language-text">qDataPages</code><span>, которое, в свою очередь, содержит </span><code class=" language-text">qArea</code><span>и </span><code class=" language-text">qMatrix</code><span>.</span></p>
<p><span>Предполагая, что гиперкуб содержит одно измерение, </span><em><span>название фильма</span></em><span> , и одну меру, </span><em><span>средний рейтинг</span></em><span> , содержимое может выглядеть следующим образом:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">qDataPages: [
  {
    qMatrix: [
      [
        // first row
        { qText: '2 Fast 2 Furious', qNum: 'NaN', qElemNumber: 447, qState: 'O' }, // NxCell
        { qText: '6.2', qNum: 6.2, qElemNumber: 0, qState: 'L' },
      ],
      [
        // second
        { qText: '2 Guns', qNum: 'NaN', qElemNumber: 681, qState: 'O' },
        { qText: '6.6', qNum: 6.6, qElemNumber: 0, qState: 'L' },
      ],
    ],
    qArea: { qTop: 0, qLeft: 0, qWidth: 2, qHeight: 2 },
  },
];</pre>
<p><span>Помимо текстовых и числовых значений, каждая </span><a href="https://qlik.dev/apis/json-rpc/qix/schemas#%23%2Fdefinitions%2Fschemas%2Fentries%2FNxCell"><span>ячейка NxCell</span></a><span> содержит </span><code class=" language-text">qElemNumber</code><span>свойство, известное как </span><em><span>ранг</span></em><span> . Ранг для ячейки измерения можно рассматривать как свойство, которое однозначно идентифицирует текстовое значение этой ячейки в своем поле во всей модели данных. Вы можете использовать это свойство для обеспечения единообразного поведения во всем приложении, вы можете, например, установить постоянный цвет значений измерения в поле, когда и где бы они ни использовались:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">// color scheme
const colors = ['#26A0A7', '#79D69F', '#F9EC86', '#EC983D'];

const cellColor = colors[cell.qElemNumber % colors.length];</pre>
<p><span>Это свойство также необходимо отслеживать, когда вы хотите сделать выбор в своей диаграмме.</span></p>
<h4 id="getting-more-data"><span>Получение дополнительных данных</span></h4>
<p><span>Из-за ограничения объема данных, которые вы можете получить в исходном макете, могут возникнуть ситуации, когда вам потребуется получить остальные данные, если вы хотите отобразить их больше. Вы можете сделать это с помощью методов, представленных в </span><em><span>модели</span></em><span> универсального объекта. Какой метод использовать, опять же, зависит </span><code class=" language-text">qMode</code><span>от гиперкуба, для </span><code class=" language-text">'S'</code><span>режима это </span><a href="https://qlik.dev/apis/json-rpc/qix/genericobject#%23%2Fentries%2FGenericObject%2Fentries%2FGetHyperCubeData"><span>GetHyperCubeData</span></a><span> .</span></p>
<p><span>При подкачке данных в прямом режиме вы должны начать с просмотра </span><code class=" language-text">qHyperCubeDef.qSize</code><span>свойства, которое содержит информацию о ширине и высоте полного гиперкуба. Исходя из этого, вы можете рассчитать количество страниц, которые вам нужно получить:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useModel, useLayout, useEffect } from '@nebula.js/stardust';

const NUM_CELLS_PER_PAGE = 10000;
const MAX_PAGES = 10;
// ...
component() {
  const model = useModel();
  const layout = useLayout();

  useEffect(() =&gt; {
    const Y = layout.qHyperCube.qSize.qcy;
    const X = layout.qHyperCube.qSize.qcx;

    const HEIGHT_PER_PAGE = Math.ceil(NUM_CELLS_PER_PAGE / X);
    const NUM_PAGES = Math.floor(MAX_PAGES, Math.ceil(Y / HEIGHT_PER_PAGE));

    const pagesToFetch = [];
    for (let i = 0; i &lt; NUM_PAGES; i++) {
      pagesToFetch.push({ qLeft: 0, qTop: i * HEIGHT_PER_PAGE, qHeight: HEIGHT_PER_PAGE, qWidth: X });
    }

    Promise.all(pagesToFetch.map((page) =&gt; model.getHyperCubeData('/qHyperCubeDef', [page]))).then((pages) =&gt; {
      console.log(pages);
    });
  }, [layout]);

}</pre>
<p><span>Однако вы должны быть </span><strong><span>очень</span></strong><span> осторожны при динамической выборке таких данных, имейте в виду, что размер куба может исчисляться миллионами, выборка такого большого набора данных может занять время и создать очень плохое взаимодействие с пользователем. В предыдущем примере максимальное количество страниц установлено равным 10, так что всего выбирается не более 100 000 значений.</span></p>
<p><span>Вы также можете использовать другие методы, чтобы не получать все данные сразу. </span><em><span>Виртуальная прокрутка</span></em><span> в сочетании с регулированием каждого запроса может значительно повысить производительность. Вам также следует рассмотреть возможность использования сокращенного набора данных, если вам не нужны точные значения:</span></p>
<ul>
<li><a href="https://qlik.dev/apis/json-rpc/qix/genericobject#%23%2Fentries%2FGenericObject%2Fentries%2FGetHyperCubeBinnedData"><span>getHyperCubeBinnedData</span></a><span> связывает точки данных в группы и отлично подходит для тепловых карт и 2D-графиков плотности.</span></li>
<li><a href="https://qlik.dev/apis/json-rpc/qix/genericobject#%23%2Fentries%2FGenericObject%2Fentries%2FGetHyperCubeContinuousData"><span>getHyperCubeContinuousData</span></a><span> уменьшает количество точек в непрерывном измерении и отлично подходит для временных данных.</span></li>
<li><a href="https://qlik.dev/apis/json-rpc/qix/genericobject#%23%2Fentries%2FGenericObject%2Fentries%2FGetHyperCubeReducedData"><span>getHyperCubeReducedData</span></a><span> выполняет некоторую магию вейвлетов и отлично подходит для мини-диаграмм.</span></li>
</ul>
<h2>Selecting data. Выбор данных</h2>
<p><span>Выборка &#8211; это фундаментальная часть ассоциативного механизма Qlik. Все поля и связи между ними содержатся в ассоциативной модели. Когда вы применяете выбор, вы не только применяете фильтр в модели данных, но также демонстрируете связи между вашими источниками данных.</span></p>
<h3 id="applying-selections"><span>Applying selections. </span><span>Применение выделений</span></h3>
<p><span>Выборки можно применять с помощью методов, представленных в модели, возвращенной из </span><code class="language-text">useModel</code><span>хука.</span></p>
<p><span>Поскольку универсальный объект может содержать несколько гиперкубов, вам всегда нужно указать, какой гиперкуб вы хотите выбрать, указав его путь JSON в качестве первого аргумента:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useModel } from '@nebula.js/stardust';
// ...
component() {
  const model = useModel();

  useEffect(() =&gt; {
    model.selectHyperCubeCells('/qHyperCubeDef', [1], []);
  }, [model])
}</pre>
<h3 id="selection-patterns"><span>Шаблоны выбора. Selection patterns</span></h3>
<p><span>Есть два разных шаблона выбора: мгновенный и модальный.</span></p>
<h4 id="instant-selections"><span>Мгновенный выбор. Instant selections</span></h4>
<p><span>Как видно из названия, этот тип шаблона является немедленным и фильтрует как источник выбора, так и все, на что он влияет.</span></p>
<p><span>В следующем примере, как только значение выбрано на гистограмме, фильтрация применяется мгновенно, и обе диаграммы немедленно обновляются отфильтрованными данными:</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/selections_instant_qlik_sense_nebula_js_nebulajs_api.gif"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/selections_instant_qlik_sense_nebula_js_nebulajs_api.gif" alt="" width="912" height="388" class="aligncenter size-full wp-image-2460" /></a></p>
<h4 id="modal-selections"><span>Модальный выбор. Modal selections</span></h4>
<p><span>Когда инициируется модальный выбор, источник выбора входит в форму модального состояния, которое позволяет пользователю изменять выбор до подтверждения изменений.</span></p>
<p><span>В следующем примере пользователь сначала выбирает одно значение на линейчатой ​​диаграмме, после чего другие диаграммы обновляются, как и раньше. Однако гистограмма по-прежнему содержит все доступные данные и позволяет пользователю выбрать другое значение перед подтверждением изменений и обновлением самой гистограммы:</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/selections_modal_qlik_sense_nebula_js_nebulajs_api.gif"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2020/11/selections_modal_qlik_sense_nebula_js_nebulajs_api.gif" alt="" width="912" height="388" class="aligncenter size-full wp-image-2462" /></a></p>
<p><span>Чтобы реализовать этот тип паттерна, вам необходимо выполнить несколько простых шагов </span><code class=" language-text">useSelections</code><span>в сочетании с </span><code class=" language-text">useModel</code><span>ними:</span></p>
<ol>
<li><span>Войдите в модальное состояние, позвонив </span><code class=" language-text">beginSelections</code><span>.</span></li>
<li><span>Выберите значения.</span></li>
<li><span>Обеспечьте визуальную обратную связь с пользователем о том, что было выбрано, например, изменив прозрачность выбранных значений.</span></li>
<li><span>Следите за выходом из модального состояния, чтобы сбросить визуальную обратную связь.</span></li>
</ol>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { useModel, useSelections, useElement } from '@nebula.js/stardust';
// ...
component() {
  const element = useElement();
  const model = useModel();
  const selections = useSelections();

  useEffect(() =&gt; {
    const clicked = () =&gt; {
      const clickedOnRow = 1;

      // 1. enter modal state if not already in it
      if (!selections.isActive()) {
        selections.beginSelections(['/qHyperCubeDef']);
      }
      // 2. select the clicked row
      model.selectHyperCubeCells('/qHyperCubeDef', [clickedOnRow], []);
    }

    element.addEventListener('click', clicked);
    return () =&gt; {
      element.removeEventListener('click', clicked);
    }
  }, [element, model, selections]);

  useEffect(() =&gt; {
    if (layout.qSelectionInfo.qInSelections) {
      // 3. update with visual feedback on active selections
      // YOUR CODE HERE
    } else {
      // 4. normal update
      // YOUR CODE HERE
    }
  }, [layout]);
}</pre>
<p>&nbsp;</p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/nebula-js-qlik-sense-api-javascript-library-examples/">nebula.js &#8211; Qlik Sense API Javascript библиотека. Примеры</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/nebula-js-qlik-sense-api-javascript-library-examples/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Концепт Hypercube для Qlik Sense Developers</title>
		<link>https://qliksense.ivan-shamaev.ru/hypercube-concept-for-qlik-sense-developers/</link>
					<comments>https://qliksense.ivan-shamaev.ru/hypercube-concept-for-qlik-sense-developers/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Mon, 19 Aug 2019 15:02:36 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[initialProperties]]></category>
		<category><![CDATA[mashup]]></category>
		<category><![CDATA[qDimensions]]></category>
		<category><![CDATA[qHyperCubeDef]]></category>
		<category><![CDATA[qInitialDataFetch]]></category>
		<category><![CDATA[Qlik Data Engine]]></category>
		<category><![CDATA[Qlik Engine]]></category>
		<category><![CDATA[Qlik Sense Developers]]></category>
		<category><![CDATA[qMeasures]]></category>
		<category><![CDATA[Концепт Hypercube]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=1470</guid>

					<description><![CDATA[<p>HyperCube HyperCube можно считать сердцем большинства визуализаций. Это определение cube, предоставляемое Qlik Data Engine, которое содержит всю информацию о том, какие данные запрашиваются и как они рассчитываются. Если выборка (selections) применяется к HyperCube, отображаются только выбранные значения. HyperCube можно визуально представить как обычную прямую таблицу в Qlik с набором измерений<a class="moretag" href="https://qliksense.ivan-shamaev.ru/hypercube-concept-for-qlik-sense-developers/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/hypercube-concept-for-qlik-sense-developers/">Концепт Hypercube для Qlik Sense Developers</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">HyperCube</h2>



<p>HyperCube можно считать сердцем большинства визуализаций. Это определение cube, предоставляемое <strong>Qlik Data Engine</strong>, которое содержит всю информацию о том, какие данные запрашиваются и как они рассчитываются. Если выборка (selections) применяется к HyperCube, отображаются только выбранные значения.</p>
<p>HyperCube можно визуально представить как обычную прямую таблицу в Qlik с набором измерений и метрик, а также с дополнительными атрибутами.</p>
<p>Объект <code class="literal">qHyperCubeDef</code> играет значительную роль в создании визуализаций и других компонентов, которые в значительной степени зависят от механизма Qlik engine для расчетов.</p>



<h3 class="wp-block-heading">qHyperCubeDef</h3>



<p><code class="literal"></code><span style="font-size: inherit;"><code class="literal">qHyperCubeDef</code>&#8211; это описание объекта, который передается в API Qlik Engine для создания запроса для обработки. Большинство визуализаций, встроенных в Qlik Sense, основаны на определении HyperCube на корневом уровне (root level), то есть код расширения (extension) построен на этой технологии.</span></p>
<p>Фундаментальное определение <span style="font-size: inherit;"><strong>HyperCube</strong> (</span>гиперкуба) выглядит следующим образом:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">initialProperties:{
    version:1.0,
    qHyperCubeDef:{
    qDimensions:[],
    qMeasures:[],
    qInitialDataFetch:[{
        qWidth:2,
        qHeight:50
}]
  }
}</pre>
<p><strong>По-умолчанию</strong>, большинство расширений (extensions) не будут иметь никаких измерений или мер, определенных в их первоначальных свойствах (<code class="literal">initialProperties</code>), чтобы позволить пользователю достичь того же самого путем добавления измерений и метрики через панель свойств.</p>
<blockquote>
<p>Всегда добавляйте <code class="literal">initialProperties</code>, чтобы определить, сколько строк / столбцов доступно в вашем объекте JavaScript. При изменении начальных свойств <code class="literal">initialProperties</code> удалите и повторно добавьте расширение визуализации (<span>visualization extension)</span>; простого обновления страницы (F5) будет недостаточно.</p>
</blockquote>
<p>Размер фактического HyperCube в Qlik Engine определяется числом результирующих строк после его вычисления. Иногда HyperCube может быть огромным, и поэтому <strong>qInitialDataFetch</strong> позволяет вам определить, сколько из этих ячеек данных будет возвращено в код расширения. Это задается через параметры с <code class="literal">qWidth</code> и <code class="literal">qHeight</code>.</p>
<blockquote>
<p>Произведение параметров <span class="emphasis"><em>qWidth*qHeight</em></span> никогда не может превышать 10000 ячеек данных. Если вам необходимо вернуть более 10 000 ячеек данных для конкретного варианта использования или визуализации, вам потребуется реализовать последующую нумерацию (subsequent pagination) страниц в своем коде.</p>
</blockquote>



<h3 class="wp-block-heading">qHyperCubeDef properties &#8211; свойства</h3>



<p>Существует несколько высокоуровневых свойств, которые могут помочь изменить и установить базовый HyperCube, даже за пределами измерений и мер.</p>



<h4 class="wp-block-heading">qDimensions</h4>



<p><strong>qDimensions </strong>определяет массив измерений, которые будут использоваться в HyperCube. Обычно qDimensions определяется с помощью панели свойств, но это также может быть сделано вручную непосредственно в файле JSON. Последнее рекомендуется только для использования в мэшапах (mashup), когда вы определяете визуализацию на лету.</p>
<p>В дополнение к имени измерения (dimension name), Вы также можете определить параметры, такие как:</p>
<blockquote>
<ul type="bullet">
<li><code class="literal">qNullSuppression</code> &#8211; подавляет нулевые значения в измерении</li>
<li><code class="literal">qShowAll</code> &#8211; если задано значение true, отображает все значения измерений, независимо от того, выбраны ли они</li>
<li><code class="literal">qCalcCond</code> &#8211; устанавливает условие вычисления, которое должно быть выполнено для вычисления измерения</li>
<li><code class="literal">qTotalLabel</code> и <code class="literal">qOtherLabel</code> перемаркировка (переименовывание) меток Other и Total в возвращенном HyperCube</li>
</ul>
</blockquote>
<p>Если вы используете панель свойств (property panel) для определения измерений, простое использование этих свойств в качестве ссылочных значений позволяет вам определять их напрямую, например:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">suppressNulls:{
    type:"boolean",
    ref:"qNullSuppression",
    label:"Suppress Nulls",
    defaultValue: false
},</pre>



<h4 class="wp-block-heading">qMeasures</h4>



<p><code>qMeasures</code>&nbsp;очень похож на qDimensions, но помогает вам определить меры. Как и в случае с измерениями, они обычно задаются через панель свойств (property panel). </p>



<h4 class="wp-block-heading">qInitialDataFetch</h4>



<p><code>qInitialDataFetch</code>&nbsp;помогает определить, сколько ячеек данных первоначально извлекается из вычисленного HyperCube. </p>



<h4 class="wp-block-heading">qStateName</h4>



<p><code>qStateName</code>&nbsp;помогает определить имя альтернативного состояния, при этом $ (текущий выбор) является значением по умолчанию. Альтернативные состояния помогают создать виртуальный образ выборок, основанных на том же наборе данных, но не затронутых выборками, сделанными в других состояниях. В основном используется для сравнительного анализа. </p>



<h4 class="wp-block-heading">qInterColumnSortOrder</h4>



<p>Свойство <code>qInterColumnSortOrder</code>&nbsp;помогает определить порядок сортировки по столбцам в HyperCube. Он определяется с помощью массива целых чисел, например, [1,3,2,0], который указывает, в каком порядке будут сортироваться столбцы. </p>



<h4 class="wp-block-heading">qSuppressZero</h4>



<p><code>qSuppressZero</code>&nbsp;удаляет строки с нулевыми значениями во всей строке HyperCube, если установлено значение true. </p>



<h4 class="wp-block-heading">qSuppressMissing</h4>



<p><code>qSuppressMissing</code>&nbsp;удаляет строки, в которых отсутствуют значения по всей строке HyperCube, если установлено значение true. </p>



<h4 class="wp-block-heading">qMode</h4>



<p><code>qMode</code>&nbsp;определяет, в какой структуре будет возвращен HyperCube. По умолчанию и для большинства соответствующих случаев использования режим данных возвращается в виде таблицы. Дополнительные расширенные режимы доступны следующим образом:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Pivot Table&nbsp;representation &#8211; Представление сводной таблицы (<code>qMode P</code>)</p><p>Stacked Table representation &#8211; Представление Стековая таблица (<code>qMode K</code>)</p><p>Tree representation &#8211; Представление дерева (<code>qMode T</code>)</p></blockquote>



<p>Эти различные типы представлений являются расширенными и возвращают Вам предварительно агрегированный формат базовых измерений и мер, включая промежуточные итоги. </p>



<h4 class="wp-block-heading">qNoOfLeftDims</h4>



<p>Это свойство применяется к сводным таблицам и сложенным сводным таблицам.</p>



<p>В структуре сводной таблицы этот параметр используется, чтобы помочь определить, сколько и какие измерения заданы в виде строк, а какие повернуты по горизонтали (отображаются в столбцах). Это относительно продвинутый вариант, и дополнительную документацию по этому вопросу можно найти на странице справки Qlik Sense.</p>



<h4 class="wp-block-heading">qAlwaysFullyExpanded</h4>



<p>Это свойство применяется к сводным таблицам и сложенным сводным таблицам.</p>



<p>Это свойство гарантирует, что ячейки всегда раскрыты (Fully Expanded), если установлено значение true.</p>



<h4 class="wp-block-heading">qMaxStackedCells</h4>



<p>В сложенном режиме/в режиме с накоплением (qMode = K), этот параметр определяет максимальное количество ячеек для начальной выборки данных (по умолчанию 5000).</p>



<h4 class="wp-block-heading">qPopulateMissing</h4>



<p>Пропущенные значения или нули возвращаются как дефисы (-) в модели данных.&nbsp;<code>qPopulateMissing</code>&nbsp;заменяет числовые нули на 0, а строковые нули &#8211; пустыми строками.&nbsp; </p>



<h4 class="wp-block-heading">qShowTotalsAbove</h4>



<p>Если true, он возвращает итоговую строку в первой строке гиперкуба. Их также можно получить from&nbsp;<code>qHyperCube.qGrandTotalRow[i].qNum</code>. </p>



<h4 class="wp-block-heading">qIndentMode</h4>



<p>Это свойство применяется к сводным таблицам и сложенным сводным таблицам.</p>



<p>Это свойство применяет отступ для сводных таблиц и позволяет изменять макет таблицы (<code>layout</code>), добавляя отступ в начало каждой строки.</p>



<h4 class="wp-block-heading">qCalcCond</h4>



<p><code>qCalcCond</code>&nbsp;определяет условие вычисления для всего гиперкуба для вычисления. Это особенно полезно, когда у вас широкие таблицы с очень сложными вычислениями, и вы хотите убедиться, что пользователь отфильтровал подмножество данных перед запуском вычисления в движок Qlik. Тяжелые вычисления не только увеличивают время расчета, но и увеличивают использование RAM на вашем сервере Qlik Sense. </p>



<h4 class="wp-block-heading">qSortbyYValue</h4>



<p>Это свойство применяется к сводным таблицам и сложенным сводным таблицам.</p>



<p><code>qSortbyYValue</code>&nbsp;включает сортировку по возрастанию или убыванию в значениях меры.</p>



<h3 class="wp-block-heading">Возращаемая структура qHyperCube structure</h3>



<p><span>Как только </span><code class="literal">qHyperCubeDef</code><span> определен с помощью набора свойств или с помощью панели свойств</span>, Qlik Engine рассчитывает HyperCube при каждой выборке и взаимодействии с Qlik engine. После расчета он возвращает структуру<span>&nbsp;</span><code class="literal">qHyperCube</code><span>&nbsp;</span>в<span>&nbsp;</span><code class="literal">layout</code>&nbsp;вместе с результатами.</p>
<p>В расширении (extension) <strong>MasteringQS</strong>&nbsp;следующий пример иллюстрирует возвращенный вычисленный<span>&nbsp;</span><code class="literal">qHyperCube</code> для образца измерения и метрики:</p>
<p><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/propertyjs_panel_values_extensionMeta_qHyperCube.png" alt="" width="665" height="708" class="aligncenter size-full wp-image-1475" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/propertyjs_panel_values_extensionMeta_qHyperCube.png 665w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/propertyjs_panel_values_extensionMeta_qHyperCube-282x300.png 282w" sizes="(max-width: 665px) 100vw, 665px" /></p>
<p><span>Теперь Вы, наверное, можете интуитивно распознать большинство&nbsp; объектов и переменных. Любое свойство, начинающееся с буквы q, является свойством определения Qlik; однако есть некоторые дополнительные, которые не имеют префикса (например, заголовок и подзаголовок).</span></p>
<blockquote>
<p><span>Кроме того, вместе с </span><code class="literal">qHyperCube</code><span>, </span><code class="literal">layout</code><span>&nbsp;также возвращает информацию, хранящуюся в файле</span><code class="literal">.qext</code><span> которую можно получить через свойство объекта </span><code class="literal">extensionMeta</code><span>. То же самое относится к пользовательским свойствам, определенным в файле <strong>properties.js</strong>, которые также возвращаются в </span><code class="literal">layout</code><span> ,вместе с </span><code class="literal">qHyperCube</code><span>, например </span><code class="literal">fontSize</code><span>,</span><code class="literal">fontFamily</code><span>, и так далее.</span></p>
</blockquote>
<p>Для начала обратите внимание на следующие объекты:</p>
<div class="itemizedlist">
<ul type="bullet">
<li><code class="literal">layout.qHyperCube.qDimensionInfo</code>: Used dimensions (Используемые измерения)</li>
<li><code class="literal">layout.qHyperCube.qMeasureInfo</code>: Used measures (Используемые меры)</li>
<li><code class="literal">layout.qHyperCube.qDataPages</code>: Результат</li>
<li><code class="literal">layout.qHyperCube.qSize</code>: The page size (Размер страницы/Размер гиперкуба)</li>
</ul>
</div>
<p>Из этих трех наиболее актуальным является, конечно,<span>&nbsp;</span><code class="literal">qDataPages</code>, который содержит рассчитанные данные:</p>
<p><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/return_size_of_data_qDataPages.png" alt="" width="509" height="428" class="aligncenter size-full wp-image-1476" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/return_size_of_data_qDataPages.png 509w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/return_size_of_data_qDataPages-300x252.png 300w" sizes="(max-width: 509px) 100vw, 509px" /></p>
<p><span>Если вы развернете узел </span><code class="literal">qDataPages</code>, то вы увидите следующее you:</p>
<div class="itemizedlist">
<ul type="bullet">
<li><code class="literal">qDataPages</code><span> это массив</span></li>
<li><span>данные хранятся в </span><code class="literal">qDataPages[0].qMatrix</code>, который снова является массивом объектов, представляющих строки, каждый из которых снова содержит массив некоторых других объектов, представляющих отдельные ячейки (столбцы для каждой строки)</li>
</ul>
</div>
<p>В свою очередь каждая ячейка содержит следующую информацию:</p>
<div class="itemizedlist">
<ul type="bullet">
<li><code class="literal">qText</code>, текстовое представление результирующего значения ячейки</li>
<li><code class="literal">qNum</code>, если число, то вернет Вам числовое значение</li>
<li>Если ячейка является измерением,<span>&nbsp;</span><code class="literal">qElemNumber</code><span> предоставит вам внутренний идентификатор значения измерения, который можно использовать для выбора с помощью</span>&nbsp;<code class="literal">qState</code>, состояния выборки объекта</li>
</ul>
</div>
<p><span>Одной из типичных задач является преобразование данных </span><code class="literal">qDataPages.qMatrix</code><span> в массив объектов другого формата для лучшей обработки в коде расширения</span>.</p>
<p><span>Например, если вы знаете, что у вас всегда будет только одно значение измерения и одна метрика, преобразование структуры данных в нечто более удобное для вашего кода может быть выполнено с помощью функции </span><code class="literal">.map()</code><span>, которая выглядит следующим образом</span>:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">var data = [];
 data = scope.layout.qHyperCube.qDataPages[0].qMatrix.map(function(d) {
 return {
     dimensionvalue: d[0].qText,
     measurevalue: d[1].qNum
 };
 })</pre>
<p><span>Результат выглядит намного дружелюбнее:</span></p>
<p><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/result_hypercube_dimensionvalue_measurevalue.png" alt="" width="471" height="372" class="aligncenter size-full wp-image-1479" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/result_hypercube_dimensionvalue_measurevalue.png 471w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/result_hypercube_dimensionvalue_measurevalue-300x237.png 300w" sizes="(max-width: 471px) 100vw, 471px" /></p>



<h3 class="wp-block-heading">qListObjectDef</h3>



<p>The family of generic objects<span>&nbsp;</span><span>has</span><span>&nbsp;</span>provided<span>&nbsp;</span><code class="literal">qHyperCube</code><span>&nbsp;</span>with a sister called the<span>&nbsp;</span><code class="literal">qListObject</code>. Unlike a HyperCube, a list object better serves the<span>&nbsp;</span><span>purposes</span><a id="id288633443" class="indexterm"></a><span>&nbsp;</span>of displaying one single dimension<span>&nbsp;</span><span class="emphasis"><em>without</em></span><span>&nbsp;</span>any required calculation, meaning no metrics are required to be defined. As such, it is fairly straightforward to work the list objects, and their definition is very similar to the<span>&nbsp;</span><code class="literal">qHyperCube</code><span>&nbsp;</span>object, with some added extra properties but without measures.&nbsp;</p>
<p>The following code is an example of creating a<span>&nbsp;</span><code class="literal">qListObjectDef</code><span>&nbsp;</span>and writing the resulting list object into the console:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">//DefineListObject
var obj = {
    "qDef": {
    "qFieldDefs": ["Case Owner"]
    },
    "qShowAlternatives" : true,
    "qInitialDataFetch": [{
        qTop : 0,
        qLeft : 0,
        qHeight : 10000,
        qWidth : 1
    }]
    };

var app = qlik.currApp(this);

//Create the listbox as a session object which will persist over the //session and then be deleted.
app.createList(obj,function(listobject) {
  console.log(listobject)
})</pre>



<p><span>Код возвращает следующий результат:</span></p>
<p><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/qListObjectDef_result.png" alt="" width="398" height="609" class="aligncenter size-full wp-image-1480" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/qListObjectDef_result.png 398w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2019/08/qListObjectDef_result-196x300.png 196w" sizes="(max-width: 398px) 100vw, 398px" /></p>
<p><span>Это структура, очень похожая на </span><code class="literal">qHyperCube</code>, с ее<span>&nbsp;</span><code class="literal">qDataPages</code>, но с дополнительной информацией о найденном объекте измерения и списка.</p>
<p><span>Помимо классических свойств, уже описанных для </span><code class="literal">qHyperCube</code>, для объекта<span>&nbsp;</span><code class="literal">qListObject</code> вы можете определить следующие параметры:</p>
<div class="itemizedlist">
<ul type="bullet">
<li><code class="literal">qAutoSortByState</code>: определяет сортировку по состоянию.</li>
<li><code class="literal">qFrequencyMode</code>: Определяет frequency mode используемый для расчета частоты значения в объекте списка. Этот параметр является необязательным, и по умолчанию частота не возвращается (<code class="literal">NX_FREQUENCY_NONE</code>). Альтернативные значения:<span>&nbsp;</span><code class="literal">NX_FREQUENCY_VALUE</code>,<span>&nbsp;</span><code class="literal">NX_FREQUENCY_PERCENT</code>, и<span>&nbsp;</span><code class="literal">NQ_FREQUENCY_RELATIVE</code>.</li>
<li><code class="literal">qShowAlternatives</code>: если для этого параметра установлено значение <strong>true</strong>, это позволит включить альтернативные значения в возвращаемые данные <strong>qData</strong>. Если установлено значение <strong>false</strong>, альтернативные значения не отображаются в <code class="literal"><span>qData</span></code>&nbsp;(Вместо этого значения исключены). <code class="literal">qStateCounts</code><span> считает исключенные значения в качестве альтернативных значений</span>.</li>
</ul>
<blockquote>
<p><span>Важно отметить, что с помощью </span><code class="literal">qListObject</code><span>, все значения отображаются независимо от того, были они исключены или нет. Если выбор применяется к объекту списка, выбранные значения отображаются вместе с исключенными и дополнительными значениями.</span></p>
</blockquote>
</div>



<h3 class="wp-block-heading">qStringExpression и qValueExpression</h3>



<p><span>Для простоты одноразовых вычислений, в которых вы просто хотите использовать всю мощь механизма <strong>Qlik Sense Engine</strong>, </span><code class="literal">qStringExpression</code><span> и&nbsp;</span><code class="literal">qValueExpression</code><span> являются младшими сестрами</span><span>&nbsp;</span><code class="literal">qHyperCube</code><span> и&nbsp;</span><code class="literal">qListObject</code><span>. Они работают, используя ту же концепцию, что и остальные, но на более простом уровне: все, что вам нужно сделать, это определить выражение Qlik, и механизм вернет вам свой результат</span><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">var app = qlik.currApp(this);
app.createGenericObject({
    user: {
qStringExpression:"=OSUser()"
    }, 
    version: {
qStringExpression:"=EngineVersion()"
    }, 
    fields: { 
qValueExpression:"=Count (DISTINCT $Field)"
    } 
}, function ( reply ) { 
    var str = "Version:" + reply.version + 
        str+= " Number of Fields:"+reply.fields; 
    if(reply.user) { 
        str += " User:" + reply.user; 
    }
    console.log(str)
}</pre>
<p><span>Использование этих определений объектов очень удобно в сочетании с другими объектами, такими как </span><code class="literal">qHyperCube</code><span>.</span></p>
<blockquote>
<p><span>Знак </span><code class="literal">=</code><span> в строковом выражении не является обязательным. Даже если знак </span><code class="literal">=</code><span> не указан, выражение вычисляется. Строковое выражение не оценивается, если выражение окружено чистыми кавычками.</span></p>
</blockquote>



<h2 class="wp-block-heading">Kill the hypercubes</h2>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Kill the hypercubes" width="750" height="563" src="https://www.youtube.com/embed/-w-d1Am2cjY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><figcaption> See how to manage and clean up  hypercubes in a Qlik Sense Mashup. </figcaption></figure>



<p>Find the code shown in this video for both the Visualization API and the Capabilities API: <a href="https://github.com/ChristofSchwarz/qs-mash-KillHypercube" target="_blank" rel="noreferrer noopener" aria-label="https://github.com/ChristofSchwarz/qs-mash-KillHypercube (opens in a new tab)">https://github.com/ChristofSchwarz/qs-mash-KillHypercube</a></p>



<h2 class="wp-block-heading">Mash-Up APIs Part 4: Creating Hypercubes</h2>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Mash-Up APIs Part 4: Creating Hypercubes" width="750" height="422" src="https://www.youtube.com/embed/pDbDbkc22Ds?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><figcaption> In Part 4, we’ll explain the power of HyperCubes and how to use them in your web applications.</figcaption></figure>



<h2 class="wp-block-heading">Qlik Sense Tutorial | Creating Qlik Sense Mashup by using Hypercube</h2>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Qlik Sense Tutorial | Creating Qlik Sense Mashup by using Hypercube" width="750" height="422" src="https://www.youtube.com/embed/D_cDvUTps80?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><figcaption> We provide industry standard online training on Qlik Sense Development , Administration and live project development with hand-holding support of expert trainer. For Instructor lead live Qlik Sense online training, please feel free to get back to us on below contact details.</figcaption></figure>



<h2 class="wp-block-heading">Mash-Up APIs Part 3: Connecting to Fields</h2>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Mash-Up APIs Part 3: Connecting to Fields" width="750" height="422" src="https://www.youtube.com/embed/fqGwrGhlW-I?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><figcaption> Learn how to connect and hook into fields in the Qlik Sense data model and use them on your web site. </figcaption></figure>



<h2 class="wp-block-heading">Getting started building mashup &#8211; Qlik Sense</h2>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Getting started building mashup - Qlik Sense" width="750" height="422" src="https://www.youtube.com/embed/dyTAXzcgR5E?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><figcaption> The Mashup editor assists you in creating your mashups displaying Qlik Sense data on your website. This video shows you how to create your first mashup in Qlik Sense Developer Hub, how to add objects from multiple Qlik Sense apps, how to create a list and a hypercube, and how to import asset files.</figcaption></figure>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/hypercube-concept-for-qlik-sense-developers/">Концепт Hypercube для Qlik Sense Developers</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/hypercube-concept-for-qlik-sense-developers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
