Группировка элементов данных

Какие группировки бывают

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

Обязательная группировка

Группировка является неотъемлемой частью компонентов с иерархическими данными (которые, однако, можно наполнить и линейными данными).

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

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

Необязательная группировка

Данные можно группировать по определённому критерию.

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

Статичная/изначальная группировка

Критерий для группировки задаётся при инициализации компонента. За это отвечает ключ $group у объекта scheme. Это необходимо для компонентов с обязательной группировкой.

webix.ui({
    view:"tree",
    scheme:{
        $group:"year"
    }
});

Related sample:  Tree: Plain JSON Data with Client-side Grouping

Динамическая группировка

Группировка определяется с помощью функции, которая затем применяется к компоненту.

$$("mytree").group("year");

Чтобы отменить группировку, используйте метод ungroup.

$$("mychart").ungroup();

Как указать шаблон группировки

Синтаксис методы group() и свойства $group один и тот же - вам необходимо указать критерий группировки следующим образом:

  • элемент данных;
  • функция;
  • объект.

Элемент данных

Строка, которая указывает на свойство набора данных:

// статичный режим
var tree = webix.ui({
    view:"tree",
    scheme:{
        $group:"year"
    }
});
 
// динамический режим
tree.group("title");

Функция

Функция, которая применяется к объекту данных и возвращает критерии группировки:

scheme:{
    $group:function(obj){
        return obj.year/* + ..*/;
    }
}

Related sample:  List: Grouping

Объект

Объект со свойствами, которые определяют критерий и шаблон группировки:

  • by (обязательно) - задаёт критерий группировки как строку или функцию.
  • map - объект, который переопределяет значения для текущего темплейта. Здесь к элементам группировки применяются математические функторы.
  • missing (boolean, string) - определяет группировку хедеров, которые возвращают ""/null/false/undefined. Возможные значения:
    • true (по умолчанию) - недостающие значения добавляются после групповых,
    • false - игнорирует недостающие значения,
    • string - создаёт группу для недостающих значений или, если строка является именем для какой-либо уже существующей группы, добавляет их в эту группу.
  • footer (для treetable) - определяет темплейт для дополнительный строки таблицы, которая показывает общее свойство для элементов группы.
  • row (для datatable и treetable) - определяет темплейт для всего ряда вне зависимости от изначальных столбцов.
// статичный режим
webix.ui({
    view:"chart",
    scheme:{
        $group:{
            by:"year",
            map:{/* ... */}
        }
    }
});
 
// динамический режим
grida.group({
    by:"year",
    map:{/* ... */}
});

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

$group:"year"
 
$group: function(obj){ return obj.year;}
 
$group:{ by:"year" }
 
$group:{
    by: function(obj){ return obj.year }
}

Функция может быть любого уровня сложности:

by: function(obj){ return Math.floor(obj.year/10); }

Related sample:  Static Grouping

Функторы группировки

Функторы группировки используются внутри map и footer, которые переопределяют темплейт.

$group:{
    by:"year",
    map:{
        property(template):['property', functor]
    }   // или свойство:[function (obj){...}]
}

Какие бывают функторы группировки:

  • any - показывает все значения этого свойства; тот же самое, если вы не укажите функтор вообще.
  • sum - складывает значения и показывает результат;
  • max - выбирает наибольшее значение свойства;
  • min - выбирает наименьшее значение свойства;
  • count - считает количество элементов каждой группы;
  • string - показывает имя свойства как строку. В случае с {year:1994}, слово "year" будет показано в компоненте;
  • пользофательский функтор - для других математических операций.

Читайте подробнее о функторах группировки.

Группировка недостающих значений

Если ваши данных содержат элементы данных с недостающими значениями ("", null, false или undefined), и вы группируете по этому значению, то для таких случаем существует несколько опций:

  • (по умолчанию) показывать записи с недостающими значениями после сгруппированных записей
$$("grid").group({
    by:"year",
    row:"title",
    missing:true    // указывать необязательно; работает по умочланию
});
  • спрятать записи с недостающими значениями
$$("grid").group({
    by:"year",
    row:"title",
    missing:false
});
  • создать отдельную группу для записей с недостающими значениями
$$("grid").group({
    by:"year",
    row:"title",
    missing:"Other"
});

Если имя группы совпадает с именем другой группы (которая уже существует), записи с недостающими значениями добавятся в уже существующую группу.

Related sample:  Treetable: Grouping for Missed Items

Темплейты для групп и элементов

По умолчанию, элементы компонента показывают объект value, который есть:

  • свойство value источника данных;
  • значение из данных, заданное через темплейт;
  • значение любого элемента массива (если данные приходят в JSArray);

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

webix.ui({
    view:"tree",
    scheme:{
        $group:{
            by:"year" // значение группового хедера
        }
    },
    data: [  // значение по умолчанию
        { id:1, value:"The Shawshank Redemption", year:1994,
            votes:678790, rating:9.2, rank:1},
        {/* ... */}
    ]
});

Related sample:  Tree: Plain JSON Data with Client-side Grouping

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

webix.ui({
    view:"tree",
    template:'{common.icon()} {common.folder()}#title#',
    scheme:{
        $group:{
            by:"year",
            map:{
                title:["year", "any"]
            }
        }
    }
});

По умолчанию, темплейт показывает только title. map подменяет групповой title на year и отображает "year".

Говоря о группировке элементов, у каждого компонента есть свои особенности темплейтов, которых мы коснёмся дальше. Также вы можете изменить отображаемые данные, описав функцию для события onGroupCreated.

Особенности DataTable и TreeTable

Для DataTable и TreeTable темплейты указываются через ID столбцов, темлейтов столбцов или и того, и другого.

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

С помощью map можно переопределить более одного свойства.

map:{
    votes:["votes", "sum"], // сложит значения "votes" 
    title:["year"] // title возьмёт значения year 
}

Related sample:  Data Grouping: Aggregate Values

Темлейты-функции позволяют задавать разные варианты показа групповых элементов и групповых хедеров.

  • obj.$group - хранит состояние элемента (вне зависимости от того, элемент это или хедер).
  • obj.$level - хранит уровень иерархии (верхний равен '1').

У обоих сниппетов один результат:

template: function(){
    if(obj.$group) return /* ... */; // для хедеров групп
    return /* ... */ // для элементов групп
}
 
 
template: function(){
    if (obj.$level==1) return /* ... */; // для хедеров групп
    return /* ... */ // для элементов групп
}

treetable с указанным свойством map:

columns:[
    {
        id:"title", template:function(obj, common){
            if (obj.$group)
                return common.treetable(obj, common) + obj.title;
            return obj.title;
        }
    }
],
scheme: {
    $group:{
        by: "year",
        map:{
            title:["year"] // year это 'obj.title' для групповых хедеров
        }
    }
}

Related sample:  Data Grouping: Aggregate Values

treetable без свойства map:

columns:[
    {
        id:"title", template:function(obj, common){
            if (obj.$level == 1)
                return common.treetable(obj, common) + obj.value;
            return obj.title;
        }
    }
],
scheme:{
    $group:"year" // year это obj.value для группового хедера
}

Related sample:  Static Grouping

Темплейты для рядов и дополнительные ряды

Темплейт для ряда

Свойство row внутри объекта группировки задаёт темплейт дял группового хедера для всего ряда вне зависимости от столбцов.

grida.group({
    by:"year",
    map:{
        "year":["year",  "any"],
        "votes":["votes", "sum"]
    },
    row:function(obj, common){
        return "Year "+obj.year+", total votes: "+webix.i18n.numberFormat(obj.votes);
    }
});

Related sample:  Data Aggregation in Custom Format

Групповой футер

Групповой футер показывает общее значение для всех элементов группы (общую сумму, мин/макс. значение и пр.).

Футеры определяются так же, как и map, и включают в себя выбранные свойства, которые обрабатываются функторами, и темплейт для отображения данных.

grida.group({
    by:/* ... */,
    map:{/* ... */},
    footer:{
        votes:["votes", "sum"],
        row:function(obj, common){
            return "<span style='float:right;'>Total: "
            +webix.i18n.numberFormat(obj.votes)+"</span>"
        }
    }
});

Related sample:  Dynamic Grouping: Extra Lines

Особенности Chart

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

  • Значения оси X отображают критерий группировки (представленный в by);
  • Значения оси Y отображают выбранные значения, которые работают с функтором.

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

webix.ui({
    view:"chart",
    value:"#sales#", // исходный темплейт для Y-axis
    scheme:{
        $group({
            by:"company", // темплейт для X-axis
            map:{
                sales:["sales","sum"]
            } // темплейт Y-axis показывает сумму всех зарплат за каждый год
        });
    }
});

Related sample:  Grouping

Первый элемент в map - это свойство элемента данных, второй - функтор, который применяется ко всем значениям этого свойства.

Особенности GroupList

У GroupList свои свойства:

  • templateItem - задаёт темплейт для элементов группы;
  • templateGroup/templateBack - задаёт темплейт для хедера группы.

Более подробно читайте в статье о GroupList.

Группировка по нескольким значениям

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

Treetable

Чтобы сгруппировать Treetable по нескольким столбцам, вызовите метод group() ещё раз и передайте в него ID ветки для группировки в качестве второго параметра:

// первая группировка
grida.group({
    by:function(obj){ return obj.unitName + "-" + obj.tagName },
    map:{
        value:["unitName"],
        tagName:["tagName"],
        samples:["samples","sum"]
    }
});
 
// вторая группировка
grida.group({
    by:"tagName",
    map:{
        value:["tagName"],
        unitName:["unitName"],
        samples:["samples","sum"]
    }
}, 0);

Related sample:  Treetable: Multiple Grouping

Datatable

Чтобы сгруппировать Datatable по нескольким столбцам, в метод group() передайте true вторым параметром:

grida.group({
    by:function(obj){ return obj.unitName + "-" + obj.tagName },
    map:{
        value:["unitName"],
        tagName:["tagName"],
        samples:["samples","sum"]
    }
});
 
grida.group({
    by:"tagName",
    map:{
        value:["tagName"],
        unitName:["unitName"],
        samples:["samples","sum"]
    }
}, true);

События группировки

  • onGroupCreated - срабатывает при группировке и принимает следующие параметры:
    • id - ID хедера группы (родительская ветка);
    • value - значение критерия группировки;
    • data - объект компонента данных;
  • onGroupFooter - срабатывает при группироке (если определён футер).
webix.ui({
    view:"treetable",
    on:{
        "data->onGroupCreated":function(id, value, data){
            this.item(id).value = "Year "+value;
        }
    }
});
 
grida.group({
    by:"year" //obj.value = year
});

Related sample:  Handling Events while Data Grouping

Наверх