Create a list using ng-repeat in AngularJS, each item separated by "custom categories"

I am looking to create a dynamic list that will display values entered by users, categorized by custom categories. The challenge is that I do not know in advance which category each element will belong to. Here's an example of how I envision the list being displayed:

Category 1:
- Element 1
- Element 2
- Element 3

Category 2:
- Element 1
- Element 2
- Element 3

My Custom Category:
- Element 1
- Element 2

I attempted to use an ng-repeat along with filtering to avoid duplicate categories. The idea was to first display the category titles and then show the corresponding elements beneath each title using another ng-repeat with an ng-if statement to filter based on the category:

<div ng-repeat="x in elements | unique:'Category'">
     <h2>{{x.Category}}</h2>
     <div class="element" ng-repeat="y in elements" ng-if="y.Category === {{x.Category}}">
        <p class="click-text">{{y.Title}}</p>
     </div>
</div>

This setup is quite messy and I need assistance in finding a cleaner solution.


Here is an example JSON array of elements:

[{
  "Category": "Category 1",
  "Title": "Title example",
  "Comments": "Example comments"
},
{
  "Category": "Category 1",
  "Title": "My cat is named George",
  "Comments": "Example comments"
},
{
  "Category": "Category 1",
  "Title": "Hocus pokus",
  "Comments": "Example comments"
},
{
  "Category": "Category 2",
  "Title": "7 projects going LIVE now",
  "Comments": "Example comments"
},
{
  "Category": "Category 2",
  "Title": "Batman vs Superman was a good movie",
  "Comments": "Example comments"
},
{
  "Category": "Category 2",
  "Title": "projects (more)",
  "Comments": "Example comments"
},
{
  "Category": "Custom Category",
  "Title": "Remember, remember the fifth of november",
  "Comments": "Hello there!"
},
{
  "Category": "Custom Category",
  "Title": "It's night, electric night",
  "Comments": "General Kenobi"
}]

Answer №1

If you want to organize elements by category and iterate through them based on object properties, you can do so by creating an object with categories and their corresponding elements. For a detailed guide on iterating over object properties, refer to the ngRepeat documentation.

Whenever you add a new element, make sure to include it in the object as well, placing it next to other elements within the same category.

Below is a demonstration of this concept in action (take note of how the mapping from categories to elements is established within the vm.init function):

angular
  .module('elementsApp', [])
  .controller('elements', function() {
    var vm = this;
    vm.elements = [{
        "Category": "Category 1",
        "Title": "Title example",
        "Comments": "Example comments"
      },
      {
        "Category": "Category 1",
        "Title": "My cat is named George",
        "Comments": "Example comments"
      },
      {
        "Category": "Category 1",
        "Title": "Hocus pokus",
        "Comments": "Example comments"
      },
      {
        "Category": "Category 2",
        "Title": "7 projects going LIVE now",
        "Comments": "Example comments"
      },
      {
        "Category": "Category 2",
        "Title": "Batman vs Superman was a good movie",
        "Comments": "Example comments"
      },
      {
        "Category": "Category 2",
        "Title": "projects (more)",
        "Comments": "Example comments"
      },
      {
        "Category": "Category invented by me",
        "Title": "Remember, remember the fifth of november",
        "Comments": "Hello there!"
      },
      {
        "Category": "Category invented by me",
        "Title": "It's night, electric night",
        "Comments": "General Kenobi"
      }
    ];
    vm.newElement = {};
    vm.elementGroups = {};

    vm.addElement = function(e) {
      vm.elements.push(e);
      vm.elementGroups[e.Category] = vm.elementGroups[e.Category] || [];
      vm.elementGroups[e.Category].push(e);
      vm.newElement = {};
    };

    vm.init = function() {
      vm.elements.forEach(e => {
        vm.elementGroups[e.Category] = vm.elementGroups[e.Category] || [];
        vm.elementGroups[e.Category].push(e);
      });
    };


  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>

<div ng-app="elementsApp">
  <div ng-controller="elements as ctrl" ng-init="ctrl.init()">
    <form ng-submit='ctrl.addElement(ctrl.newElement)'>
      <input ng-model="ctrl.newElement.Title" placeholder='Title' required>
      <input ng-model="ctrl.newElement.Category" placeholder='Category' required>
      <button type='submit'>Add</button>
    </form>

    <div ng-repeat="(category, elements) in ctrl.elementGroups">
      <h2>{{category}}</h2>
      <div ng-repeat="element in elements">
        {{element.Title}}
      </div>
    </div>
  </div>
</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

Automate populating input fields with data

I need help with a form that has four input boxes. Is it possible to automatically fill the remaining three input boxes with the value entered in the first box when the user clicks a button using JavaScript? Or should I aim to prefill the textboxes with ...

Run a script on a specific div element exclusively

Up until this point, we have been using Iframe to load HTML and script in order to display the form to the user. Now, we are looking to transition from Iframe to DIV, but we are encountering an issue with the script. With Iframe, the loaded script is onl ...

Can you provide instructions on how to display data in two lines within a mat-select field?

Is it possible to show selected options in mat-select with long strings in two lines within the same dropdown? Currently, the string appears incomplete. You can see an example of this issue here: incomplete string example <mat-form-field class="f ...

Is there a way to eliminate the legend symbol for just one legend in Highcharts?

Looking to customize a legend in Highcharts but facing limitations due to Plot Lines and Bands not having legends. To work around this, I have added an empty series that acts as a toggle for showing/hiding plot lines. Since my plot lines are vertical, I im ...

Steps for creating a basic table filter using jQuery

What is an efficient way to create a basic table filter using jQuery without pagination requirements? I want to retrieve data from a database and display it as a list. I would like to avoid using plugins and instead opt for concise code snippets. For ...

Add data to a nested array with Vuex

Currently, I am facing a challenge with adding an object to a nested array in Vue using store / vuex. While I have successfully updated the main comments array with a mutation, I am struggling to identify the specific main comment to which the new reply ob ...

No matter how hard I try, I can't seem to get any of my jQuery events to function properly on my

Help! I'm encountering issues with jQuery on my webpage. It's not functioning at all, despite my extensive search for a solution. Feeling desperate, I'm reaching out for assistance here. Below are my HTML and JS files: HTML <html> ...

The Price Filtering feature in the MERN Stack for Products is currently experiencing technical difficulties

Hey there! I am currently working on developing an Ecommerce Application using the MERN Stack with redux. I've encountered a problem while trying to send a price array argument in my fetching function. The error message states: XHR GET http://localhos ...

Searching for variables within files using Node.js and constructing an object from the results

Trying to figure out how to streamline this process. Here's the directory structure I'm working with: src/ modules/ clients/ i18n/ en-US.ts tasks/ i18n/ en-US.ts So, ea ...

Creating a dynamic dropdown menu to display nested arrays in Vuejs

I have some important data Challenge I'm facing difficulty in accessing the tubes array within my data Solution script data() { return { types: [] } }, methods: { handleChange ...

There has been a mistake: The module '.... ode_modules erser-webpack-plugindistindex.js' cannot be found. Please ensure that the package.json file contains a correct "main" entry

After setting up Vue.js and executing npm run serve, I encountered the following error: PS C:\Amit\Demo\VUEDemo\myvue> npm run serve > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="98f5e1eeedfdd8a8b6 ...

Tips for creating a scale animation using HTML5 Canvas

I am currently developing a canvas whiteboard tool and I have reached the stage where I am focusing on implementing the Zoom In and Zoom Out feature. While the functionality is working fine, I would like to enhance it with smooth animations for scaling. H ...

I'm looking to display 9 images on a single page that rotate every 5 seconds between 3 different images. While I can figure out how to display one image easily, I'm

<script type="text/javascript"> var currPic = 1; var totPics = 9; var keepTime; function setupPicChange() { keepTime = setTimeout("changePic()", 5000); } function changePic() { currPic++; if (currPic > totPics) currPic = 1; var f ...

After the rendering process, the React Component member goes back to a state of

One issue I encountered is related to a component that utilizes a separate client for making HTTP requests. Specifically, when trying to use the client within a click event handler, the call to this.client.getChannel() fails due to this.client being undefi ...

What is the reason behind utilizing the external 'this' within the inner function in Vue: $this=this?

Recently, I came across some code online that included a line $this=this. My initial interpretation was that this line assigns the 'this' of the outer function to a variable, allowing it to be used in the inner function as well. However, upon fur ...

What are the steps for integrating connect-multiparty into route paths?

I am looking to incorporate connect-multiparty into my routes. Upon researching, I found the following example... var multipart = require('connect-multiparty'); var multipartMiddleware = multipart(); app.post('/upload', multipartMiddle ...

JavaScript program that continuously reads and retrieves the most recent data from a dynamically updating JSON file at regular intervals of every few seconds

I am a beginner in JavaScript and I'm facing an issue with displaying the most recent values from a .json file on an HTML page. The file is updated every 10 seconds, and I am also reading it every 10 seconds, but I'm not getting the latest data. ...

Utilize Function to Gain Access to React Context

As I work on developing a package that enhances the responsiveness of my React widget, I have encountered an issue. The responsiveness now relies not on the viewport width, but rather on the width of the widget container element. Presently, I am wrapping ...

Utilizing headless Chrome to automatically capture AJAX requests

Chrome officially supports running the browser in headless mode, allowing for programmatic control through the Puppeteer API and/or the CRI library. I've thoroughly explored the documentation but have not discovered a method to programmatically captu ...

ng-model establishes a connection with objects, not properties

Having just started my journey with AngularJS and JavaScript, I decided to create a simple app that allows users to input their name and age, and then displays the list of users and their ages. Here is the code I put together: var main = angular.module( ...