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

I am facing difficulty showing JSON data using Vue.js

I'm having trouble using v-for to display the products array from a JSON data. The attempt to showcase the product data from the array isn't yielding results as expected. Vue.js <div class="box" v-for="product in products" ...

State variables in React hooks like useState always return the previous value before

Whenever I choose a value, it seems to always display the previously selected option instead of the current one. What I really want is for the selection to update and store the current value immediately. const [postsPerPage, setPostsPerPage] = useState(1 ...

Selenium Python Slider Button Element Visibility Issue

Currently, I am developing a parser to automate the process of clicking buttons on a website. However, I am encountering difficulties in clicking two specific buttons. The buttons I am aiming to click are "Elija el imports a financiar" and "Elija la mensu ...

Changes in a portion of the state for Vaadin's AbstractJavascriptComponent

I am currently working on implementing a JavaScript-based component for Vaadin that will be responsible for displaying and updating a large data set. To achieve this, I am extending AbstractJavaScriptComponent. My goal is to keep the JavaScript side as si ...

Capturing a res.send(404) error in ExpressJS during production: Tips and tricks

Can middleware handle errors like 404 and 500 when they are returned this way? exports.index = function(req, res) { res.send(404); } In production, I would want to display a custom missing page for these errors. However, my error handler middleware doe ...

Learn how to retrieve data from a JSON server in Angular 8 and then sort that data in a table by utilizing checkboxes

Currently, I'm in the middle of an Angular project where I could use some assistance on how to filter data through checkboxes within a table. The setup involves a home component that displays data from a JSON server in a tabular format using a service ...

Guide on utilizing VueJS plugins in the browser without any added layers

I have decided to incorporate VueJS into an old system instead of using JQuery. However, I am facing difficulties in utilizing plugins like I would with JQuery. For instance, when trying to import the "vuetable" library directly into my HTML using script t ...

Issue with form validation, code malfunctioning

I am struggling to figure out why this validation isn't working. Here is the HTML code I'm using: <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type='text/javascript' src="scripts. ...

The Toggle Functionality necessitates a double-click action

I'm currently working on implementing a menu that appears when scrolling. The menu consists of two <li> elements and has toggle functionality. Everything is functioning properly, except for the fact that the toggle requires two taps to activate ...

Challenge with row identification in Datatables when rowId begins with a number

In compliance with the Datatables specifications, each row in my table can be assigned a unique ID: $('#myTable').DataTable( { ajax: '/api/staff', rowId: 'staffId' } ); However, it is mentioned in the same specificat ...

The jQuery selectors are not able to identify any dynamically generated HTML input elements

After successfully injecting HTML code into the DOM using Ajax, I encountered an issue where my jQuery selector was not working for a specific HTML input element. For example, when attempting to use the following jQuery code: $("input[id*='cb_Compare ...

I was surprised by how Await behaved in if-else statements, it was not what

let metadata = []; allNFTs.map(async (e) => { if (e.metadata) { metadata.push(JSON.parse(e.metadata).attributes); } else { let config = { method: "get", url: `http://localhost:3000/api/fetch ...

Issue with Angular 2 NgFor Pattern Error Message Display Absence

I am attempting to incorporate inputs with a regex requirement within an ngFor loop, but I am not receiving the expected error message when entering something that does not match the required pattern. Even when I input an incorrect pattern, "Test" remains ...

Enhancing data rendering by incorporating extra verifications through the logical AND operator to prevent crashes upon page refresh

Upon refreshing the page, my app crashed. The issue stemmed from the page loading faster than my data, prompting me to include additional checks using the logical AND operator. While effective in preventing crashes, this approach seems laborious and begs t ...

The unusual behavior of the :to attribute on @click in Vue

I have a specific element: Hashtag.vue: <template> <router-link :to="getTo" custom v-slot="{ navigate }"> <div role="link" @click="navigate"> {{text}}</div> </rout ...

The AWS Cognito User Interface utilizes a hash in order to incorporate parameters during its invocation of the callback page

I'm encountering an issue with the AWS Cognito provided UI interface. When attempting to use the provided UI, I make a call to the endpoint using the populated URL: The issue arises after authentication when Cognito utilizes a # to return the requir ...

Retrieve the attribute from the element that is in the active state

I'm facing a challenge in determining the active status of an element attribute. I attempted the following approach, but it incorrectly returned false even though the element had the attribute in an active state - (.c-banner.active is present) During ...

What is the best way to retrieve an item using a composite key?

const dynamoDB = new AWS.DynamoDB.DocumentClient(); var parameters: any = {}; parameters.TableName = 'StockDailyCandles'; var primarykey = { 'symbol': 'AAPL', 'datetime': '640590008898' }; // sa ...

JavaScript believes that the function is not defined, despite its clear existence

This question pertains to an issue regarding the recognition of Bookshelf.js model function as a function. The error message "Function is undefined, Bookshelf.js model function is not being recognized as a function" arises when trying to POST to the login ...

Ways to bypass mongoose schema validation while making an update request in the API

In my model, one of the fields is specified as providerID: { type: Number, required: true, unique: true }. The providerID is a unique number that is assigned when inserting provider details for the first time. There are situations where I need to update ...