Содержание урока по Qlik Sense

Введение в nebula.js

nebula.js представляет собой набор библиотек JavaScript, визуализаций и интерфейсов командной строки, которые помогают разработчикам создавать и интегрировать визуализации поверх ассоциативного движка Qlik.

Коллекция организована в @nebula.jsрамках области в виде пакетов npm. Основной пакет @nebula.js/stardustсодержит API-интерфейсы для интеграции существующих визуализаций с гибридными приложениями, а также API-интерфейсы для создания пользовательских визуализаций.

EMBEDDING VISUALIZATIONS. ВСТРАИВАНИЕ ВИЗУАЛИЗАЦИЙ

Configuration. Конфигурация

Когда вы создаете веб-сайт, будь то сайт всей компании или небольшой личный проект, у вас, скорее всего, есть свои собственные рекомендации по дизайну, шаблоны и требования UX, и вы захотите применить эти рекомендации к тому, что вы с ним интегрируете; диаграммы должны использовать ваши цветовые схемы, шрифты, языковой стандарт и уважать любые ограничения, которые могут быть у вас на интерактивность. Вы также можете контролировать, как загружаются диаграммы и темы, в зависимости от того, подключено ли ваше решение к сети или нет.

Вы можете управлять большинством из них через Configurationобъект.

Временный конфиг

ConfigurationОбъект является необязательным аргументом , который вы можете предоставить при инстанцировании embedэкземпляра:

import { embed } from '@nebula.js/stardust';

const n = embed(enigmaApp, {
  context: {
    theme: 'dark',
  },
  types: [
    /* types */
  ],
});

n.render(/* chart 1*/);
n.render(/* chart 2*/);

Многоразовая конфигурация

Если вы работаете с несколькими приложениями или хотите иметь несколько разных конфигураций, вам может быть проще сначала создать конфигурации, а затем повторно использовать их.

Создайте файл, baseConfigкоторый выполняет тяжелую работу по регистрации типов и тем:

const baseConfig = embed.createConfiguration({
  types: [
    /* register type once*/
  ],
  themes: [
    /* register themes once*/
  ],
});

Создайте другую конфигурацию, которая наследуется от baseConfig, примените 'dark'тему и установите ограничение, запрещающее выбор:

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*/);

Вы также можете напрямую привязать конфигурацию к приложению:

const swedishPink = baseConfig(enigmaApp, {
  context: {
    theme: 'pinkish',
    language: 'sv-SE',
  },
});

swedishPink.render(/* chart config */);

Регистрация типов

Перед визуализацией визуализации ее модуль необходимо загрузить и зарегистрировать. Вы можете загрузить необходимые модули из npm:

$npm install @nebula.js/sn-bar-chart @nebula.js/sn-pie-chart

А потом зарегистрируйте каждого typeиндивидуально:

import barchart from '@nebula.js/sn-bar-chart';
import piechart from '@nebula.js/sn-pie-chart';

embed.createConfiguration({
  types: [
    {
      name: 'bar',
      load: () => Promise.resolve(barchart),
    },
    {
      name: 'pie',
      load: () => Promise.resolve(piechart),
    },
  ],
});

Загрузка на лету

Если вы точно не знаете, какие типы вам нужны, и не хотите устанавливать все, чтобы уменьшить размер вашего пакета, вы можете загрузить визуализации во время выполнения, используя облегченный загрузчик определений асинхронных модулей, например d3-require .

Начнем с установки модуля:

npm install d3-require

а затем настройте его для загрузки модулей из CDN, например https://unpkg.com, а также укажите псевдоним для использования локальной версии @nebula.js/stardust:

import { requireFrom } from 'd3-require';
import * as stardust from '@nebula.js/stardust';

const loadSnType = requireFrom((name) => `https://unpkg.com/@nebula.js/sn-${name}-chart`).alias({
  '@nebula.js/stardust': stardust,
});

Затем вы можете настроить все типы, которые вы ожидаете использовать:

const types = ['bar', 'line', 'pie', 'sankey'].map((t) => ({
  type: t,
  load: () => loadSnType(t),
}));
const baseConfig = stardust.embed.createConfiguration({ types });

Тип загружается с удаленного URL-адреса при первом отображении:

baseConfig(enigmaApp).render({
  type: 'bar',
  fields: ['Product', '=sum(Sales)'],
});

Контекст

При настройке конфигурации вы можете применить, contextкоторый контролирует язык, тему и ограничения в каждой визуализации, которую вы визуализируете:

embed.createConfiguration({
  context: {},
});

Ограничения

Ограничения позволяют указать визуализации на отключение определенных типов взаимодействий и поведения.

Вы можете применить три различных ограничения:

  • passive: отключить такие взаимодействия, как всплывающие подсказки.
  • active: отключение взаимодействий, влияющих на состояние визуального представления, таких как масштабирование, прокрутка и т. д.
  • select: выключить выделение.
{
  context: {
    constraints: {
      active: true,
      passive: true,
      select: true,
    },
  },
};

stardust никоим образом не навязывает эти ограничения, вместо этого разработчик визуализации должен соблюдать и реализовывать их.

Язык

stardust поддерживает 15 языков:

  • 'en-US' – Американский английский
  • 'sv-SE' – шведский
  • 'it-IT' – итальянский
  • 'zh-CN' – Упрощенный китайский
  • 'zh-TW' – Традиционный китайский
  • 'ko-KR' – Корейский язык
  • 'de-DE' – Немецкий
  • 'es-ES' – Испанский
  • 'pt-BR' – Бразильский португальский
  • 'ja-JP' – Японский
  • 'fr-FR' – Французкий язык
  • 'nl-NL' – Голландский
  • 'tr-TR' – Турецкий
  • 'pl-PL' – польский
  • 'ru-RU' – Русский
{
  context: {
    language: 'sv-SE',
  },
};

Тема

Из коробки доступны две основные темы: 'light'и 'dark'.

{
  context: {
    theme: 'dark',
  }
};

Светлая тема

Темная тема

Вы также можете зарегистрировать собственные темы и применить одну из них в контексте:

{
  themes: [{
    id: 'pinkish',
    load: () => Promise.resolve({
      palettes: {
        data: [{
          scale: [
            '#fac6e5',
            '#ff95d6',
            '#e76eb1',
            '#b44772',
          ],
        }]
      }
    })
  }],
  context: {
    theme: 'pinkish'
  }
};

Embedding visualizations. Встраивание визуализаций

Встраивание визуализаций

Вы можете встроить визуализацию двумя способами:

  1. На лету
  2. Из существующего объекта

Рендеринг выполняется с использованием render()метода экземпляра, возвращаемого embedфункцией, который, как минимум, требует того, в который HTMLElementвы хотите выполнить рендеринг:

import { embed } from '@nebula.js/stardust';

const n = embed(enigmaApp);
n.render({
  element,
  // rest of the config
});

Рендеринг на лету

При рендеринге визуализации на лету вам необходимо указать, что type вы хотите визуализировать:

n.render({
  element,
  type: 'barchart',
});

Некоторые визуализации предъявляют минимальные требования к различным свойствам и / или данным, которые необходимо отображать, и в этом случае вы можете увидеть что-то вроде этого:

Чтобы предоставить визуализацию исходные данные, добавьте в fieldsсвойство измерения и меры данных :

n.render({
  element,
  type: 'barchart',
  fields: ['Region', '=sum(Sales)'],
});

Вы также можете изменить начальные свойства:

n.render({
  element,
  type: 'barchart',
  fields: ['Product', '=sum(Sales)'],
  properties: {
    title: 'Sales by region',
  },
});

Рендеринг из существующих объектов

Если вы уже создали общий объект в своем приложении и хотите его отобразить, вы можете сделать это, предоставив объекту id:

n.render({
  element,
  id: '<ObjectID>',
});

Current app selections. Выборки текущего приложения

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

Панель выбора текущего приложения

На панели выбора текущего приложения отображаются активные в данный момент выборки в указанном приложении. Для рендеринга этого бара вам сначала понадобится HTMLElement:

<div class="curr-selections"></div>

Затем вы можете mountвыбрать пользовательский интерфейс в этом элементе:

const n = embed(enigmaApp);

(await n.selections()).mount(document.querySelector('.curr-selections'));

Без каких-либо выделений должно получиться так:

Когда вы начинаете применять выборки в различных диаграммах, пользовательский интерфейс обновляется, чтобы отразить текущее состояние:

Несколько баров

Если вы подключены к нескольким приложениям, вы можете отобразить текущий выбор в каждом из них, установив панель в разные элементы:

(await embed(enigmaApp).selections()).mount(document.querySelector('.curr-selections'));

(await embed(anotherApp, { context: { theme: 'dark' } }).selections()).mount(
  document.querySelector('.another-curr-selections')
);

DEVELOPING VISUALIZATIONS. РАЗРАБОТКА ВИЗУАЛИЗАЦИЙ

Visualization. Визуализация

Что такое визуализация

Визуализация в контексте этого API представляет собой визуальный вывод некоторых базовых данных, хранящихся в ассоциативной модели данных Qlik. Это может быть почти все, что вы хотите, и оно традиционно разработано для отображения данных в форме диаграммы, таблицы, kpi и т. Д.

Визуализация состоит из двух основных частей:

  • backend Generic Object, который описывает свойства этого визуализация и сохраняется в модели данных,
  • и внешний интерфейс визуальной части, которая производит рендеринг layout  из Generic Object.

Определение

Минимальная визуализация, которая не содержит никаких данных и ничего не отображает, выглядит так:

export default function () {
  return {
    qae: {
      /* */
    },
    component() {},
  };
}

Здесь component()вы визуализируете визуальную часть, а qaeздесь вы определяете свойства и данные, обрабатываемые ассоциативным механизмом Qlik (QAE).

Rendering. Рендеринг

В componentчасти определения происходит весь рендеринг, это просто функция, которая ничего не возвращает:

export default function () {
  return {
    component() {
      // rendering logic goes here
    },
  };
}

Чтобы отрендерить что-то, что вам нужно для доступа к элементу DOM, которому назначена визуализация, вы можете сделать это, импортировав useElement функцию:

import { useElement } from '@nebula.js/stardust';

Эта функция возвращает простой HTMLElement, который является вашей точкой входа в визуальный мир:

component() {
  const element = useElement();
  element.innerHTML = 'Hello!';
}

useElement– это одна из многих функций, которые удовлетворяют наиболее распространенные требования при разработке визуализации, они позволяют подключаться к ресурсам, предоставляемым обеими stardustсторонами и ассоциативным движком Qlik.

Hooks

Если вы работали с React, вы могли узнать это как хуки . Хуки – это концепция, в которой упор делается на многократно используемые составные функции, а не на классические объектно-ориентированные классы и наследование. Хотя реализация полностью настраивается с использованием настраиваемых хуков, концепция и правила очень похожи, настолько, что вы можете прочитать документацию по крючкам React, чтобы понять, как использовать собственные хуки stardust.

useElement

Вы уже видели useElementкрючок, его единственная цель – предоставить HTMLElement, к которому вы должны прикрепить свои собственные элементы, чтобы сделать ваш контент видимым, в следующем примере для элемента innerHTMLустановлено значение Hello!:

component() {
  // get the element
  const element = useElement();
  // set element content
  element.innerHTML = 'Hello!';
}

Однако статическая строка не даст многого, в большинстве случаев вы обновляете контент на основе ввода данных, состояния компонентов и взаимодействия с пользователем.

component()Функция выполняется каждый раз , когда что – то , что может быть связано с вашими изменениями рендеринга; тема, модель данных, выбор данных, состояние компонента и т. д. Таким образом, добавление и удаление прослушивателей событий, обновление узлов DOM и выборка данных не идеальны и могут быть довольно тяжелыми для производительности, если делать это каждый раз при component()запуске. Вместо этого вы должны выполнять пакетные обновления с useEffect.

useEffect

useEffect– это ловушка, которая принимает функцию обратного вызова, которая запускается только при изменении указанного вами значения. Это позволяет не только выполнять пакетные обновления, но и реализовывать собственную форму управления жизненным циклом в вашем компоненте.

import { useEffect } from '@nebula.js/stardust';
// ...
component() {
  const element = useElement();

  useEffect(() => {
    // run only once when the component is created
    console.log('created');
  }, []);
}

Добавление слушателей событий к элементу обычно выполняется только при запуске компонента, а затем удаляется при его уничтожении:

component() {
  const element = useElement();

  useEffect(() => {
    const listener = () => {
      console.log('clicked');
    };

    element.addEventListener('click', listener);

    return () => {
      // clean-up
      element.removeEventListener('click', listener);
    };
  }, [element]);
}

В предыдущем примере elementв качестве второго аргумента предоставляется наблюдаемое значение, поэтому эффект запускается только при elementизменении. Однако, поскольку elementникогда не изменяется для одного и того же компонента, обратный вызов запускается только один раз при создании компонента. Таким образом listener, экземпляр может быть создан только один раз, и clickдобавляется только один прослушиватель событий. Обратный вызов также возвращает функцию в конце, это функция очистки, которая выполняется при изменении любого из наблюдаемых значений или при уничтожении компонента. Здесь вы должны очистить все добавленные побочные эффекты, в этом случае прослушиватель событий удаляется, чтобы избежать утечки памяти.

useState

Поскольку component()это функция, а не экземпляр класса или объекта, вы не можете использовать его thisдля хранения значений экземпляра, как в противном случае. Способ хранения состояния useState:

import { useState } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const [count, setCount] = useState(0);
    },
  };
}

useStateвозвращает кортеж, в котором первый элемент совпадает с начальным значением, указанным в качестве аргумента useState, а второй элемент является функцией установки, с помощью которой вы можете изменить значение.

В следующем примере countувеличивается на 1, когда пользователь нажимает element:

component() {
  const element = useElement();
  const [count, setCount] = useState(0);

  useEffect(() => {
    const listener = () => {
      setCount(count + 1);
    };

    element.addEventListener('click', listener);

    return () => {
      element.removeEventListener('click', listener);
    };
  }, [element]);
}

Чтобы отобразить обновленное значение, вы можете добавить другое, useEffectкоторое будет запускаться при countизменении:

const [count, setCount] = useState(0);
useEffect(() => {
  element.innerHTML = `Count: ${count}`;
}, [count]);

Configuring data. Конфигурирование данных

В qaeразделе определения вы определяете свойства универсального объекта и форму данных, которые вы ожидаете использовать.

{
  "qae": {
    "properties": {}
  }
}

Общий объект

Каждая визуализация связана со всей моделью данных и ассоциативным механизмом Qlik через универсальный объект . Это объект JSON, содержащий свойства, в результате которых создается макет , описывающий состояние внутренней части визуализации.

Каждый раз, когда кто-то хочет визуализировать вашу визуализацию, в модели данных создается экземпляр универсального объекта. Если у создателя есть необходимые разрешения, он может сохранить и сохранить этот объект в своей модели данных.

Свойства

Какие свойства вы устанавливаете, полностью зависит от вас, однако это должен быть действительный объект JSON. Большинство свойств – это просто настройки, которые вы, возможно, захотите сохранить с течением времени. Если вы разрабатываете гистограмму, вы можете сохранить настройку, которая указывает, следует ли ее складывать или какой цвет должны иметь столбцы:

{
  "isStacked": true,
  "barColor": "red"
}

Эти свойства статичны , то, что входит, выходит точно так же. Истинная сила универсального объекта – это динамические свойства, которые вы можете установить, что позволяет вам использовать ассоциативный механизм Qlik и получать доступ к данным внутри него.

Динамические свойства имеют особую структуру, которая позволяет серверной части различать динамические и статические свойства. У них также есть соглашение об именах: все они начинаются с qбуквы, за которой следует заглавная буква, что позволяет людям и машинам легко различать два типа свойств.

Существует множество различных предопределенных динамических свойств для различных целей, например, вы можете использовать ValueExpression для выполнения простых вычислений:

{
  "simpleMath": {
    "qValueExpression": {
      "qExpr": "1+1"
    }
  }
}

Layout (Макет/Слой)

layout из Generic Object является результатом статических и динамических свойств. layout предыдущих свойств выглядит следующим образом:

{
  "isStacked": true,
  "barColor": "red",
  "simpleMath": 2
}

Обратите внимание, что статические свойства остаются точно такими же, в то время как динамическое свойство simpleMathтеперь содержит вычисленный результат ValueExpression.

Большинство динамических свойств имеют определение ввода и соответствующий вывод макета; а ListObjectDef приводит к ListObject , а SelectionObjectDef результаты в SelectionObject , и так далее.

Данные

Наиболее часто используемым определением свойства является HyperCubeDef , это динамическое свойство, которое предоставляет вам данные из внутренней модели данных. Вы можете разместить это в корне объекта свойств или на более глубоком уровне, и у вас может быть столько, сколько вам нужно:

{
  "qHyperCubeDef": {},
  "anotherOne": {
    "qHyperCubeDef": {},
    "andAThird": {
      "qHyperCubeDef": {}
    }
  }
}

Основными входными данными HyperCubeDef являются измерения и меры :

{
  "qHyperCubeDef": {
    "qDimensions": [{ "qLibraryId": "hdg534" }],
    "qMeasures": [{ "qLibraryId": "gt5dgd" }]
  }
}

В этом случае измерения и меры жестко запрограммированы на предопределенное значение, которое может существовать в определенной модели данных, что редко бывает тем, что вам нужно. Если вы разрабатываете диаграмму для использования другими с какой-либо моделью данных, которая вам нужна, чтобы можно было добавлять их динамически, вы можете сделать это, указав целевые объекты данных .

Цели данных

Целевой объект данных – это способ определить, где расположены динамические HyperCubeDef в свойствах универсального объекта. Хотя вы stardustможете просматривать свойства и находить все их использования qHyperCubeDef, вы можете не захотеть, чтобы все они были динамическими, или вы можете сгенерировать их только для внутреннего использования.

Вы указываете целевые объекты данных с помощью data.targetsключа qae, каждая цель должна иметь pathключ, который указывает путь JSON к HyperCubeDef из корня объекта свойств:

qae: {
  properties: {
    qHyperCubeDef: {},
    my: {
      nested: {
        qHyperCubeDef: {}
      },
    }
  },
  data: {
    targets: [
      { path: '/qHyperCubeDef' },
      { path: '/my/nested/qHyperCubeDef' },
    ];
  }
}

Вы можете для каждого целевого объекта данных указать дополнительные сведения, такие как максимальное / минимальное количество измерений и мер, и внести изменения при их добавлении.

Это полезно, когда вы знаете ограничения того, что может отображать диаграмма. Например, круговая диаграмма в основном используется, когда у нее есть ровно одно измерение и одна мера, но вы также можете реализовать поддержку второй меры. Это также избавляет вас от некоторой логики кода, поскольку stardustне пытается отобразить диаграмму, ограничения которой не были выполнены, а вместо этого показывает, что некоторые поля отсутствуют.

Field limitations. Ограничения поля

Чтобы указать ограничения для измерений или показателей, добавьте каждый соответствующий тип поля как объект как часть целевого объекта данных:

targets: [
  {
    path: '/qHyperCubeDef',
    dimensions: {
      min: 1,
      max: 1,
    },
    measures: {
      min: 1,
      max: 2,
    },
  },
];

Field modifications

Вы также можете изменить добавленное или удаленное поле непосредственно перед тем, как изменение будет применено и отправлено на серверную часть, это полезно для таких вещей, как настройка сортировки при добавлении измерения или добавление дополнительных свойств, которые, как вы знаете, всегда необходимы.

Если вы, например, хотите убедиться, что нулевые значения подавляются, поскольку это не то, что вы можете визуализировать или представить в хорошем виде, вы можете установить, qNullSuppression: trueкогда добавляется измерение:

dimensions: {
  added(dimension) {
    dimension.qNullSuppression = true;
  }
}

Consuming data. Потребление данных

Access layout

Вы можете получить доступ к layout Generic Object через набор предопределенных hooks.

useLayout

useLayout возвращает evaluated layout свойств Generic Object:

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 }
    },
  };
}

Вы должны useEffectпри наблюдении изменений на layout:

const layout = useLayout();

useEffect(() => {
  // do some heavy update
}, [layout]);

useAppLayout

useAppLayoutвозвращает NxAppLayout, к которому вы в данный момент подключены:

import { useAppLayout } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const appLayout = useAppLayout();
      console.log(appLayout); // { qTitle: 'App title', qLocaleInfo: {/* */ } }
    },
  };
}

Наиболее распространенный вариант использования макета приложения – это доступ, qLocaleInfoкоторый содержит сведения о локали, выбранные владельцем приложения и должен использоваться для форматирования чисел.

Models. Модели

Помимо макетов приложения и универсального объекта, у вас есть полный доступ к API, созданным с помощью enigma.js. Эти API-интерфейсы генерируются из схемы JSON-RPC и раскрывают всю мощь Associate Engine Qlik.

useModel

useModelвозвращает сгенерированный API Generic Object :

import { useModel } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const model = useModel();
      model.getInfo().then((info) => {
        console.log(info);
      });
    },
  };
}

Общие операции в этом API:

  • делать выбор с помощью beginSelections,  selectHyperCubeValues и endSelections
  • получить больше данных с getHyperCubeData

useApp

useAppвозвращает сгенерированный API Doc:

import { useApp } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const app = useApp();
      app.clearAll();
    },
  };
}

Общие операции в этом API:

  • изменять стек выбора с clearAll,  back,forward
  • создавать и применять закладки с помощью createBookmark и applyBookmark

useGlobal

useGlobalвозвращает сгенерированный API Global :

import { useGlobal } from '@nebula.js/stardust';

export default function () {
  return {
    component() {
      const g = useGlobal();
      g.engineVersion().then((v) => {
        console.log(v);
      });
    },
  };
}

Общие операции в этом API:

  • получить список приложений с getDocList

HyperCube introduction. Введение в HyperCube

Это HyperCubeDefфундаментальная структура, которую вы настраиваете, прежде чем вам будет предоставлен результат в виде файла HyperCube. Не позволяйте имени пугать вас, хотя оно содержит множество свойств и может быть настроено разными способами, в своей основной форме оно напоминает простую таблицу со строками и столбцами.

Конфигурация HyperCubeDef

Не все свойства одинаково важны, и есть несколько ключевых, о которых нужно помнить при настройке HyperCubeDef.

qMode

Хотя вам может не потребоваться qModeявно устанавливать, поскольку по умолчанию используется простейший режим 'S', важно знать, какое влияние он оказывает на структуру данных.

qMode: 'P', или режим сводной таблицы, дает вам структуру, подходящую для представления сводных таблиц с группами как в вертикальном, так и в горизонтальном направлениях, а также группы для всех показателей.

qMode: 'T', или древовидный режим , дает вам структуру, напоминающую дерево и подходящую для визуализации древовидных визуализаций; древовидная карта, упаковка кругов, солнечные лучи, дендрограмма, решётка и т. д.

qMode: 'S', или прямой режим , является самым простым из них и дает вам структуру данных, которая выглядит как простая таблица со строками и столбцами. Для простоты объяснения остальной части гиперкуба можно предположить, что он используется.

qDimensions и qMeasures

qDimensionsи qMeasuresявляются столбцами вашей «таблицы», нет явного ограничения на их количество, которое вы можете добавить, но часто существует ограничение на количество измерений и мер, которые может обрабатывать определенная диаграмма, и вам нужно сохранить это количество из них в виду, когда вы укажете qInitialDataFetch.

qInitialDataFetch

Ассоциативный движок Qlik – это решение на основе памяти, что означает, что объем данных, которые он может обрабатывать, полностью зависит от ресурсов памяти, к которым у него есть доступ. Таким образом, он может содержать миллиарды значений данных, и поэтому количество строк в гиперкубе также потенциально может достигать миллиардов.

Чтобы избежать случаев, когда такие огромные объемы данных передаются в интерфейсную часть, гиперкуб по умолчанию вообще не включает никаких строк. Чтобы контролировать это, вы можете установить количество строк и столбцов, которое вы хотите изначально qInitialDataFetch. Это свойство позволяет вам установить страницы данных, которые вы хотите извлечь из всего гиперкуба, поэтому вы можете, например, выбрать получение первых 50 строк:

qHyperCubeDef: {
  qInitialDataFetch: [{ qLeft: 0, qTop: 0, qHeight: 50, qWidth: 4 }];
}

Если вы думаете о прямой таблице как о сетке, из которой вы хотите извлечь некоторые данные, тогда qLeftи qTop– это верхний левый угол подмножества, которое вы хотите извлечь, а qHeightи qWidth– количество строк и столбцов.

Однако существует максимальный предел в 10 000 ячеек, которые вы можете извлечь за один раз, и это количество вызывает ошибку. Поэтому вам нужно следить за количеством столбцов может потребоваться для обеспечения общей не превышает 10 000. Если вы, например , знаете , что вы никогда не нужно больше , чем 4 колонки, то вы можете установить qHeightна 10000/4:

qInitialDataFetch: [{ qLeft: 0, qTop: 0, qHeight: 2500, qWidth: 4 }];

Первоначальная выборка данных указывает только самую большую возможную часть всего гиперкуба в макете, если в гиперкубе всего 7 строк, вы не получите больше 7. Вы также можете динамически получать больше данных позже.

Потребление HyperCube

Выход, или компоновка , из HyperCubeDefявляется гиперкубом . В макете он расположен в том же месте, что и вы определили в своих свойствах, но без Def, например ввода:

{
  properties: {
    qHyperCubeDef: {},
    another: {
      one: {
        qHyperCubeDef: {}
      }
    }
  }
}

приводит к выводу:

{
  layout: {
    qHyperCube: {},
    another: {
      one: {
        qHyperCube: {}
      }
    }
  }
}

Рядом с qDimensionInfoи qMeasureInfoсвойствами , которые содержат ваши размеры и меры, наиболее важную часть гиперкуба являются страницы данных .

Страницы данных

На страницах данных содержатся фактические значения данных гиперкуба, где именно и какая структура они имеют, зависит от qModeзначения, которое вы установили ранее. Для режима 'S'это место qDataPages, которое, в свою очередь, содержит qAreaи qMatrix.

Предполагая, что гиперкуб содержит одно измерение, название фильма , и одну меру, средний рейтинг , содержимое может выглядеть следующим образом:

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 },
  },
];

Помимо текстовых и числовых значений, каждая ячейка NxCell содержит qElemNumberсвойство, известное как ранг . Ранг для ячейки измерения можно рассматривать как свойство, которое однозначно идентифицирует текстовое значение этой ячейки в своем поле во всей модели данных. Вы можете использовать это свойство для обеспечения единообразного поведения во всем приложении, вы можете, например, установить постоянный цвет значений измерения в поле, когда и где бы они ни использовались:

// color scheme
const colors = ['#26A0A7', '#79D69F', '#F9EC86', '#EC983D'];

const cellColor = colors[cell.qElemNumber % colors.length];

Это свойство также необходимо отслеживать, когда вы хотите сделать выбор в своей диаграмме.

Получение дополнительных данных

Из-за ограничения объема данных, которые вы можете получить в исходном макете, могут возникнуть ситуации, когда вам потребуется получить остальные данные, если вы хотите отобразить их больше. Вы можете сделать это с помощью методов, представленных в модели универсального объекта. Какой метод использовать, опять же, зависит qModeот гиперкуба, для 'S'режима это GetHyperCubeData .

При подкачке данных в прямом режиме вы должны начать с просмотра qHyperCubeDef.qSizeсвойства, которое содержит информацию о ширине и высоте полного гиперкуба. Исходя из этого, вы можете рассчитать количество страниц, которые вам нужно получить:

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(() => {
    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 < NUM_PAGES; i++) {
      pagesToFetch.push({ qLeft: 0, qTop: i * HEIGHT_PER_PAGE, qHeight: HEIGHT_PER_PAGE, qWidth: X });
    }

    Promise.all(pagesToFetch.map((page) => model.getHyperCubeData('/qHyperCubeDef', [page]))).then((pages) => {
      console.log(pages);
    });
  }, [layout]);

}

Однако вы должны быть очень осторожны при динамической выборке таких данных, имейте в виду, что размер куба может исчисляться миллионами, выборка такого большого набора данных может занять время и создать очень плохое взаимодействие с пользователем. В предыдущем примере максимальное количество страниц установлено равным 10, так что всего выбирается не более 100 000 значений.

Вы также можете использовать другие методы, чтобы не получать все данные сразу. Виртуальная прокрутка в сочетании с регулированием каждого запроса может значительно повысить производительность. Вам также следует рассмотреть возможность использования сокращенного набора данных, если вам не нужны точные значения:

  • getHyperCubeBinnedData связывает точки данных в группы и отлично подходит для тепловых карт и 2D-графиков плотности.
  • getHyperCubeContinuousData уменьшает количество точек в непрерывном измерении и отлично подходит для временных данных.
  • getHyperCubeReducedData выполняет некоторую магию вейвлетов и отлично подходит для мини-диаграмм.

Selecting data. Выбор данных

Выборка – это фундаментальная часть ассоциативного механизма Qlik. Все поля и связи между ними содержатся в ассоциативной модели. Когда вы применяете выбор, вы не только применяете фильтр в модели данных, но также демонстрируете связи между вашими источниками данных.

Applying selections. Применение выделений

Выборки можно применять с помощью методов, представленных в модели, возвращенной из useModelхука.

Поскольку универсальный объект может содержать несколько гиперкубов, вам всегда нужно указать, какой гиперкуб вы хотите выбрать, указав его путь JSON в качестве первого аргумента:

import { useModel } from '@nebula.js/stardust';
// ...
component() {
  const model = useModel();

  useEffect(() => {
    model.selectHyperCubeCells('/qHyperCubeDef', [1], []);
  }, [model])
}

Шаблоны выбора. Selection patterns

Есть два разных шаблона выбора: мгновенный и модальный.

Мгновенный выбор. Instant selections

Как видно из названия, этот тип шаблона является немедленным и фильтрует как источник выбора, так и все, на что он влияет.

В следующем примере, как только значение выбрано на гистограмме, фильтрация применяется мгновенно, и обе диаграммы немедленно обновляются отфильтрованными данными:

Когда инициируется модальный выбор, источник выбора входит в форму модального состояния, которое позволяет пользователю изменять выбор до подтверждения изменений.

В следующем примере пользователь сначала выбирает одно значение на линейчатой ​​диаграмме, после чего другие диаграммы обновляются, как и раньше. Однако гистограмма по-прежнему содержит все доступные данные и позволяет пользователю выбрать другое значение перед подтверждением изменений и обновлением самой гистограммы:

Чтобы реализовать этот тип паттерна, вам необходимо выполнить несколько простых шагов useSelectionsв сочетании с useModelними:

  1. Войдите в модальное состояние, позвонив beginSelections.
  2. Выберите значения.
  3. Обеспечьте визуальную обратную связь с пользователем о том, что было выбрано, например, изменив прозрачность выбранных значений.
  4. Следите за выходом из модального состояния, чтобы сбросить визуальную обратную связь.
import { useModel, useSelections, useElement } from '@nebula.js/stardust';
// ...
component() {
  const element = useElement();
  const model = useModel();
  const selections = useSelections();

  useEffect(() => {
    const clicked = () => {
      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 () => {
      element.removeEventListener('click', clicked);
    }
  }, [element, model, selections]);

  useEffect(() => {
    if (layout.qSelectionInfo.qInSelections) {
      // 3. update with visual feedback on active selections
      // YOUR CODE HERE
    } else {
      // 4. normal update
      // YOUR CODE HERE
    }
  }, [layout]);
}

 

4.5 2 голосов
Рейтинг статьи

Подписаться
Уведомление о
guest
0 комментариев
Встроенная Обратная Связь
Просмотр всех комментариев
0
Оставьте, пожалуйста, комментарий!x