Organizing elements in a javascript array by their attributes using AngularJS

Picture this scenario: a collection of different wines:

[  
   {  
      "name":"wine A",
      "category":[  
         "red",
         "merlot"
      ]
   },
   {  
      "name":"wine B",
      "category":[  
         "white",
         "chardonnay"
      ]
   },
   {  
      "name":"wine C",
      "category":[  
         "white",
         "chardonnay",
         "red",
         "merlot"
      ]
   }
]

I am tasked with creating a filtering/grouping feature using AngularJS. For example, if a user selects "chardonnay", the filtered results should display:

Results: wine B, wine C

Although I have a functioning example, there is a need to review the data structure of that example. It does not define arrays within the object items. What adjustments should be made in the controller to align it with the above (array) structure?

var app = angular.module("myApp", []); 
app.controller("myCtrl", function($scope) {
  $scope.wines = [
    {
      name: "Wine A",
      category: "red"
    },
    ...
   
});

app.filter("capitalizeFirst", function() {
  return function(str) {
    str = str || "";
    return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
  };
});
<script src... angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="myCtrl">
    <div ng-repeat="(prop, ignoredValue) in wines[0]" ng-init="filter[prop]={}">
      <b>{{prop | capitalizeFirst}}:</b>
      ...
      
</div>

Answer №1

To filter, simply utilize the search filter :

<b>Select a category: (Hard coded)</b>
            <ul>
              <li style="cursor:pointer" ng-click="click_filter('red')">red</li>
              <li style="cursor:pointer" ng-click="click_filter('merlot')">merlot</li>
              <li style="cursor:pointer" ng-click="click_filter('white')">white</li>
              <li style="cursor:pointer" ng-click="click_filter('chardonnay')">chardonnay</li>
            </ul>

    <b>Result</b>
          <div ng-repeat="wine in wines | filter:search ">
          <b>{{wine.name}}</b> - (category): {{wine.category}}
          </div>
    </div>

JS:

 $scope.click_filter = function(item) {
         $scope.search = item;
     }

For dynamic categories, you can explore eliminating duplicate entries from ng-repeat (as shown in my Plunker example).

View Plunker:

Answer №2

When transitioning from a list to an array, adjustments need to be made in how options are retrieved and a call to flat() needs to be added

  $scope.getOptionsFor = function(propName) {
    return ($scope.wines || [])
      .map(function(w) {
        return w[propName];
      })
      .flat()
      .filter(function(w, idx, arr) {
        return arr.indexOf(w) === idx;
      });
  };

Subsequently, the filterByProperty function must be capable of handling arrays as well as individual values:

  $scope.filterByProperties = function(wine) {
    // Use this code snippet for AND matching
    var matchesAND = true;
    for (var prop in $scope.filter) {
      if (noSubFilter($scope.filter[prop])) 
        continue;

      if(Array.isArray(wine[prop])) {
          let matchCount = 0;  
          for(let i in wine[prop]) {
            if ($scope.filter[prop][wine[prop][i]]) {
              ++matchCount;
            }
          }
          let trueFilter = 0
          Object.values($scope.filter[prop]).forEach(element => {
              if (element)
                ++trueFilter
          });
          matchesAND = matchCount == trueFilter;
          if (! matchesAND)
            break
      }
      else {
      if (!$scope.filter[prop][wine[prop]]) {
        matchesAND = false;
        break;
      }}
    }
    return matchesAND;
  };

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

Implementing a Singleton Pattern in ReactJS using Context API for Asynchronous Operations

My current implementation involves using a hook: function useFollowUser() { const isFollowing = useRef(false); return (userId) => { if(isFollowing.current) return; // mutual exclusion isFollowing.current = true; ... updat ...

JS, Async (library), Express. Issue with response() function not functioning properly within an async context

After completing some asynchronous operations using Async.waterfall([], cb), I attempted to call res(). Unfortunately, it appears that the req/res objects are not accessible in that scope. Instead, I have to call them from my callback function cb. functio ...

Exchange selection choices among harvested selected boxes

In my project, I am working on swapping all the options between two select boxes. The specific scenario I am dealing with involves recording details of phone calls. These calls can either be inbound or outbound. For outbound calls, I have a 'caller&ap ...

Making API calls using JavaScript

I'm struggling with understanding how to approach this problem in javascript. Here is the question along with the details. I would appreciate any assistance. QUERY We have a server backend that provides two endpoints: /GetLocalPressReleases and /Get ...

PhoneGap switches up the error type with each consecutive run

Why does PhoneGap change errors after every time it is compiled? Sometimes it runs without any issues, but then the same code throws strange errors like parse error or function not found, even though no changes were made to the code. Here is the code that ...

Is it possible to showcase D3 charts on an .epub file?

For my research project, I am exploring the possibilities of .epub files and experimenting with embedding JavaScript code to display data visualizations. I am currently using calibre to convert an HTML file containing D3 scatterplots into an .epub. The s ...

Conceal component while navigating in VueJs

I am working on a Vue project. I am trying to implement a feature where a component is hidden while the user scrolls, but then reappears once the scrolling stops. I have tried using a scroll event, but the component does not show up again. <div c ...

Show the outcome of an HTTP POST request exclusively for the row that corresponds to the button being clicked in AngularJS

As a newcomer to Angular, I am currently working on starting and stopping a Windows service in .Net using AngularJS. The user interface includes fields for server name, the status of the Windows service, and two buttons to start and stop the service. Whe ...

Is it possible to use Ramses to store and search through unstructured data efficiently?

Looking to provide my users with the ability to store unstructured JSON data alongside structured data using an API generated with Ramses. I'm working on making this data searchable and indexed in Elasticsearch. However, I can't seem to find any ...

Update the data in Firebase, but revert it back to the original state after a few seconds with the use of "angularFire."

I'm currently working on updating data in the Firebase Realtime Database using Angular and AngularFire. The issue I'm facing is that even though the data changes successfully, it reverts back to the original data after a few seconds. Below is the ...

Implementing restify on a website that mandates user login authentication

Currently, I am operating a REST API server using restify. In addition, my front-end consists of angularjs with html, css, and js files hosted on an Apache webserver. The next step is to implement user login authentication for this webapp. Access to the w ...

MUI Autocomplete is failing to update the value when onChange event is triggered

I have successfully fetched autocomplete options from an API and it displays the pre-selected options from the API. However, I am encountering an issue where I am unable to delete or add a value (category) once selected. For an online demo, you can check ...

What is the best way to individually update fields using Prisma?

I am facing a challenge with updating fields individually for an object named Post. This object has three fields: title, content, and summary. Situation To save a post in the database, I can fill in just the title field initially and leave the other fiel ...

Can anyone suggest a solution to troubleshoot this issue with CSS Flexbox and absolute positioning?

I'm currently developing a React application featuring flex container cards (referred to as .FilmCard with movie poster backgrounds) within another flex container with flex-wrap. Each card has an item positioned absolutely (an FontAwesome arrow icon). ...

Issue with rendering JSON in Backbone.js -

I am facing a coding challenge: window.TicketCollection = Backbone.Collection.extend({ model:Tickets, url:"/index.php/tickets/viewJSON" }); window.TicketsView = Backbone.View.extend({ tagName:'div', initialize: function () { ...

How does the functionality of $.ajax differ from that of $.get?

Similar Inquiry: Understanding the Variations of $.ajax(), $.get(), and $.load() I'm curious about the disparities between $.get() and $.ajax The given code showcases calls like this: $.get(href) .success(function (content) { $(&apos ...

Utilizing Server-Sent Events to display a interactive navigation button

Currently, I am managing a web-based point of sale system where some buttons are hidden for specific functions. To streamline the process, I would like to allow managers to simply click on an "Enable" button in the admin panel and have it immediately refle ...

Ways to invoke external jQuery functions within Angular applications

In the midst of working on an Angular CLI Project, I find myself needing to incorporate some jQuery functionalities. To accomplish this task, I have added the necessary JavaScript files in the angular.json configuration: "scripts": [ "node_modules/jq ...

Ambiguous limitation regarding noptr-new-declartor

Declaration of noptr-new-declarator: [ expression ] attribute-specifier-seq_opt noptr-new-declarator [ constant-expression ] attribute-specifier-seq_opt The reasoning behind using constant-expression in square brackets for the latter case of allow ...

What is the reason behind Visual Studio intellisense not displaying the methods of XMLHttpRequest objects?

Why am I unable to access the open and send methods of the XMLHttpRequest object in Visual Studio's Intellisense? var httprequest = new XMLHttpRequest(); httprequest. I cannot see the methods in Intellisense after the dot. ...