Convert the Query string parameters to a JSON object - javascript

How to convert the query string parameters to a JSON object
Code I was written
var actualappt = {
RoomId: 1, HotelId: 29, BookingStartDate: Sept 26 2014, BookingEndDate: Sept 26 2014 , BookingStatusId: '1', BookingTypeId: '1', DepositAmount: 3000, NoOfRooms: 2, UnitPrice: 4000,
Customers: { GuestName: rk, MobileNo: 5656566555, Email: rk#gmail.com, Address: hyd }, Payment_Mode_Id: 4
};
var stringsata = JSON.stringify(actualappt);
var queryString = $.param(actualappt);
Now I am able to convert JSON object to query string and sending to next page, in my page I want reverse process i.e from query string to JSON object

var actualappt = {
RoomId: 1, HotelId: 29, BookingStartDate: "Sept 26 2014", BookingEndDate:"Sept 26 2014" , BookingStatusId: '1', BookingTypeId: '1', DepositAmount: 3000, NoOfRooms: 2, UnitPrice: 4000,
Customers: { GuestName: "rk", MobileNo: 5656566555, Email: "rk#gmail.com", Address: "hyd"}, Payment_Mode_Id: 4
};
var stringsata = JSON.stringify(actualappt);
var queryString = $.param(actualappt);
var recoveredParams = {};
var queryString = decodeURIComponent(queryString)
$.each(queryString.split('&'), function(key, value){
var item= value.split('=');
recoveredParams[item[0]] = item[1];
});
console.log(recoveredParams)

Related

Arrange Chat Messages By Date

I am working with Vue, but this is a general javascript question.
I make a call to an api to get cat messages for a chat UI. The initial call returns an array of objects where each object is a chat message object as below.
data: [
0: {id: 1, created_at: "2022-05-20T15:12:40.000000Z", updated_at: "2022-05-20T17:18:03.000000Z",…}
1: {id: 2, created_at: "2022-05-20T15:12:41.000000Z", updated_at: "2022-05-20T17:18:04.000000Z",…}
2: {id: 3, created_at: "2022-05-20T15:12:41.000000Z", updated_at: "2022-05-20T17:18:04.000000Z",…}
3: {id: 4, created_at: "2022-05-20T15:12:41.000000Z", updated_at: "2022-05-20T17:18:04.000000Z",…}
]
I initial wanted to format the message so they can be grouped by their dates in the chat window. This is the code I used to group them
This is a computed property in vue
const formattedChats = computed(() => {
let dateFormattedMessages = messages.value.map(message => {
return {...message, updated_at: new Date(message.updated_at).toDateString(), created_at: new Date(message.created_at).toDateString()}
})
return dateFormattedMessages.reduce((total, currentValue) => {
total[currentValue.updated_at] = total[currentValue.updated_at] || [];
total[currentValue.updated_at].push(currentValue);
return total;
}, Object.create(null));
})
The above will first take the each chat object an convert their updated_at and created_at to a date string and then group the array using the updated_at.
The result was as follows:
formattedChats = {
Fri Jun 24 2022: [
{...}, {...
]
Fri May 20 2022:[
{...}, {...
]
Mon Jun 27 2022:Array[
{...}, {...
]
Sat May 21 2022:Array[
{...}, {...
]
Tue Jun 28 2022:Array[
{...}, {...
]
}
If you notice, the problem I am facing is that the dates are not arranged in any order. it doesnt make sense to render it to the UI like this because the resulting chats with not be arranged by date.
This is how the UI should look
You need to use arrays (or a map) to keep the order sorted. I would use an array of arrays. First you need to sort the data on date (I used updated_at, which I made of type Date in the data array). Then iterate over the sorted array. See snippet below.
const data = [{
id: 1,
updated_at: new Date("2022-05-21T15:12:40.000000Z"),
created_at: "2022-05-20T17:18:03.000000Z"
},
{
id: 2,
updated_at: new Date("2022-05-20T15:12:41.000000Z"),
created_at: "2022-05-20T17:18:04.000000Z"
},
{
id: 3,
updated_at: new Date("2022-05-23T15:12:41.000000Z"),
created_at: "2022-05-20T17:18:04.000000Z"
},
{
id: 4,
updated_at: new Date("2022-05-21T15:12:41.000000Z"),
created_at: "2022-05-20T17:18:04.000000Z"
},
]
const sortedData = data.sort(
(a, b) => Number(a.updated_at) - Number(b.updated_at),
);
let currentDay = sortedData[0].updated_at;
const stillCurrentDay = (dayOfMessage) => {
return dayOfMessage.getFullYear() === currentDay.getFullYear() &&
dayOfMessage.getMonth() === currentDay.getMonth() &&
dayOfMessage.getDate() === currentDay.getDate()
}
let dayMessageArray = [];
const fullMessageArray = [];
const createMessagesArray = (messages) => {
const newDay = {};
newDay[currentDay.toISOString().split('T')[0]] = messages;
fullMessageArray.push(newDay);
}
sortedData.forEach(message => {
if (!stillCurrentDay(message.updated_at)) {
createMessagesArray(dayMessageArray);
currentDay = message.updated_at;
dayMessageArray = [];
}
dayMessageArray.push(message);
});
createMessagesArray(dayMessageArray);
console.log(fullMessageArray);
Hope this helps. Perhaps there are easier ways, please let me know.

How to push data which is not hard coded into variable?

I am trying to push data into a variable Data[] but all I have is an example of how to do this hard coded:
var data = [{
id: "1",
name: "Development Life Cycle",
actualStart: Date.UTC(2018, 01, 02),
actualEnd: Date.UTC(2018, 06, 15),
children: [{
id: "1_1",
name: "Planning",
actualStart: Date.UTC(2018, 01, 02),
actualEnd: Date.UTC(2018, 01, 22),
connectTo: "1_2",
connectorType: "finish-start",
progressValue: "75%"
},
// more data goes here
]
}];
I tried with following code but it doesn't seem to work:
ganttdata = [];
// DUMMY DATA
id = 10;
RFInum = 'asfd';
start= 1;
LTIOV = 2;
progressValue = 10;
ganttdata.push("{id:"+id, "parent: null", "name:"+RFInum, "actualStart: Date.UTC("+start+")", "actualEnd: Date.UTC("+LTIOV+")", "progressValue:"+progressValue+"%}");
console.log(ganttdata);
Anyone know how to write this?
You are currently inserting your data as a string and not as an object.
I recreated your approach and inserted your data as an object into the ganttdata array.
Date documentation
var ganttdata = [];
// DUMMY DATA
var id = 10;
var RFInum = 'asfd';
var start = Date.UTC(2021, 12, 31);
var LTIOV = Date.UTC(2021, 12, 31);
var progressValue = 10;
ganttdata.push({
id,
parent: null,
name: RFInum,
actualStart: start,
actualEnd: LTIOV,
progressValue: `${progressValue}%`,
});
console.log(ganttdata);
Or if you want to append some data to an existing object at a specific index:
var data = [{
id: 1,
name: 'test'
}];
console.log('before:', data);
data[0].extend = 'hello World';
data[0].foo = 'bar';
console.log('after:', data);

Combine objects of an array with the same date into one - JavaScript

I receive an array of posts through an API and want to merge the ones with the same "month" and "year" (day is not important), into one object. I looked up for answers but there are just too many foo-bar examples that confuses more than helping. I want to know the cleanest, most elegant way of handling such problems, without getting into call-back hell and nested blocks...
Here is the API response:
0:
{
date: {day: 27, month: 1, year: 2020}
id: 3
}
1:
{
date: {day: 28, month: 1, year: 2020}
id: 4
}
2:
{
date: {day: 31, month: 1, year: 2020}
id: 5
}
3:
{
date: {day: 1, month: 2, year: 2020}
id: 6
}
4:
{
date: {day: 2, month: 2, year: 2020}
id: 7
}
The expected outcome:
0:
result: {month: 1, year: 2020, id:[3,4,5]}
1:
result: {month: 2, year: 2020, id:[6,7]}
One approach would be to use the Array#reduce() method to transform the input array into a dictionary, where each value contains the accumulation of id's for that month and year. Once this dictionary has been built, you could then extract the values of that dictionary to an array via Object#values() to obtain the required output:
let input=[{date:{day:27,month:1,year:2020},id:3},{date:{day:28,month:1,year:2020},id:4},{date:{day:31,month:1,year:2020},id:5},{date:{day:1,month:2,year:2020},id:6},{date:{day:2,month:2,year:2020},id:7}];
/* Convert the dictionary that will be created by reduce to a value array */
var output = Object.values(input.reduce((dict, item) => {
const { date, id } = item;
/* The distinct key for this item based on month/year of date field */
const key = `${date.month}-${date.year}`;
/* Check if dictionary already has an object value for key. This short hand
will only insert a new object value for key, if one does not already exist
in the dictionary */
const value = dict[key] || { month : date.month, year : date.year, id : [] };
/* Add the item id to the dictionary entries id array */
value.id.push(id);
/* Update value object for key */
return { ...dict, [key] : value };
}, {}))
console.log(output);
The idea here is that the dictionary is built using Compound Keys, where the keys are derived from the month and year of the current array item.
When no value exists for the current key, a new value object is inserted to the dictionary for that key:
{ month : date.month, year : date.year, id : [] }
The id of the current array item is then added (accumulated) to the id sub array of the object for that key:
dict[key].id.push(id);
Hope that helps
Here is an alternate approach, if you are not a big fan of Array.reduce and Array.values and also, if you like to consider performance when running the response for a larger data set.
This approach avoids cloning object (or rather non-mutating object) with spread operator i.e {...<anyObject>} while iterating. which should be fine for minimal set of data but but definitely not when you deal with huge volume.
const response = [{
date: { day: 27, month: 1, year: 2020 },
id: 3
}, {
date: { day: 28, month: 1, year: 2020 },
id: 4
}, {
date: { day: 31, month: 1, year: 2020 },
id: 5
},{
date: { day: 1, month: 2, year: 2020 },
id: 6
},{
date: { day: 2, month: 2, year: 2020 },
id: 7
}];
function groupByMonthYear(response) {
// output
const groupedData = []
// Using map for lookup to avoid iterating again on the grouped data
const referenceMap = new Map();
// destructing month, year and id from the response
for (const { date: { month, year }, id } of response) {
const groupKey = `${month}${year}`
// check if the month and year reference is already seen using the groupKey MMYYYY
if (referenceMap.has(groupKey)) {
referenceMap.get(groupKey).id.push(id);
// early return
continue;
}
// simply add a new entry if it doesn't exist
const data = {
month,
year,
id: [id]
};
groupedData.push(data);
referenceMap.set(groupKey, data)
}
return groupedData;
}
// Invoke and Print the result
console.log(groupByMonthYear(response));

How to find the closest date from current date from a multi-dimensional array in Javascript

Question
I have the following multi-dimensional array where slot_date is coming from the database query. I have a button for every student_id. But I need only one button for the closest date.
Output in Ajax call
[
'1': {
slot_date: "2019-01-11"
student_id: 26
}
'2': {
slot_date: "2019-01-21"
student_id: 27
}
'3': {
slot_date: "2019-03-11"
student_id: 28
}
'4': {
slot_date: "2019-03-18"
student_id: 29
}
]
Javascript file
join_button = '<a onclick="studentJoinMeeting()"><button class="ongoing-btn">Join Meeting</button></a>';
Desired Output
I need the id of date 2019-03-11 i.e closest date to current date. I need the join button only on that 2019-03-11 date.
You can sort your array based on the dates, by calculating their absolute distance to today. You can then take the first element.
I modified your data array to be a data object since your are using key/values pairs.
const data = {
'1': {
slot_date: "2019-01-11",
student_id: 26
},
'2': {
slot_date: "2019-01-21",
student_id: 27
},
'3': {
slot_date: "2019-03-11",
student_id: 28
},
'4': {
slot_date: "2019-03-18",
student_id: 29
}
};
const today = Date.now();
// This function returns the absolute difference in ms between 2 dates
const dateAbsoluteDiff = (date1, date2) => {
if (date1 - date2 < 0) return date2 - date1;
else return date1 - date2;
};
// get the entries (array of key/values) of the data, sort them based
// on their date distance to today
// take the first element (the closest), this is a key/value pair
// return the second item from this pair, which is the original object
const closest = Object.entries(data).sort((e1, e2) => {
return dateAbsoluteDiff(new Date(e1[1].slot_date), today) -
dateAbsoluteDiff(new Date(e2[1].slot_date), today);
})[0][1];
console.log(closest);
console.log('Student id:', closest.student_id);
If your input data was instead an array, you can sort it directly:
const data = [{
slot_date: "2019-01-11",
student_id: 26
}, {
slot_date: "2019-01-21",
student_id: 27
}, {
slot_date: "2019-03-11",
student_id: 28
}, {
slot_date: "2019-03-18",
student_id: 29
}];
const closest = data.sort((e1, e2) => {
return dateAbsoluteDiff(new Date(e1.slot_date), today) -
dateAbsoluteDiff(new Date(e2.slot_date), today);
})[0];
If instead you want to get the next closest date, then don't take the absolute difference, map your array to an array containing the differences, then sort them and find the first difference greater or equal to 0.
const data = [{
slot_date: "2019-01-11",
student_id: 26
}, {
slot_date: "2019-01-21",
student_id: 27
}, {
slot_date: "2019-03-11",
student_id: 28
}, {
slot_date: "2019-03-18",
student_id: 29
}];
const today = Date.now();
const nextDate = data
.map(({ slot_date }) => ({ slot_date, diff: new Date(slot_date) - today }))
.sort((e1, e2) => e1.diff - e2.diff)
.find(date => date.diff >= 0)
console.log(nextDate.slot_date)
You given array is not valid. Arrays cannot have keys. You cant write key:value in [] use {} for that. Here is example with array.
And closest date to current date will the highest date and it will be 2019-03-18
let arr = [{slot_date: "2019-01-11",student_id: 26},
{slot_date: "2019-01-21",student_id: 27},
{slot_date: "2019-03-11",student_id: 28},
{slot_date: "2019-03-18",student_id: 29},
]
let maxDate = 0;
let maxDateID;
for(let item of arr){
if(new Date(item.slot_date) > maxDate){
maxDate = new Date(item.slot_date);
maxDateID = item.student_id;
}
}

Convert string to nested array

I have a string passed from server which was called with AJAX and I have to convert the string into a nested array which will be used to populate on PDF.
For example:
var tableData = "[{ name: 'Bartek', age: 34 },{ name: 'John', age: 27 },{ name:'Elizabeth', age: 30 }]";
and I need to convert into an array in JavaScript which will be like this:
var newTableData = [
{ name: 'Bartek', age: 34 },
{ name: 'John', age: 27 },
{ name: 'Elizabeth', age: 30 }
];
How can I do that?
As pointed out in the comments, the best solution would be to return a valid JSON from the server and to parse it using JSON.parse.
You can use tools like https://jsonlint.com/ or JSV to check that your JSON is valid.
If because of some "real world problem", your servers aren't JSON complaint, you can use a dirty parser like dirty-json or write your own JSON parse.
dirty-json does not require object keys to be quoted, and can handle single-quoted value strings.
var dJSON = require('dirty-json');
dJSON.parse("{ test: 'this is a test'}").then(function (r) {
console.log(JSON.stringify(r));
});
// output: {"test":"this is a test"}
Your last resort, while technically possible and the easiest to implement, is probably your worst choice because of it's dangers. but it would work out of the box: eval.
eval(tableData);
// [ { name: 'Bartek', age: 34 },
// { name: 'John', age: 27 },
// { name: 'Elizabeth', age: 30 } ]
By slightly changing how you return the string from the server you can JSON.parse it
var dataString = '[{"name":"Bartek","age":34},{"name":"John","age":27},{"name":"Elizabeth","age":30}]';
var data = JSON.parse(dataString);
console.log(data);
Use eval() method The completion value of evaluating the given code. If the completion value is empty, undefined is returned:
var tableData = "[{ name: 'Bartek', age: 34 },{ name: 'John', age: 27 },{ name:'Elizabeth', age: 30 }]";
tableData = eval(tableData);
console.log(tableData[0]);

Categories