Create a list that starts with a header determined by an object's attribute within an array

Currently in Vue, I am attempting to create a list based on a specific property within an object. The array being retrieved from the vuex store is structured as follows:

const array = [
 { 
   name: "British title string"
   nationality: "British"
 },
 { 
   name: "Another title"
   nationality: "American"
 },
 { 
   name: "Name"
   nationality: "Dutch"
 },
{ 
   name: "Another american item"
   nationality: "American"
 },
];

The desired outcome involves presenting the data using v-for in the following manner:

<h2>British</h2>
<ul>
   <li>British title string</li>
</ul>

<h2>American</h2>
<ul>
   <li>Another title</li>
   <li>Another american item</li>
</ul>

<h2>Dutch</h2>
<ul>
   <li>Name</li>
</ul>

I have managed to sort the array by the nationality property through lodash _.sortBy resulting in an array sorted by nationality. However, my goal is to include an H2 element that displays the value of the respective nationality.

Answer №1

If you need to group multiple items by their nationality and then sort them, you can achieve this by using _.groupBy() followed by _.sortBy():

Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
  el: '#app',
  template: '#appTemplate',
  data: () => ({
    rawData: [{
        name: "British title string",
        nationality: "British"
      },
      {
        name: "Another title",
        nationality: "American"
      },
      {
        name: "Name",
        nationality: "Dutch"
      },
      {
        name: "Another american item",
        nationality: "American"
      }
    ]
  }),
  computed: {
    groupedItems() {
      return _.sortBy(
        _.map(
          _.groupBy(this.rawData, 'nationality'), 
          items => ({
            items,
            nationality: items[0].nationality
          })
        ), 
        ['nationality']
      );
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script type="text/template" id="appTemplate">
  <div>
    <template v-for="group in groupedItems">
      <h2 v-text="group.nationality" />
      <ul>
        <li v-for="(item, index) in group.items" :key="index" v-text="item.name" />
      </ul>
    </template>
  </div>
</script>
<div id="app"></div>

To simplify the grouping process for better readability, I have mapped the first item's nationality as the group's nationality (with the name items), but you could have directly used the nationality of item 0 in the template instead.
To illustrate, here is how you would do that:

Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
  el: '#app',
  template: '#appTemplate',
  data: () => ({
    rawData: [{
        name: "British title string",
        nationality: "British"
      },
      {
        name: "Another title",
        nationality: "American"
      },
      {
        name: "Name",
        nationality: "Dutch"
      },
      {
        name: "Another american item",
        nationality: "American"
      }
    ]
  }),
  computed: {
    groupedItems() {
      return _.sortBy(
        _.groupBy(this.rawData, 'nationality'), 
        ['0.nationality']
      );
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script type="text/template" id="appTemplate">
  <div>
    <template v-for="grouped in groupedItems">
      <h2 v-text="grouped[0].nationality" />
      <ul>
        <li v-for="(item, index) in grouped" :key="index" v-text="item.name" />
      </ul>
    </template>
  </div>
</script>
<div id="app"></div>

Both examples above generate the necessary markup. If you want each item to have its own wrapper, you can replace <template> with an html tag and add keys. For example:

<article v-for="(grouped, key) in groupedItems" :key="key">

Answer №2

If the array is ordered, you can easily achieve this:

    const list = [
      {
        title: "Another item",
        category: "Fruit"
      },
      {
        title: "Second fruit item",
        category: "Fruit"
      },
      {
        title: "Vegetable name",
        category: "Vegetable"
      },
      {
        title: "Food item",
        category: "Meat"
      },

    ];
    const organizedList = [];
    var j = 0;
    for (var i = 0; i < list.length;) {
      console.log(list[i].title);
      organizedList.push({
        category: list[i].category,
        items: [list[i].title]
      });
      i++;
      while ( i < list.length && list[i].category === list[i - 1].category) {
        organizedList[j].items.push(list[i].title);
        i++;
      }
      j++;

    }
    console.log(organizedList);

In your HTML file:

<div v-for="element in organizedList">
  <h2>{{ element.category }}</h2>
  <ul>
    <li v-for="item in element.items">
      {{ item.title }}
    </li>
  </ul>
</div>

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 variable (form.onsubmit) remains unset even after assigning a value

function setFormOnSubmit(formName){ if(!formName) return; var form = document[formName]; form.onsubmit = function(){ console.log('This is the onsubmit function'); }; console.log('onsubmit successfully set ...

Tips for revealing a hidden div by clicking on another div?

I have a Google visualization chart inside a div tag. I would like to display this chart in a pop-up box when clicking on the chart's div. I am utilizing jQuery for this feature. ...

How to locate the index.js file within my application using Node.js?

Directory Structure bin - main.js lib - javascript files... models - javascript files... node_modules - folders and files public - index.html route - javascript files... index.js package.json I am using Express and angular.js. The ser ...

Is there a way to assign each MySQL result to a separate variable while maintaining just one connection to the database?

I'm in the midst of a personal project and I could really use your expertise. Despite hours of research, I haven't been able to find a solid solution to my problem (likely because my PHP skills are still a work in progress). Here's the deal ...

Transform uploaded image file into a blob format and store it in a VueJS database

I am facing an issue with my form that has multiple inputs, including one of type "file". My goal is to upload an image and then submit the form to the API for storage in the database. <input name="image" class="w-full border-2 border-gray-200 rounded-3 ...

Communication between Angular Controller and Nodejs Server for Data Exchange

Expanding on the solution provided in this thread, my goal is to implement a way to retrieve a response from the node server. Angular Controller $scope.loginUser = function() { $scope.statusMsg = 'Sending data to server...'; $http({ ...

Testing the updated version 18 of Create React APP index.js using Jest

Previously, I had this index.js file created for React version <= 17. import React from 'react'; import ReactDOM from 'react-dom'; import App from './views/App'; import reportWebVitals from './reportWebVitals'; im ...

Image transformed by hovering effect

I've been attempting to add a hover effect to the images in my WordPress theme. The images are displayed in a grid format, created by the featured image on the posts. The grid layout is controlled within content.php <?php /** * controls main gri ...

Having trouble with the rendering of the Stripe Element Quickstart example

Currently, I am diving into the world of Stripe's Element Quickstart. Take a look at this fiddle that I have been working on. It seems to be quite different from the example provided. Although I have included the file, I can't seem to figure out ...

Having issues with Vue.js and the splice method not functioning properly on an array row

Having an Object array, I noticed that when I try to remove an object from the array list, only items are deleted from the end. <div class="hours" v-for="(time, index) in hour" :key="index"> So, I decided to place a cli ...

Tips for customizing your MUI slider design

import * as React from "react"; import Box from "@mui/material/Box"; import Slider from "@mui/material/Slider"; function valuetext(value) { return `${value}°C`; } export default function RangeSlider() { const [value, se ...

What is the method to retrieve the exact value of {match.params.id} in React Router?

This is an example of code that I have. However, I am unsure about how to extract the value and utilize it afterwards. class CustomView extends Component { componentDidMount() { var uniqueId = {match.params.id} } render() { ...

Getting variables from different functions in Python can be achieved by using the return

I am trying to implement a feature where I can fetch a search term from the function getRandomVideo() and then use it in a jQuery statement. For example, if I get "Beethoven" as the search term from the variable searches, I want to use it to retrieve JS ...

Is it feasible to access a variable outside the scope of a function if it is initially created within the scope of another function that returns a function using that same variable?

function creatPrintNumFunction() { var num= 12; return function printNum() { console.log(num); } } var printer = creatPrintNumFunction(); printer.num =13; //this part doesn't work but is there a way to access this Num variable Outside t ...

Struggling to successfully toggle the visibility of items

I am currently facing an issue with displaying different sets of data based on button clicks. The first block of information is showing correctly upon page load, but when I try to display other blocks by clicking on the corresponding buttons, the info cont ...

Problems with Google Maps Event Tracker

I recently inherited a section of code that utilizes the Google Maps API to place markers on a map along with information windows. Below is an excerpt from the code responsible for creating the markers and setting up event listeners: if(markers.length > ...

The React loader fails to function properly when used with nested routes

I'm currently working on my App.js file where I have defined all the routes for my application. I wanted to implement React-Router data loader functionality. import React from 'react' import { Routes, Route, Navigate, RouterProvider, createB ...

What is the best way to prevent a jQuery hover event from adding a text-shadow to the CSS?

Currently, I am facing an issue with a jQuery event that triggers a text-shadow effect: $(".leftColumn").hover(function (){ $(".leftColumn h2").css("text-shadow", "0px 2px 3px rgba(0, 0, 0, 0.5)"); },function(){}); The problem arises when the text-shad ...

Bypassing the "Your connection is not private" error in NodeJS + Express with fetch() using Javascript

Presently, I have a setup with a NodeJS + ExpressJS client-side server that communicates with the back-end server via API calls. However, every time I make a call, I need to manually navigate to the URL of the API back-end server and click on Advanced -> P ...

I'm encountering difficulties in utilizing Ajax to upload images

I have been attempting to utilize ajax and bootstrap (modal) to add a new product. However, when I click the save changes button, I encounter an issue where all fields return an error message stating 'Undefined index'. Below is the code snippet ...