Javascript template literals help splitting by month

Here is an extract of my json data

"availability":[
    {
      "hash":"820eRWiyq2Vy4Sk",
      "arrival":"2019-12-01",
      "departure":"2019-12-08",
      "description":"",
      "col1":"695",
      "availability":"empty",
      "availableRooms":"7",
      "availableGuests":"16"
      },
    {
      "hash":"8201ahPFdE28VUF",
      "arrival":"2020-01-05",
      "departure":"2020-01-12",
      "description":"",
      "col1":"695",
      "availability":"empty",
      "availableRooms":"7",
      "availableGuests":"16"
      },
      {

and here is where I have got to with my limited, newly acquired knowledge of javascript template literals

success: function(data) { 
myObj = data.chalets[0].availability;
console.log(myObj);
document.getElementById("app").innerHTML = `
<h2 class="section-title text-center-xs">Price &amp; Availability</h2>
<div class="chalet-price-table"> 
											<!-- chalet-price-row -->
<div class="chalet-price-row">
<div class="row-date" data-month="12"> 
<span><span>Dec '19</span></span>
</div> 
															<!-- row-days -->
${myObj.map(function(chalet) {
return `                              
<div class="row-days">
<div class="row-days-wrap">
<div class="day">
<span class="d">${chalet.arrival.slice(-2)}</span>
<span class="rooms-left">${chalet.availableRooms} Rooms Left</span>
<span class="price"><span class="only-price"><b>N/A</b></span><span class="inc-price"><b>&pound;${chalet.col1}</b> per person</span></span>
<small class="was text-red"><span class="only-price"></span><span class="inc-price"></span></small>
<a data-chalet-id="26054" data-chalet-name="Chalet La Ferme d’Elise" data-chalet-offer-day="14/12/2019" href="#" data-price="inc-price" data-toggle="modal" data-modal-class="modal-vertical-centered" data-modal-size="lg" data-target="#offer-enquiry-modal" class="btn btn-yellow"><i class="fa fa-angle-right"></i><i class="fa fa-angle-right"></i></a>
</div>
</div>
</div>
`
}).join('')}
								<!-- row-days END -->
</div>
											 
</div>
<p>Changeover day is Saturday.</p>
`
},

and here is the image of what is returned once formatted (top image)


So here is where I ask for some pointers please.
The Black box featuring Dec '19 is outside the loop and has been manually produced.
Firstly, how would I set about extracting the available months from the json? I am guessing .arrival.slice(5, 7)
would play a part her. I suppose I then need to create a map of the original array for each of the available months, in my case just dec, jan and feb so that just the availability from each month comes after the relevant black boxed month as per the second part of the above image (in which the data has to be manually inserted!)

OK, I got to this so far but I hope that someone may be able to help reduce my code via a loop.
I inserted this

myObjAll = data.chalets[0].availability;
let myObj = myObjAll.filter(it => it.arrival.slice(5, 7) == 12);
let myObj1 = myObjAll.filter(it => it.arrival.slice(5, 7) == 01);
let myObj2 = myObjAll.filter(it => it.arrival.slice(5, 7) == 02);
let myObj3 = myObjAll.filter(it => it.arrival.slice(5, 7) == 03);

then repeated the template literal part for each myObj thus:

<div class="chalet-price-row">
<div class="row-date" data-month="12"> 
<span><span>Jan '20</span></span>
</div> 
															<!-- row-days -->
${myObj1.map(function(chalet) {
return `                              
<div class="row-days">
<div class="row-days-wrap">
<div class="day">
<span class="d">${chalet.arrival.slice(-2)}</span>
<span class="rooms-left">${room(chalet.availableRooms)}</span>
<span class="price"><span class="only-price"><b>N/A</b></span><span class="inc-price">${price(chalet.col1)}</span></span>
<small class="was text-red"><span class="only-price"></span><span class="inc-price"></span></small>
<a data-chalet-id="26054" data-chalet-name="Chalet La Ferme d’Elise" data-chalet-offer-day="14/12/2019" href="#" data-price="inc-price" data-toggle="modal" data-modal-class="modal-vertical-centered" data-modal-size="lg" data-target="#offer-enquiry-modal" class="btn btn-yellow"><i class="fa fa-angle-right"></i><i class="fa fa-angle-right"></i></a>
</div>
</div>
</div>
`
}).join('')}
								<!-- row-days END -->
</div>

Can you just clarify here, I’m understanding what you have here to be:

You have an array of objects which, overall, represents the availability of a specific chalet. The chalets are booked on a weekly basis, so each object represents a week in the calendar.

So is there an array for each month, or are they all in one array?

As far as I can see, this is not a template literal problem. That is how you will render out the data in the HTML, but it’s an implementation detail, the important thing here afaics is how you parse that data into something more usable

Without completely giving you the answer, here is something I put together that may help your code readability, and give you some extra functionality from the Date object. Using the function below you no longer need to manually create the month names, you can include <div class="row-date" data-month="${month}"> when looping over the array.

You can learn more about the cool properties and methods available to the Date object here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Date.prototype_Methods

While not obvious in the code example below, you can use the date object to do things like calculate the time between now and arrival date, or maybe get the day of the week.

Note: For demo purposes, I’ve changed your availability property from the JSON object to a regular array and modified the HTML output a bit. I included the console.log() function, so you can copy all the code below and test in your browser.

const availability = [
  {
    hash: "820eRWiyq2Vy4Sk",
    arrival: "2019-12-01",
    departure: "2019-12-08",
    description: "",
    col1: "695",
    availability: "empty",
    availableRooms: "7",
    availableGuests: "16"
  },
  {
    hash: "8201ahPFdE28VUF",
    arrival: "2020-01-05",
    departure: "2020-01-12",
    description: "",
    col1: "695",
    availability: "empty",
    availableRooms: "7",
    availableGuests: "16"
  }
];

const monthNames = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December"
];

function formatAvailability(availability) {
  return availability
    .map(chalet => {
	  // Create an array from chalet.arrival
	  // Use array destructuring to store each part of your date string in a variable.
      // https://hacks.mozilla.org/2015/05/es6-in-depth-destructuring/
      let [year, month, day] = chalet.arrival.split("-");
      const montZeroIndex = month - 1;
      // Create a new date object
      const date = new Date(year, montZeroIndex , day);

      return `
	  <div class="row-date" data-month="${month}">
         <!-- Here you can display the month name from the monthNames array by converting the month number to it's zero-index value. -->
	  	 <span><span>${monthNames[montZeroIndex]} ${date.getFullYear()}</span></span>
	  </div>
	  <div class="day">
	     <span class="d">${date.getDate()}</span>
	  </div>`;
    })
    .join("");
}

console.log(formatAvailability(availability));
1 Like

Hi, no, the arrays are are not split by month. The json is extracted from a third party booking system’s API so I have no controlover how they represent the data.

Thanks for this in depth information. I have it working using my d’dirty’ method but it still feels like I just struck lucky using tutorials, help from people like you and hours of write/test/edit repeat.

The inner pedant strives for a more elegant ‘correct’ solution so I will play with your code and hope to achieve a cleaner solution

I guess from the date code format but I concur; the API has awful documentation which coupled with my zero JSON and very little javascript experience has made for a fun adventure.

I finally got round to playing with your code and ran into a problem. I added a few more dates to availability including multiple ones per month so I could mess around and find how to utilise it but when I ran it I found it produced a new div for each week rather than the required one per month.
I expanded availability:

const availability = [
  {
    hash: "820eRWiyq2Vy4Sk",
    arrival: "2019-12-01",
    departure: "2019-12-08",
    description: "",
    col1: "695",
    availability: "empty",
    availableRooms: "7",
    availableGuests: "16"
  },
  {
    hash: "8201ahPFdE28VUF",
    arrival: "2020-01-13",
    departure: "2020-01-19",
    description: "",
    col1: "695",
    availability: "empty",
    availableRooms: "7",
    availableGuests: "16"
  },
  {
    hash: "8201ahPFdE28VUF",
    arrival: "2020-01-20",
    departure: "2020-01-27",
    description: "",
    col1: "695",
    availability: "empty",
    availableRooms: "7",
    availableGuests: "16"
  },
  {
    hash: "8201ahPFdE28VUF",
    arrival: "2020-02-05",
    departure: "2020-02-13",
    description: "",
    col1: "695",
    availability: "empty",
    availableRooms: "7",
    availableGuests: "16"
  },
  {
    hash: "8201ahPFdE28VUF",
    arrival: "2020-02-14",
    departure: "2020-02-21",
    description: "",
    col1: "695",
    availability: "empty",
    availableRooms: "7",
    availableGuests: "16"
  }
];

which returned this:

	  <div class="row-date" data-month="12">
         <!-- Here you can display the month name from the monthNames array by converting the month number to it's zero-index value. -->
	  	 <span><span>December 2019</span></span>
	  </div>
	  <div class="day">
	     <span class="d">1</span>
	  </div>
	  <div class="row-date" data-month="01">
         <!-- Here you can display the month name from the monthNames array by converting the month number to it's zero-index value. -->
	  	 <span><span>January 2020</span></span>
	  </div>
	  <div class="day">
	     <span class="d">13</span>
	  </div>
	  <div class="row-date" data-month="01">
         <!-- Here you can display the month name from the monthNames array by converting the month number to it's zero-index value. -->
	  	 <span><span>January 2020</span></span>
	  </div>
	  <div class="day">
	     <span class="d">20</span>
	  </div>
	  <div class="row-date" data-month="02">
         <!-- Here you can display the month name from the monthNames array by converting the month number to it's zero-index value. -->
	  	 <span><span>February 2020</span></span>
	  </div>
	  <div class="day">
	     <span class="d">5</span>
	  </div>
	  <div class="row-date" data-month="02">
         <!-- Here you can display the month name from the monthNames array by converting the month number to it's zero-index value. -->
	  	 <span><span>February 2020</span></span>
	  </div>
	  <div class="day">
	     <span class="d">14</span>
	  </div>```