Skip to Content
Author's profile photo Gaurav Singh

Creating HashMap in UI5

 

A data structure is a reusable entity which can perform this operation. We have few entities already used in javascript like arrays,weakmaps etc .

However in  SAP UI5 libraries HashMap is not available .It can serve numerous functions for transactional data in front-end component . Few of them are

  • Store filtered data temporarily on front end page and based on the filter criteria added by end user keep on updating the list of current filters applied and also the result count.
  • If we should reach on a temporary state when we start cancelling the filters, then instead of making a call on the back-end o-data service and causing real-time traffic. These results can be cancelled on front-end and reverted back to the previous level

.

In this blog, I am sharing the step by step details on how to create this map and how to store information in form of key,value pairs and also as key,value array pairs

 

 

Step 1.  Create a new package in your UI5 Project

Step 2  Inside this package create a javascript file (For example Utils.js)

 

Step 3 :  Inside your Utils.js file  create the placeholder for contents  by doing the following

sap.ui.define(

function () {

“use-strict”;

var Utils = {

}

return Utils;

}

);

 

This object by the name utils is created and will be returned to any calling controller file.

Step 4  Now we need to create an object by the name map (for example) in this utils.js file

 

In order to do that we need to create another method by the name createMap which will return us the map object

 

This snippet needs to be created inside definition of utils object  as we did in Step 3

 

createMap:function() {

var  map = {

};

return map;

}

 

Step 5.  Now inside  the constructor of this map , which we have called as createMap, will contain two arrays. One array can be called as keyArray and the other array can be called as valueArray.

After putting them it will look like this

createMap:function() {

var keyArray;

var valueArray;

var map = {

keyArray : new Array(),

valueArray:new Array(),

 

var  map = {

};

return map;

}

 

Step 6.   Define the size method for map.

Size of the map can be determined by returning the length of keyArray. Since map contains data in the fom of key,value pairs. It makes sense to check how many keys the map has at any point of time. This number can be used to return the size of the map.Our original snippet gets changed  like this

 

createMap:function() {

var keyArray;

var valueArray;

var map = {

keyArray : new Array(),

valueArray:new Array(),

var  map = {

size :function() {

return this.keyArray.length;

}

};

return map;

}

 

Step 7  Define the keySet and valueSet methods as shown below.

createMap:function() {

var keyArray;

var valueArray;

var map = {

keyArray : new Array(),

valueArray:new Array(),

var  map = {

size :function() {

return this.keyArray.length;

},

keySet :function() {

return this.keyArray;

},

valueSet:function() {

return this.valArray;

}

 

 

};

return map;

}

Step 8. If we note that for each additional method we define for this map we put comma after previous  method and then define the new method (as shown highlighted in the latest snippet). We need to continue this pattern till we define all  methods of the map.

We have defined the basic methods like size,keySet and valueSet of a map. Now we need to define other additional methods which reflect the transactions done on a map. These methods are

  • findIt(key)
  • get (key)
  • put (key,val)
  • clear()
  • removeAt( key)

 

 

  1. For implementing the findIt we need to search the keyArray for the key which we gave as input

 

findIt :function(key) {

var result = (-1);

 

for( var i = 0; i < this.keyArray.length; i++ )

{

if( this.keyArray[ i ] === key )

{

result = i;

break;

}

}

return result;

}

};

return map;

},

 

  1. In order to implement get we need to use the findIt method. Get method will call findIt method to know the index of the key from the keyArray. Once we know the index then using same index, if valArray is called then , actual value of the requested key will be retrieved from the map

 

 

get :function(key) {

var result = null;

var elementIndex = this.findIt( key );

if( elementIndex != (-1) )

{

result = this.valArray[ elementIndex ];

}

return result;

},

 

 

 

  1. Implementation of put method will put the values and keys in both keyArray and valArray at same location

put :function(key,val) {

var elementIndex = this.findIt( key );

if( elementIndex === (-1) )

{

this.keyArray.push( key );

this.valArray.push( val );

}

else

{

this.valArray[ elementIndex ] = val;

}

},

clear :function() {

this.keyArray.splice(1,this.keyArray.length)

this.valArray.splice(1,this.valArray.length)

},

 

 

Following the steps above 1- 8 we can create a map which will hold the results in form of key,value pairs

These kay and value must be objects but they cannot be an array objects.Array objects are being discussed in next section.

 

Refining the map with additional attributes of array

In certain cases where we get nested result sets from the O-data Service then , map created above needs to be modified to help in storing the transactional state of UI5 app

For example a particular apparel can have an attribute which can be overlapped with other apparels . so in this scenario filtering based on one attribute (which is not exclusive) can be tricky.

I want Running Shoes of size 8 , Now property size 8  is exclusive property of a shoe which means that if shoe has size 8 then it has size 8 only and no other size  but what if I want it to be white color and belonging to brand Nike. In this situation brand is a attribute which is not exclusive and can be shared across other shoes. One white shoe of size 8 can belong to Adidas and can also belong to Nike

To achieve this, we need to have an array associated with a key in a map. This array will contain value objects for that key.

 

Step 1: define the new variable and initialize it  in constructor function

 

In our case it can be createMap function

 

var  valueObjectArray = new Array();

 

 

 

Step 2

Write a new valueSet function. For easy implementation we can name it as valueArraySet

valueArraySet:function() {

return this.valueObjectArray;

},

 

Step 3 :A new getter function getArrayForKey  should also be implemented  like this

getArrayForKey :function(key) {

var result = null;

var elementIndex = this.findIt( key );

if( elementIndex != (-1) )

{

result = this.userRoleArray[ elementIndex ];

}

return result;

},

 

Step 4: For each key , an array can be put as value for an object . For this we need to create a new method to accomplish it

putArray :function(key,valArray) {

var elementIndex = this.findIt( key );

if( elementIndex === (-1) )

{

this.keyArray.push( key );                                                               Array.prototype.push.apply(this.userRoleArray,valArray);

}

else

{

this.userRoleArray[ elementIndex ] = valArray;

}

},

Assigned Tags

      3 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      hi Gaurav,

      Most browsers currently support Map as native code, which will very likely provide better performance than your code or any polyfill - you can check the compatibility here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

      A lot of people still need to support Internet Explorer 11, and you can find a polyfill here: https://www.npmjs.com/package/es6-map

      Main thing is, you should avoid re-implement a common function that is available as native code if possible!

      🙂

       

      Cheers,

      Dan.

      Author's profile photo Gaurav Singh
      Gaurav Singh
      Blog Post Author

      Thank you for your feedback Dan and valuable insight

      This is not available in all browsers and also in our UI5 libraries (I could not find it ) . Therefore I had to implement it to continue in my work

      Author's profile photo Former Member
      Former Member

      hi Gaurav,

       

      yes, I told you it’s not available in every browser and you could use a polyfill – no need to repeat my own words. Internet Explorer 11 wouldn’t have it, as you might know.. however, the Web API is a set of classes that all javascript developers should know, and it’s a lot better for you to utilize them in your code instead of implementing a custom API to do the same work.

       

      The reason behind is, when Internet Explorer gets booted your code will run slower in every single possible browser, you increase the amount of bytes being transferred just because you didn’t adhere to the standard Web API – so it’s not worth it, not to mention you utilizing time to develop something that has been built and it’s very stable and accepted around (I also pointed you the es6 polyfill).

       

      I’m here just to point it out there is a better way to do what you just did, to anyone who actually comes here and read it.

       

      Cheers,

      Dan.