GroupedList - globules-io/OGX.JS GitHub Wiki

GroupedList is a component to group a list of objects by the value of a common property and display groups in a nested fashion. This components only supports one level of grouping for now. It also supports sorting and binding.

Stack

Extends

 Uxi, Touch

Requires

 NestList, DynamicList, Templater, List

The stack for this component is GroupedList -> List -> NestList -> DynamicList

Basically, when you pass it an array of objects, it will transform it as a List, then use the group method, and finally prepare the configuration for the NestList which will use DynamicList to render the items.

OML

 {"selector:GroupedList":{CONFIFG}}

Config

 let config = {
      el:_SELECTOR_, //selector, required
      display:_OBJECT_, //display object, required
      list:_ARRAY_|_LIST_, //the data
      group_by:_STRING_, //The common property to group with
      group_mode:_STRING_,  //Optional, The optional operation (substr, numrange, date)
      group_param:*,  //Optional, The optional value to match to the result of the operation 
      group_order:_ARRAY_ //Optional, see ordering in OGX.NestList
 };

Create

As an OML node

 let OML = {};
 OML["#myDiv:GroupedList] = config;
 let list = OGX.OML.render(this, OML);

On the fly, at runtime from an Object extending Uxi

 let list = this.create('GroupedList', config);

Or independently

 let list = OGX.Object.create('GroupedList', config);

Data

To sort the list first by name descending, use

list.val().sort({name:-1});

To group a list of objects by price range, in groups of increment of $500

group_by:'price',
group_mode:'numrange',
group_param:500

numrange also supports symbols (for currencies), if you wish to use symbols and display the currency, do

group_param:[500, '$', 'pre'] //The last value is the position, either 'pre' or 'post'

To group a list of objects by date range, in groups of increment of 30 days, with a group dates format of YYYY-MM

group_by:'date',
group_mode:'date',
group_param:[30, 'YYYY-MM']

group_param for date accepts different types of grouping such as

group_param:'year'
group_param:'month'
group_param:'week'

If a numeric value for the interval in days is used instead, the format output is expected such as group_param:[30, 'YYYY-MM']

To group a list of objects by the 5 first letters of their respective name

group_by:'name',
group_mode:'substr',
group_param:[0, 5]

You can also update the grouping on the fly 1.28.0+

list.grouping('date', 'date', 'month');

Get/Set

 list.val(_ARRAY_); //Set data Array or List
 list.val(); //Get returns a List
 list.getNested(); //Get the NestList component used inside it

Enable/Disable

 list.enable();
 list.disable();

Group

 list.group(_GROUP_BY_, _GROUP_MODE_, _GROUP_PARAM_);

Filtering

GroupedList can be filtered using the same filters as List. it provides shortcut methods to the internal list.

list.addFilter(__property, __mode, __value);
list.removeFilter(__property, __mode, __value);
list.resetFilters();
list.getFilters();
list.filter();
list.unfilter();

Binding

GroupedList can be bound to other elements that can control the filtering of the list. It is possible to bind a common property of the objects of a list, to another HTML element or OGX.JS component.

list.bind(_OBJECT_);
list.unbind(_PROPERTY_);

In this example, we filter our list by matching the common property first_name via an input[type=text]. Every time the user inputs in this field, the list is going to be filtered and rendered

list.bind({property:'first_name', object:'#my_input', mode:'in'});

In this example, we filter our list by matching the common property price via an input[type=range] using the option 'lt' (lesser than) as a price limit

list.bind({property:'price', object:'#my_input', mode:'lt'});

MODE is the comparison mode or the filtering mode. To check out the supported modes, please refer to List under Filtering modes.

Group editing

All of the lists in the nests of NestList created by GroupedList are instances of DynamicList. So some of the methods are mirrored to edit the items of each list.

Add an item with auto grouping

 list.addItem(__item);

Remove an item with auto degrouping passing a prop/val search combo

 list.removeItem(__prop, __val);

Add an item to the list of a specific group

 list.addToGroup(__group, __item);

Remove item from specific group given a prop/val search combo

 list.removeFromGroup(__group, __prop, __val);

Remove all items from a specific group

 list.removeGroup(__group);

Update item from specific group given a prop/val search combo

 list.updateGroupItem(__group, __prop, __val, __obj);

Update a single item given a prop/val search combo. Group will be looked up

 list.updateItem(__prop, __val, __obj);

Replace item from specific group given a prop/val search combo

 list.replaceGroupItem(__group, __prop, __val, __item); 

Replace a single item given a prop/val search combo. Group will be looked up

 list.replaceItem(__prop, __val, __obj);

Get the DynamicList from a specific group

 list.getGroupList(__group);

Note that editing an item (either update or replace) will automatically change the item's group (or nest) if the value that the list is grouped by, is changed for the item. In other words, if your list is grouped by age and the updated or replaced item has a different value for age, then it will be removed from its current nest and added to the proper nest or create it if not existing.

Events

 OGX.GroupedList.SELECT

Refresh

To re-render the selected item, do

 list.refresh();

Destroy

 list.destroy();

Example

In this example, the component will display a list of emails, grouped by date

 let config = {
      el:'#mailbox', 
      group_by:'date', 
      sort:{unix:-1},
      group_mode:'daterange',
      group_param:'month', 
      key:'_id', 
      display:{template:'mail', css:'mail'},
      list:some_array
 };	

 let grouped = OGX.Object.create('GroupedList', config);

It is expecting a list of emails such as

 let arr = [{_id:'123', date:'2018-08-23', ...}, {...}]

Note that in this example, the component uses a 'mail' template and each email will also receive the 'mail' css class. So, additional properties are expected in the list of items, such as a title, sender, body etc. It all depends on the template you would be using. For more information, check out DynamicList.