Vue: Organize information by day first, then further categorize it by time

I am currently working on organizing a list of events by day and then further grouping them by time. I have successfully achieved the first level of categorization but I am facing challenges with implementing the second level.

Ultimately, I aim to display the events as follows:

Friday
8:00 - Event 1, Event 2, etc…
9:00 - Event 1, Event 2, etc…

Saturday
8:00 - Event 1, Event 2, etc…
9:00 - Event 1, Event 2, etc…

The code snippet below illustrates my progress so far in creating the day-level groupings. As I am relatively new to this, I would appreciate any suggestions for a more efficient approach.

You can view a CodePen version of the current implementation, which only groups the events by day and not by time.

I have attempted various methods. While I understand that I may need to implement a similar logic for time grouping as I did for date, I am unsure how to handle non-existing arrays in the process of creation, looping, and displaying.

<div id="vue">
  <div v-for="events, day in groupedDays" class="day">
    <h2>{{ day == today ? 'Today' : day }}</h2>
    <div v-for="event, time in events">
      {{ event.date.toLocaleTimeString() }} - {{ event.title }}
    </div>
  </div>
</div>
function groupBy(array, fn) {
  let result = {};
  array.forEach(item => {
    let key = fn(item);

    if (!result[key]) {
      result[key] = [];
    }
    result[key].push(item);
  });
  return result;
}

let conferenceDays = [];

for (let [key, session] of Object.entries(sessions)) {
  // console.log(session.Start);
  conferenceDays.push({
    date: new Date(session.Start),
    title: session.Title
  });
}

new Vue({
  el: "#vue",
  data() {
    return {
      conferenceDays,
      today: new Date().toDateString()
    };
  },
  computed: {
    groupedDays() {
      return groupBy(this.conferenceDays, day => day.date.toDateString());
    }
  }
});

In anticipation of someone referring to this question as a duplicate of a vaguely related query, I want to clarify that despite extensive research, I have not come across any inquiries addressing two levels of groupings. I remain open to alternative solutions if my current approach is suboptimal.

Answer №1

One potential resolution might involve the following approach:

Within the groupBy method, begin by arranging the array in ascending order. Then, convert each day into an object with keys representing the starting hours and values indicating the corresponding conferences commencing at that time.

function groupBy(array) {
  return array 
    .sort((c1, c2) => c1.date.getTime() - c2.date.getTime())
    .reduce((acc, crt) => {
    const k = crt.date.toDateString();
    const hr = crt.date.toLocaleTimeString();

    if (!acc[k]) {
      acc[k] = {};
    }

    acc[k][hr] = acc[k][hr] || [];
    acc[k][hr].push(crt.title);

    return acc;
  }, {})
}

This will result in your html structure appearing as follows:

<div v-for="events, day in groupedDays" class="day">
    <h2>{{ day == today ? 'Today' : day }}</h2>
    <div v-for="conferences, time in events">
      {{ time }} - {{ conferences.join(', ') }}
    </div>
  </div>

You can view the CodePen example here.

Answer №2

To tackle the data wrangling process as suggested, it is advised to follow these three essential steps:

In this implementation, I have opted for utilizing lodash as my preferred data manipulation tool; however, feel free to choose an alternative if you prefer.

The first step involves grouping all the conferences based on their respective days, a task that has already been accomplished. Here's how it can be done:

function groupAllConferencesByDay(all) {
    return _(all)
           .groupBy(conference => conference.date.toDateString())
           .mapValues(groupDaysConferencesByTime) // <---
           .value()
}

Next, for each day, it is necessary to further categorize the conferences according to their specific timeslots. This function can help achieve that:

function groupDaysConferencesByTime(day) {
    return _(day)
           .groupBy(conference=>conference.date.toLocaleTimeString())
           .mapValues(concatTitleOfSimultaniousConferences)
           .value()
}

Lastly, within each timeslot, extract the titles of the conferences and combine them with commas for better clarity. Here is an example of how this consolidation can be performed:

function concatTitleOfSimultaniousConferences(timeslot) {
  return _.map(timeslot, conference => conference.title )
          .join(", ")
         // no need for .value() here since we are using _.map(X, Y)
         // instead of _(X).map(Y)
}

Once the above processes are complete, present the organized data to the user in the following manner:

<div id="vue">
  <div v-for="events, day in groupedDays" class="day">
    <h2>{{ day == today ? 'Today' : day }}</h2>
    <div v-for="conferences, time in events">
      {{ time }} - {{ conferences }}
    </div>
  </div>
</div>

For a practical demonstration, access the provided code sample through the link below:

pen here

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The webpage's Document Object Model fails to refresh following a JavaScript modification

I have encountered an issue with a sample webpage where I am attempting to set the wmode of all YouTube elements on the page to "transparent." When inspecting the page using Chrome, I can see that my JavaScript code is functioning properly. However, the b ...

The agent.add() function is malfunctioning, while console.log() is functioning properly

I'm currently working on integrating a bot using Telegram, Dialogflow, and Firebase. One particular function that I'm struggling with is as follows: function findDoc(agent){ const userId = request.body.originalDetectIntentRequest.payload.dat ...

How to pass the table ID from one webpage to another using jQuery

I am dealing with 3 variations of tables that each have unique id values. My challenge is transitioning from one page to another and landing on the precise table within the new page. I'm uncertain about how to achieve this using jQuery. <table id= ...

Crashes within an HTML5 Canvas

Having recently started to explore Javascript and working with canvas elements, I've encountered a roadblock when trying to implement collision detection for the canvas walls. Typically, I have a small square drawn on the canvas that I can move aroun ...

Reset the idle timeout counter after each AJAX post request

I've implemented the JQuery idleTimeout plugin in an MVC 4 application, using the code snippet below to set the session timer: <script type="text/javascript"> var sessionTimer = 60; $(document).ready(function () { // setup the dial ...

The navigation menu on major browsers, such as Google Chrome, is malfunctioning and not responding as expected

Hope you're having a wonderful day! ☺️ I recently created a responsive navigation menu bar for mobile devices, but it seems to be malfunctioning on some major browsers like Google Chrome and Bing. Instead of displaying the mobile view, it shows t ...

Creating a Scrollable React Form Group

Struggling to display a large amount of data that is not scrollable, how can I make this form group scrollable to easily view all the data? render() { return ( <div style={{width: '50rem', margin: '1rem&ap ...

What is the process for including a collection of objects in chartjs?

Is there a way to add an array of objects to chartjs? In the controller of the view, an array is passed to the Twig template using the variable {{cg}}. However, I am encountering an error that suggests the array I am working with is actually an array of ar ...

"Unlocking the hidden powers within a directive: A guide to accessing inner

I have two directives called container and item. directive('container', function(){ return { replace: true, template: "<div>contains <p>...</p> </div>' } }); directive('item', fun ...

Dealing with a Node and Express server can be tricky, especially when trying to proxy a POST request along with parameters. You might encounter the error

I am trying to forward all requests made to /api/ from my local node server to a remote server, while also adding some authentication parameters to them. Everything works smoothly for GET requests with query parameters and POST requests without specifying ...

When using a custom AJAX function, make sure that bindings are functioning properly when setting properties within a callback in Ember

I've encountered some unexpected behavior while trying to set an Ember property inside a custom AJAX function callback. The AJAX function is triggered in the route, as seen in the code snippet below. The success callback updates the 'session.aja ...

PHP header malfunctioning post AJAX request triggered by JavaScript

Hey there, I have a query that might sound silly to some, but I'm curious if it's feasible to utilize the header function within a php file when receiving an AJAX response. In my scenario, I'm working on a login form where I use AJAX to com ...

Greetings Universe in angular.js

Having trouble creating a Hello World page in angular.js. When I try to display {{helloMessage}}, it shows up instead of Hello World. I'm not sure where the issue lies. Within the folder are two files: angular.min.js and HelloWorld.html. In HelloWorl ...

Having trouble with JavaScript concat function not behaving as it should? Can you provide more details to

I am trying to extract all the cities from an object that contains country names as keys and arrays of cities as values. However, my approach seems to be failing and I can't figure out why. var cities = { "United Kingdom": ['london'], ...

Navigating with the keys is disabled until an item is chosen

Currently working on a Shopify website for a client and encountered an issue where the keys don't scroll down upon page load unless a specific element is clicked or tab is used. I am not sure what caused this unexpected behavior, it may have occurred ...

The variable is constantly reverting back to its initial value

Here is the code snippet: function send() { var nop = 6; var send_this = { nop: nop }; $.ajax({ type: "GET", data: send_this, url: "example.com", success: function(r) { ...

Is there a way for me to obtain the full error message after a failed fetch request?

I'm trying to capture all errors from the fetch function, including the specific red highlighted details as a string: https://i.sstatic.net/GtHxv.png But when I catch an error in my code, all I get is "Failed to fetch." Here's what my code looks ...

Can we improve the coding of this as it seems inefficient and uses up too much room?

Do you think there is a more efficient way to write this code? It seems quite impractical and takes up a lot of space. Essentially, it's about the random chance of obtaining a rarity, like acquiring an Uncommon sword. if (Math.random() * 100 < 100 ...

How can I ensure that Redux-saga waits for API calls to resolve instead of returning promises continuously? Is there a way to make "yield call" wait for API calls to complete?

Where I'm initiating the API request: function fetchCharacter(value){ return axios.get(`https://www.breakingbadapi.com/api/characters?name=${value}`) .then(res=>{ console.log(res.data) }) .cat ...

Can a single static variable be shared among all connections on the server?

I am currently working on a turn-based Chinese checkers game. I have added an onload function in the body that sends an ajax request to the server to obtain the player number for the connection. However, I am encountering an issue where the response always ...