1.1.0 • Published 2 years ago

mmtabler v1.1.0

Weekly downloads
-
License
-
Repository
github
Last release
2 years ago

MMTabler Component

Content: 1. About 2. Usage 3. Implementation 4. Warnings in MMTabler 5. Changes in the versions 6. Author 7. Final notes


1. About

MMTabler is a ready-made Angular component for handling the tabelar display of data. It is easy to use, responsive, flexible and highly customizable.

Read Usage for detailed explanation, or skip to Implementation for jumping right into it.

It is made to be dynamic and dumb: it requires few inputs from the parent component (with more optional inputs) and will handle few variables by itself, returning just one to parent - although you can opt not to emit anything to parent.

Among many options you can set, there are options to use custom headers, reorder them or remove some - whatever your original table data actually is; to allow editing, deleting or adding table entries; you can also easily customize its DOM elements, since all elements (static or dynamic) are generated with ids, so you can access them simply by getElementById (see Customizing MMTabler elements further below). Default css variables are also provided for insertion into global css file, but feel free to check the component's css classes too.

MMTabler is meant to display one-dimensional (not nested) array of objects, where each object is a table's row entry. If you want to display nested data, MMTabler is not for you.

See it in action: MMTabler at Stackblitz

Note: linked project has some extra code (not inherent to MMTabler) just to show it in the context: it uses MMPaginator to browse through table data. Read further for details on what's actually important for the MMTabler.


2. Usage

2.1. Table data: format and passing to MMTabler

  • Data passed to MMTabler should be in the form of an array of simple non-nested objects, for example:

    yourDataVariable = [
      {
        id: "Entry 1",
        tag: "1st entry's tag",
        comment: "Displays the details of the first entry"
        (...)
      },
      {
        id: "Entry 2",
        tag: "2nd entry's tag",
        comment: "Displays the details of the second entry"
        (...)
      }
      ,
      (...)
    ]
  • The keys of the first object (entry) will be used by default as the headers of the table. See further below (in explanation of configuration options) about customizing the headers' content and display.

  • Pass the data to data @Input of the tabler via the template:

    [data]="yourDataVariable"

  • MMTabler will display a warning message (instead of the content in template) if data is not passed. However, it will not check if the data is of the right format.

2.2. MMTabler to parent communication

  • MMTabler will use the data to populate the table and if you want to allow editing and/or deleting and/or adding entries via MMTabler and have the data updated, you have to create a method getVariablesFromTabler() in parent to accept emitted changes from the MMTabler like:

    getVariablesFromTabler(data: any) {
       this.data = data;
    }
  • Create a getVariablesFromTabler() method in parent and send it to paginator's @Output like:

    (sendChangesToParent)="getVariablesFromTabler($event)"

  • If you don't want to allow these options (editing, deleting, adding) - you don't need to! Also, you can opt to allow these options only for displaying purposes, without keeping any of the changes (without modifying the data variable). Just see about configuration further below.

2.3. Displaying the data entries

  • To tell MMTabler how many entries (rows of data) to display, you need to initialize a variable with a value of entries to show, like:

    yourChoiceOfTotalNumberOfEntriesToShow: number = 30

    or if you want to keep it dynamic - if your data is coming from the subscription that can change - and display all the entries at once:

    yourChoiceOfTotalNumberOfEntriesToShow = yourDataVariable.length

  • To pass the number of entries per page to entriesToShow @Input of the tabler:

    [entriesToShow]="yourChoiceOfTotalNumberOfEntriesToShow"

  • If you want to add a paginator option to MMTabler (to handle displaying different entries while keeping the same number of them displayed), you'd need to write your own paginator logic, use some other paginator package/library or just install MMPaginator - MMTabler fits perfectly with it!

Get MMPaginator: MMPaginator at npmjs.com

2.4. Keeping track of active page

  • To keep track of active page (when using any form of pagination), you need to initialize the variable, for example:

    currentlyActivePage: number = 1

  • Pass the currentlyActivePage to activePage @Input of the tabler via the template:

    [activePage]="currentlyActivePage"

  • The MMTabler will use this value combined with entriesToShow to render the entries that fall into the specified range to display. If you're using MMPaginator, the parent component will pass the same activePage variable to both packages and MMTabler and MMPaginator will work seamlessly.

  • If you chose to display all the entries at once (without the need for pagination) by setting entriesToShow to the length of your data, you can keep the activePage at 1 throughout the lifecycle of your app. However, due to keeping the option to link MMTabler with any pagination system, you still have to pass the activePage to it.

2.5. Configuring the MMTabler options

  • MMTabler comes with a range of options, simple to set up and use for handling various aspects of the table display. You initialize the configuration object like:

    configuration = { + your choice of options + }

    and for allowed options you have:

    OptionMandatory?DescriptionExample
    customHeadersno, but must be used together with displayHeadersFromCustomHeadersused to set new headers (as strings), instead of keys from the first object in dataset new headers by using existing keys of your data objects as keys, and give them values of your new headers, i.e. if you used the example from above, where your data objects have keys as: id, tag and comment, set it like: customHeaders: { id: 'Header 1', tag: 'Ha, tag!', comment: 'Co mm ent' }
    customHeadersOrderno, but must be used together with displayHeadersFromCustomHeaders and customHeadersused to set new headers order (as strings) from customHeadersset new headers order by using any of the existing values in your customHeaders object, i.e. if you used the example from above, where your customHeaders object is as: { id: 'Header 1', tag: 'Ha, tag!', comment: 'Co mm ent' } you can set customHeadersOrder like: customHeadersOrder: 'Ha, tag!', 'Co mm ent', 'Header 1' or even decide not to display some headers, like: customHeadersOrder: 'Ha, tag!', 'Header 1'
    displayHeadersFromDatano, but then you'd have to use displayHeadersFromCustomHeadersif set to true, MMTabler will use keys from the first object in your data as headers for table. If set to false, you have to set displayHeadersFromCustomHeaders to trueYou must bave either displayHeadersFromData or displayHeadersFromCustomHeaders set to true!displayHeadersFromData: true
    displayHeadersFromCustomHeadersno, but must be used together with customHeadersused to tell MMTabler if it should use the customHeaders (above) for table headers.If you are not using customHeaders, you can omit this option, but you must have displayHeadersFromData set to trueto use the headers defined as in customHeaders above, set it to true: displayHeadersFromData: true
    headersToUppercasenoif set to true, MMTabler will display headers in ALL CAPS. If set to false or omitted, this change won't be applied.You can have only one of these options set to true: headersToUppercase, headersToCapitalized, headersToLowercaseheadersToUppercase: true
    headersToCapitalizednoif set to true, MMTabler will display headers with first of the header letter capitalized, and all others in lowercase. If set to false or omitted, this change won't be applied.You can have only one of these options set to true: headersToUppercase, headersToCapitalized, headersToLowercaseheadersToCapitalized: false
    headersToLowercasenoif set to true, MMTabler will display headers in lowercase. If set to false or omitted, this change won't be applied.You can have only one of these options set to true: headersToUppercase, headersToCapitalized, headersToLowercaseheadersToLowercase: false
    initialOrderBynosets which header to use for initial sorting of the table data. The sorting will be initialized in ascending orderinitialOrderBy: 'id'
    allowOptionsnoIf set to true, MMTabler will expect to have at least one of the next 3 options set to true too. If set to false or omitted, next 3 options can be omitted too.allowOptions: true
    allowEditno, but must be used together with allowOptionsif set to true, you will get a popover with 'Edit' option when clicking on a table row.allowEdit: true
    allowDeleteno, but must be used together with allowOptionsif set to true, you will get a popover with 'Delete' option when clicking on a table row.allowDelete: true
    allowAddno, but must be used together with allowOptionsif set to true, you will get a popover with 'Add' (new) option when clicking on a table row.allowAdd: true
    txtEditnocustom text for 'Edit' button; makes sense only if allowEdit is set to truetxtEdit: 'Izmeni'
    txtDeletenocustom text for 'Delete' button; makes sense only if allowDelete is set to truetxtDelete: 'Obriši'
    txtAddnocustom text for 'Add' button; makes sense only if allowAdd is set to truetxtAdd: 'Dodaj'
    txtCancelnocustom text for 'Cancel' button; makes sense only if any of the 3 options above (allowEdit, allowDelete, allowAdd) is set to truetxtCancel: 'Odustani'
    txtConfirmDeletenocustom text for 'Do you really want to delete this entry?' text; makes sense only if allowDelete is set to truetxtConfirmDelete: 'Želiš li zaista da obrišeš ovaj sadržaj?'
    sendChangesnoused to emit to parent the changes in data entries; makes sense only if options to 'edit', 'delete' or 'add' are set to true.If used, you need to set getVariablesFromTabler() method in parent, toosendChanges: true
  • So the configuration object might look something like this, for example:

    configuration = {
      displayHeadersFromData: true,
      headersToCapitalized: true,
      allowOptions: true,
      allowEdit: true,
      sendChanges: true
    }

2.6. CSS details and accessing elements' properties

  • MMTabler has its own css classes, but they depend on variables that you'll use in your global css styles file. You can change the colours, border, shadows etc. by changing the variables' values. Read Implementation for how to use them.

  • All DOM elements of the MMTabler have their distinctive IDs, so if you need you can easily access any of them by getElementById. This documentation file is already rather long, so for the list of available IDs you should just look at the source of html once you install the MMTabler.


3. Implementation

3.1. Customizing MMTabler elements

  • You can (and should) edit your global .css file (styles.css in web app, or global.css in your Ionic mobile app) by adding the following css code and edit it further to suit your design preferences:
:root {
  /* MMTabler variables */
  --table-border: 1px solid rgb(0, 0, 0);
  /* headers */
  --header-text-font-size: 13px;
  --header-text-font-color: rgb(0, 0, 0);
  --header-background-color: rgb(177, 220, 255);
  --header-border-bottom-color: rgb(57, 117, 145);
  /* rows */
  --row-text-font-size: 12px;
  --row-text-font-color: rgb(0, 0, 0);
  --row-background-color: rgb(255, 255, 255);
  --row-background-color-nth-child: rgb(235, 245, 255);
  --row-hover-background-color: rgb(203, 232, 255);
  /* sorting icons */
  --sorting-icons-font-size: 14px;
  --sorting-icons-font-color: rgb(0, 0, 0);
  /* warning messages */
  --warning-background-color: rgb(209, 74, 74);
  --warning-font-color: rgb(255, 255, 255);
  --warning-font-size: 12px;
  /* options popover */
  --options-container-background-color: rgb(255, 255, 255);
  --options-container-border: 1px solid rgb(0, 0, 0);
  --options-button-close-color: rgb(111, 174, 216);
  --options-button-close-color-hover: rgb(0, 0, 0);
  --options-button-close-size: 13px;
  --options-pointer-color: rgb(0, 0, 0);
  /* options buttons */
  --buttons-background-color: rgb(235, 245, 255);
  --buttons-font-size: 13px;
  --buttons-border: 1px solid rgb(0, 0, 0);
  --buttons-font-color: rgb(0, 0, 0);
  --buttons-background-color-hover: rgb(203, 232, 255);
  --buttons-background-color-selected: rgb(177, 220, 255);
  /* single option */
  --option-title-font-size: 13px;
  --option-subtitle-font-size: 11px;
  --option-key-font-size: 13px;
  --option-key-font-color: rgb(0, 0, 0);
  --option-border: 1px solid rgb(0, 0, 0);
  --option-background-color: rgb(255, 255, 255);
  --option-single-background-color: rgb(235, 245, 255);
  --textarea-background-color: rgb(255, 255, 255);
  --textarea-font-color: rgb(0, 0, 0);
  --textarea-font-size: 13px;
  /* general typing */
  --fonts: Verdana, Arial, Tahoma, Serif;
  /* styling */
  --border-radius: 8px;
  --border-thin-dark: 1px solid rgba(0, 0, 0);
  --box-shadow: 0px 2px 10px 2px rgb(212, 212, 212);
}
  • If you already have variables defined in your root, just paste there the values after / MMTabler variables / comment and before the last bracket.

  • IDs of the individual elements are too long to list, but they all start with mmtabler- so it's easy to find them. Access them easily by document.getElementById(theIDyouWant)

3.2. Parent component and modules

3.2.1. Importing the library module

  • Import the paginator:

    import { MMTablerModule } from 'mmtabler';

  • Add it to imports:

    imports: [ MMTablerModule ]

3.2.2. Changes in parent's .ts file

  • Initialize the variables you'll send to MMTabler (read Usage above, to see about possible differences in handling the variables):

      data: any[] = []; // or however you name your data var
      activePage: number = 1; // or however you name your active page var
      entriesToShow: number = 5; // or however you name your entries per page var; min 1, max == data.length
  • Set configuration details, initilize them Like this (see Usage above for details, this is an example that uses all options):

    configuration = {
      // custom table headers
      customHeaders: { id: 'HeaDer', name: 'ANOTHER ONE', tag: 'thiRD' },
      // custom order of headers
      customHeadersOrder: ['thiRD', 'HeaDer'],
      // handling table headers content
      displayHeadersFromData: false,
      displayHeadersFromCustomHeaders: true,
      // handlig display of headers text
      headersToUppercase: false, // optional
      headersToCapitalized: true, // optional
      headersToLowercase: false, // optional
      // sorting details
      initialOrderBy: 'Header 1', // initial key (header name) to sort by
      allowOptions: true, // allowing edit, delete, add options on table
      allowEdit: true, // allow edit option
      allowDelete: true, // alow delete option
      allowAdd: true, // allow add option
      // text
      txtEdit: 'Edit 1', // text for 'Edit' button
      txtDelete: 'Delete 2', // text for 'Delete' button
      txtAdd: 'Add 3', // text for 'Add' button
      txtCancel: 'Cancel 4', // text for 'Cancel' button
      txtConfirmDelete: 'Do you really really really want to delete this entry?', // text for 'Are you sure you want to delete this entry?' text
      // if MMTabler is allowed to send changed data back to parent
      sendChanges: true,
    };

    Of course, strings like 'Header 1', 'Delete 2' etc are here as an example: use any string you want.

  • Use this method to receive value emitted from MMTabler (if you're going to use edit, delete or add options):

      getVariablesFromTabler(data: any) {
          this.data = data; // instead of 'this.data' you should use your own data var, like 'this.myDataArray
      }

3.2.1. Changes in parent's template / html

  • Paste this block of code into your html where you want the MMTabler to appear:

    <mm-tabler
      [data]="data"
      [activePage]="activePage"
      [entriesToShow]="entriesToShow"
      [configuration]="configuration"
      (sendChangesToParent)="getVariablesFromTabler($event)"
    ></mm-tabler>
  • Keep in mind: activePage and entriesToShow can be used in your own pagination code, but they fit perfectly with MMPaginator package too - so if you use the MMPaginator, you can just paste its code under this block.


4. Warnings in MMTabler

  • MMTabler has several warning messages that it'll display instead of the (expected) content if you don't pass it the values in right format or if there are mismatches.

  • If you didn't pass the data for table:

    DATA MISSINGYou didn't provide any data for the table content. Please pass some data to data input.

  • If you didn't pass the activePage value:

    DATA MISSINGYou didn't provide activePage (as number) to the table. Please pass some value to activePage input.

  • If you didn't pass entriesToShow value:

    DATA MISSINGYou didn't provide (number of) entriesToShow to the table. Please pass some value to entriesToShow input.

  • If you wanted you use custom headers, but you didn't set them in configuration:

    HEADERS MISSINGYour setting in configuration sets 'displayHeadersFromDataHeaders' to 'true', but you haven't supplied 'customHeaders' to take headers from!

  • If you set allowOptions to true but forgot to set any of the individual options (edit, delete, add) to true:

    OPTIONS MISSINGYour setting in configuration sets 'allowOptions' to 'true', but you haven't supplied any particular option as 'true' (allowEdit, allowDelete or allowAdd).

  • If you set configuration to use both the headers from data and the headers from customHeaders:

    HEADERS COLLISIONYour setting in configuration sets both 'displayHeadersFromData' and 'displayHeadersFromCustomHeaders' to 'true', but you can only have one of those options set to 'true'.

  • If you accidentally set configuration to use all three possible css displays of headers:

    HEADERS STYLES COLLISIONYour setting in configuration sets 'headersToUppercase', 'headersToCapitalized' and 'headersToLowercase' to 'true', but you can have only one of those set to 'true'.

  • If you accidentally set configuration to use two of the possible css displays of headers:

    HEADERS STYLES COLLISIONYour setting in configuration sets two of these options to 'true': 'headersToUppercase', 'headersToCapitalized' or 'headersToLowercase', but you can have only one of those set to 'true'.

  • If you wanted to use custom headers and order it initially, but you set the wrong (non-existent) header name in initialOrderBy:

    HEADERS MISMATCHYour setting in configuration sets 'displayHeadersFromCustomHeaders' to 'true', but the value you passed for 'initialOrderBy' is not included in your 'customHeaders'. Check the values for typos

  • If you didn't pass configuration value to MMTabler at all:

    CONFIGURATION MISSINGYou did not provide configuration for the MMTable. Please check the documentation.

  • If you wanted to emit changes from MMTabler to parent, but forgot to pass it a method for emitter:

    DATA UPDATE ISSUEYou set 'sendChanges' in configuration to emit data changes from MMTabler to parent, but you didn't pass 'sendChangesToParent' value/method to MMTabler. Please check the documentation.


5. Changes in the versions

For version: 1.1.0:

  • Removed one obsolete console.log (sorry... xD)
  • Added an option to change the order of table headers and/or display only some of them. Also added warnings if user's configuration values for this change are misconfigured.

5. Author

  • Author: Misha Mashina, March 2022.

  • Contact: misha.mashina@gmail.com


6. Final notes

Licence

You can use this component and its code freely, with or without changes, and as you see fit.

While this component is too simple to offer any room for errors/bugs, the responsibility for the effects of using it (modified or not) rests solely on you and not on the author.

A word on docs

The code is heavily commented. Feel free to delete the stuff, modify it, or just laugh at the author's obsession with documenting it all.


Enjoy!