Aditya Tyagi

2 POSTS 0 COMMENTS
Aditya - An avid learner striving to become a full-stack web developer He is a big-time web development enthusiast and bibliophile by nature and is striving to leverage the power of technology to build brilliantly designed products for EB.

Responsive Tables in Angular, Vue.js, React using Pure CSS

0
Responsive Data Tables

Being a front-end web developer is not easy. One thing that you have to do daily is to decide which framework/library you want to use for your components/segments in your project.

Note: If you are well aware of the concepts of Flexbox and Media Queries, you can clone the project here. 

There are two primary things that a front-end developer has to deal with:

  1. Data Manipulation
    Hitting the API’s, fetching the data and then manipulating data based on the requirements on the client side.
  2. Data Population
    Showing the manipulated data in a presentable manner

Correct data population can vastly impact user experience. We live in a mobile-first era, and thus, appropriate data population according to the screen sizes becomes even more critical. The user doesn’t care the amount of data till the time it is easily readable.

Not deviating from the topic in hand, tabular representation of data has always been difficult for me, and the only reason was – RESPONSIVENESS

I have been working in Angular from quite some time, and whenever I had to use a tabular representation of data, I used to search for libraries for responsive tables. I won’t deny that there aren’t some very powerful libraries out there that help with pagination, sorting and filtering of data within the table but that comes under DATA MANIPULATION. They even claim to be responsive, but the libraries FAIL under 2 conditions:

When a different type of data is to be populated
Whenever there are 3-4 types of data in a single row like a checkbox, string, number, dropdown and buttons, the library is bound to fail.
Multiple Table Data

When there are many columns with variable width
Column names and cell data in a table are rarely of equal widths, and thus the variable width disturbs the orientation of the table, in turn breaking the responsiveness. After working with multiple libraries like ngx-datatable and trying to customize frameworks like Bootstrap or Angular Material by their CSS, I decided to solve the mystery of responsive tables once and for all!
Variable Width

Give a man a fish, and you feed him for a day. Teach a man to fish, and you feed him for a lifetime.

– Maimonides

So let me teach you to develop YOUR OWN RESPONSIVE table, where you can control the column widths according to the viewport/screen width and have multiple types of inputs in a row.

The only thing we need – CSS Flexbox.

CSS Flexbox

The Flexible Box Module, usually referred to as flexbox, was designed as a one-dimensional layout model, and as a method that could offer space distribution between items in an interface and powerful alignment capabilities.

developer.mozilla.org

In simple terms, Flexbox helps to align items in row and columns.

If you haven’t heard about it yet, I would recommend you to go through this:

For Basics: https://medium.freecodecamp.org/learn-css-flexbox-in-5-minutes-b941f0affc34

For a Comprehensive Guide: https://medium.com/@js_tut/the-complete-css-flex-box-tutorial-d17971950bdc

Flexbox Cheatsheet:
https://yoksel.github.io/flex-cheatsheet/

Our aim is to show data in tabular representation on bigger/wider screens (width > 768px) and in collapsed/card view of each row on screens less than 768px wide.

Responsive Data Tables
Figure 1: Responsive Table – Desktop
Responsive Data Tables
Figure 2: Responsive Table – Mobile (Card View)

There are two things we need to understand to implement responsiveness of the tables:

  1. Flex Basis – Flex basis specifies the initial length of the table cell, which here is our flexible item.

Available values:

flexbasis: number | auto | initial | inherit;
Number: A length unit or percentage
Auto: This is the default value. It takes the length of the content inside it.
Initial: It sets the property to its default value
Inherit: It inherits the property from its parent

  1. Media Queries
    Whenever we need to control how our elements look on different screen sizes (desktop, mobile, tablets), we use media queries to specify break-points. We can write different styling for the same element on either side of the break-point.

There are 4 standard break-points that we use:

  1. 576px – small devices
  2. 768px – tablets
  3. 992px – desktops
  4. 1200px – large desktops

This can be used with:

  1. min-width –specified minimum width and up
  2. max-width – less than the specified maximum width

For Example – and I personally use:

// Large devices (desktops, less than 1200px)
@media(max-width:1199.98px){...}

// Medium devices (tablets, less than 992px)
@media(max-width:991.98px){...}

// Small devices (landscape phones, less than 768px)
@media(max-width:767.98px){...}

// Extra small devices (portrait phones, less than 576px)
@media(max-width:575.98px){...}

Source: getbootstrap.com

Also Read: Angular Authentication Using JWT

CONTROLLING WIDTH OF COLUMNS/CELL

We’ll use flex-basis to control the width of each column. Flexbox works with the help of two things – Flex Container and Flex Items. The row becomes the flex container, and the table cells are flex items. If the content is more than the cell width, it wraps to the new line.  We consider the table row (flex container) to be at 100% width and thus divide the column widths accordingly in percentages (%).

Responsive Data Tables

Here, the row – table-headers is considered 100% of the width. It also serves as the flex-container.The row is then divided into 5 columns of variable widths:

30% + 20% + 30% + 10% + 10% = 100%

Controlling Column Width

flex-basis-30 = 30% space of 100%
flex-basis-20 = 20% space of 100%
flex-basis-30 = 30% space of 100%
flex-basis-10 = 10% space of 100%
flex-basis-10 = 10% space of 100%

flex basis

This creates the columns with the desired widths, and on increasing the screen-width, the table cells (flex-items) adjusts according to their flex-basis percentage value.   

ADDING DIFFERENT TYPES OF DATA IN TABLE CELLS

Once you have specified the width, then sky is the limit. You can add anything and everything as data in the cells which HTML permits – from dropdowns to checkboxes, radios buttons to lists, images to block buttons.

Items in table cells
Figure 3: Different types of items in table cells

Text in Table Cells

Card View
Figure 4: Card View of Table Row

COLLAPSING ROW INTO CARDS ON MOBILE VIEW

Tabular data is not recommended on mobile views due to the complexity and unease of viewing data. One thing that we can do to tackle this is that we can collapse the row into a card and then view tabular data via card view.

We’ll be using media queries to style the cards and cell data. One thing that is great about flex-basis is that it is like any other CSS property and thus we can change the width of the columns on different screen widths. This gives us true flexibility and empowers us to make the table TRULY RESPONSIVE.


Wrapping Up: 

You must be thinking of how the title of this blog justifies the content. Tables and that too responsive table have been a dreaded element for me, up until now! Any framework, be it Angular, Vue.js or React that I worked with and any project that I took had a table in it, and therefore I had to find a permanent solution. Hence I decided to learn it.  

I agree that the libraries and frameworks out there provide great tables with functionalities like sorting, filtering, and pagination, but those are data manipulation. Once you create responsive tables with flex-basis and media queries, you can programmatically manipulate the data being shown, i.e. filter, sort, and search: which in turn helps you understand how things work under the hood of the libraries you use. 

You might argue that this is like re-inventing the wheel. I consider this as understanding how the wheel is developed in the first place so that you can make a better, faster, more efficient wheel.


Handpicked Content for You:

Angular Authentication Using JWT

0
JWT Authentication

Building a web-based product is not just a skill anymore; it’s a necessity, for anything and everything that requires public attention.

A decade into the digital revolution, we are finally witnessing a tectonic shift in users’ behavior towards consumer products, wherein a majority of these products are either web-applications or mobile-applications.

A web/mobile app is usually a culmination of many components working in unison. One of the most overlooked, but significant part is user authentication. Believe me, when I say this, 70% of users leave the platform if they aren’t satisfied with the on-boarding experience.

It HAS to be Smooth & Simple.

There are countless tutorials out there exhibiting  code of how authentication in angular works, some even go the extra mile to explain how the code runs, but the only issue with such codes (for rookies) is the flowery words and jargon they use, which can be quite troublesome for someone who is just starting-out in the domain.

The following is a detailed, yet simple guide on how authentication works in angular. The code for the same could be found here. The following code is well commented so that you understand what is actually happening!

This tutorial is not a step by step guide to authentication with angular. The Internet is already swarming with thousands of them, but what’s missing is a detailed explanation of the working of those steps.

It is recommended that you clone the project here and go through this tutorial while referencing the code. It will give you the clarity you are yearning for…

Before we start with the “coding” section, we need to understand the basic concept behind authentication and JSON Web Tokens (or JWT as millennials call it).

Authentication is a means of verifying the identity of a user, which means if the user is allowed to access the application or not.  The two most prevalent ways a user can get authenticated is either through social login (Google+/Facebook login) or through a registered username (can be an email) and password. We will be using the latter to understand the inner workings of authentication in angular.

Recommended Read: A Detailed Guide to CSS Animations and Transitions

The codebase for this tutorial works on the following components:

  1. JSON Web Token
  2. Client + localStorage
  3. Backend + Secure API Endpoints + DB
  4. Authentication Service
  5. User Service
  6. JWT Interceptor
  7. Auth Guard
  8. Error Interceptor

After understanding the 8 elements mentioned above, you will not only learn about the workings of JWT and authentication but will also be able to appreciate the process behind it.

  1. JSON Web Tokens (JWT)

JSON Web Tokens, if defined abstractly, is a JSON object which helps in exchanging information between two or more parties securely. In layman terms, it’s a type of validation token from the authentication server, which indicates that the username and password supplied by the user at the time of logging in whether it is correct or not, and thus the user is “authenticated”.

Read more about JWT and its intricacies right here.

  1. Client + localStorage

The client here is the user operating on a browser (Google Chrome/Firefox/Opera/Safari). For every registered user, there is a set of username and password stored in the database at the backend.

The two most important types of storage properties of any browser are the localStorage and the sessionStorage; they allow you to store key-value pairs in the browser.

  • localStorage
    It is a persistent storage option when you don’t want the user to be logged out on refresh or closing of a browser tab. The localStorage stores the data without expiration date by default. It is a read-only property.
  • sessionStorage
    As the name indicates, it stores data for a particular session only. It is less persistent, and the user data gets lost on the closing of the browser tab or refreshing.

We will be using localStorage in our case.

NOTE: One can find localStorage in the developer console (F12 on Chrome) under the “Application” tab.

  1. Backend + Secure API Endpoints + DB

The backend for this tutorial is a fake backend as we just want to understand how things are working on the front-end part. But this backend works as any real backend wherein it has API’s that provide us with a response body and response status. The fake-backend.ts also has test data (DB) for a test user. The credentials input by the user will be validated against this test data.

Test Data:
The fake-backend will serve as a standalone backend with a delayed response so that it can imitate a real backend. The two major tasks it will perform are:

  1. It will check the user credentials that come from “Authentication Service” during login
  2. It will also work as a fake database keeping the user details (hitting a secure API end-point). The user can request for the user details only when the requests have valid JWT Token in its request authorization header

The two API’s that our current backend has are:

  • To check credentials – /users/authenticateIf the user credentials match the test user stored data, the backend sends a response body with a JWT token.

fake-backend.ts

  • To give back user details – /users

    This is a SECURE API endpoint. By secure, it means that to access this API endpoint, the request must have a valid JWT Token with it. This token is in the request header with the “Authorization: Bearer JWT-TOKEN” property.It first checks for a valid JWT token and then it responds accordingly.

fake-backend.ts

  1. Authentication Service

Authentication Service

Authentication service is used to LOG IN and LOG OUT from the application. It possesses the credentials (username and password) from the client (user/browser) to the backend and checks for the response, if it has JWT token.

If the response from the backend has a JWT token, then the authentication was successful. On successful authentication, the user details are stored in the local storage along with JWT token.

  1. User Service

The user service is a service dedicated to hitting the 2nd API (the secure API end-point) to fetch the data for all the users present in the database. Currently, only a single user is present – test user. This User Service is accessed via the home component as soon as the user logs in and the home component is initialized.

  • home.component.ts

The service will get the response from the backend only if the backend receives the request along with a valid JWT token.

  • user.service.ts

The token is not sent when the request by the client is made. Here is when JWT Interceptor comes to rescue!

  1. JWT Interceptor

JWT Interceptor

The JWT interceptor intercepts the incoming requests from the application/user and adds JWT token to the request’s Authorization header, only if the user is logged in (because then the JWT token will be present in the localStorage at client’s end).

The JWT interceptor works very smarty by not modifying the original request made by the user service, but cloning the request and adding the JWT token to the request header and then forwarding the cloned request to the backend. The value of the token is fetched from the client’s localStorage. If the user is logged out, there will be no JWT token in the localStorage, and thus, the user won’t be able to access the secured API endpoint.

jwt.interceptor.ts

  1. Auth GuardThe Auth Guard works as umm – a Guard!

The auth guard ensures that only authenticated users access specific routes in the application. The auth guard implements an interface called CanActivate with the help of which it returns either true or false.

True If the user is logged in, i.e. the localStorage has current users’ details along with a valid JWT token

False If the user is logged out, i.e. the localStorage lacks the current user details along with a valid JWT token, and in turn, will then redirect the user to the login page.

auth.guard.ts

In this particular example, we are using the presence of the current user detail as a way to give rights to access one specific route, i.e. ‘/’ (root), or the HomeComponent. There can be other conditions too like role-based authentication. The rights to access particular routes will then be allocated on the basis of the role of a specific user. The user will be able to access the admin route (say) only if he is an admin.

Even though it is developed in a separate file auth.guard.ts, but it is implemented in the routing of the application, with the canActivate parameter.

app.routing.ts

  1. Error Interceptor

The HTTP error interceptor works with the calling service and the API’s

It intercepts the responses from the API and checks for the status codes (if there were any errors).

Error Status

  1. 200: Success
  2. 401: Unauthorized Response – the user will be automatically logged out

All other errors are RE-THROWN, to be caught by the calling service so an alert can be displayed by the user service/component on the client’s end.

error.interceptor.ts


Wrapping Up

The thing about angular (or any framework) is – The more you work with it, the more you’ll discover what all you don’t know. The lack of knowledge about fundamentals will prove to be a hindrance and in turn, will slow down the development process. This is my effort to make one of the components of a web-app development process, i.e. Authentication – EASY!

We hope you found this post valuable. In case you have any doubts, let us know in the comments below.


Recommended Read: