Implementing an object as a filter in an NG-repeat function

I've created multiple select dropdowns that are populated from a JSON file containing categories.

My goal is to use the selections made by users in the dropdowns to filter a list of apps generated using ng-repeat.

In my Plunker example http://plnkr.co/edit/ipfVfH3pbLoYk1u4n3la?p=preview, the user choices are stored in an object, but I am unable to use this as a filter for ng-repeat according to what I have been told.

Is it possible to utilize these selections for filtering purposes, or can they be converted?

This issue stems from a previous post of mine - Dynamically create multiple dropdowns angularjs from a single JSON file

I also have an alternate version rendering each select individually. It employs a custom groupBy filter (using underscore):

app.filter('groupBy', ['$parse', function ($parse) {
  return function groupByFilter(input, groupByExpr) {
    return _.groupBy(input, $parse(groupByExpr));
  };
}]);

Here's how it looks:

<div ng-repeat="(categoryTypeName, categories) in groupedCategories track by categoryTypeName">
  <label>{{categoryTypeName}}</label>

  <select
    ng-model="selected[categoryTypeName]"
    ng-options="c as c.name for c in categories track by c.id"
    multiple
  ></select>
</div>

Unfortunately, applying the filter has to be done when the data changes,

$scope.$watchCollection('categories', function (categories) {
  $scope.groupedCategories = groupByFilter(categories, 'categoryType.name');
});

This is necessary because directly using it with ng-repeat will trigger an Infinite $digest Loop error in AngularJS.

So, can the output (users' choices) be used to filter the repeat items?

What I need is to filter the apps based on the selected category name. If an app is not tagged with the chosen category, it should not be displayed. Each app can be tagged with any available tags from the dropdowns.

--- ADDITIONAL INFORMATION ---

In the same controller as the filters mentioned above and in the Plunker demo, the list of displayed apps will also be managed. They will be located within the same view, similar to the image I currently have. Parts of the image have been blurred for privacy reasons.

https://i.sstatic.net/NBtOH.jpg - apologies for the low-quality screenshot.

The ng repeat structure I'm currently using for the apps is;

<div class="col-md-4"
                            ng-repeat="app in objects | filter:query |orderBy:'-createdAt'">

'Query' here refers to a simple search input box.

To generate the dropdowns for multiple choice selection, I'm using this repeat block;

<div ng-repeat="(categoryTypeName, categories) in groupedCategories track by categoryTypeName">
  <label>{{categoryTypeName}}</label>
<br>
  <select  class="form-control" multiple class="span4 chzn-select" chosen data-placeholder=" "
    ng-options="c as c.name for c in categories track by c.id"
    ng-model="selected[categoryTypeName]"

  ></select>

The 'Chosen' plugin is utilized to enhance the visual display of multiple selections.

Each displayed app can be clicked on to access more details. Apps can have one or multiple tags, all of which can be filtered by using the dropdown menus created.

As seen in the image provided, users can filter by selecting multiple categories from any of the categoryTypes. The specific request from stakeholders is to keep each filter dropdown separate and allow users to choose multiple categories from different types to apply filters.

The following code snippet illustrates the controller responsible for generating the apps;

$scope.objects = [];


  $scope.getData = function (cb) {
            return appFactory.query(function (data) {
                $scope.objects = data;
                if (cb) cb();
            }, function(data) {
                alert("ERROR getting all applications");
            });
        };

$scope.getData();

var successCallback = function (e, cb) {
        alertService.add("success", "Success!");
        $scope.getData(cb);
    };

'cb' represents a successful callback function declared in the controller.

And here is the factory definition:

.factory('appFactory', function ($resource) {
        return $resource(
                 'resources/appstore/applications/:id', 
            { id:'@id' }, 
            { 'update': { method: 'PUT'} }  
        );
    })

The desired functionality involves dynamically filtering apps as users make selections, similar to the text search demo in AngularJS, where apps matching the criteria are shown. Removing a category from the filter list should also update the displayed apps accordingly. I hope that clarifies the requirements.

I believe this covers all the information needed. If there are any crucial details missing, please feel free to let me know.

Answer №1

To address this issue, I suggest implementing a custom filter once again. You can try the following approach (utilizing underscore):

app.filter('bySelectedCategories', [function () {
  return function bySelectedCategoriesFilter(input, selection) {
    var categoryNames = _.flatten(_.map(selection, function (categories) {
      return _.pluck(categories, 'name');
    }));

    return _.filter(input, function (app) {
      return _.difference(categoryNames, app.categoryNames).length === 0;
    });
  };
}]);

This solution functions by:

  1. Retrieving the selected categoryNames,
  2. And then filtering the apps based on the difference from the selected categories.

Demonstration available at: http://plnkr.co/edit/wAyfBgjLBSS0KcN008ru?p=preview

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

.Certain IDs on a website may not respond to clicks due to various reasons

I have created a JavaScript file to automatically click a button on a website using a Chrome extension. When testing the code using Chrome Script snippet, I noticed that it worked for some IDs but not for others. Can someone please help me with this issue? ...

Error: [$injector:modulerr] was not properly handled and resulted in an un

Header.html is located here <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script> <!-- Angular Includes --> <script type="text/javascript" src="{% static 'js/myHeader.module.js' %}"& ...

Learn how to create a fading effect for an element when the mouse is inactive, and have it fade back in when the mouse is active again using J

There is a div with the ID "#top" that I want to have fade out after 3 seconds of mouse inactivity. Once the mouse is moved again, I would like it to fade back in. Any suggestions on how to achieve this effect? Appreciate your help! ...

What could be causing jQuery animate to malfunction on mobile devices when a viewport is present?

Everything seems to be working fine on my desktop webpage, but when I try it on mobile, there is no scroll... $("HTML, BODY").animate({ scrollTop: 500 }, 1000); This post suggests that mobile devices may not scroll on the body, but on the vi ...

Whenever a menu option is clicked in Umbraco, the page always redirects to the route #/content

After updating my site to the latest version available, I encountered a problem: Whenever I click on any link in the menu on the admin page (/umbraco) The temporary solution I discovered is Click on the link Go to profile Edit Confirm that you want to ...

Error: res.send is not a valid method in Node.js

I am encountering an issue with the code below, specifically receiving an error stating "res.send is not a function". I would appreciate any assistance. Code Snippet: var http = require('http'); var fs = require('fs'); var connect = ...

What is the best way to convert a graphql query into a JSON object?

I'm facing an issue where I need to convert a GraphQL query into a JSON object. Essentially, I have a query structured like the example below, and I'm seeking a method to obtain a JSON representation of this query. Despite my efforts in searching ...

Every time I try to retrieve my JavaScript code, I am bombarded with endless prompts that prevent me

Desperate for assistance! I have been using a website called "codepen" for my javascript coding, but I mistakenly triggered infinite prompts every time I open the project. Now, I am unable to access the code and despite my efforts in searching for a solu ...

A more concise approach to crafting ajax requests

Lately, I've been immersed in building various web applications using php, mysql, jquery, and bootstrap. Now, I'm faced with a common issue - how to streamline my ajax queries for posting data? Writing code that is not only functional but also a ...

Link the Material-ui ToggleButtonGroup with redux-form

I'm currently facing a challenge with connecting the material-ui ToggleButtonGroup to Redux form. The issue seems to be occurring in my code snippet below: <Field name='operator' component={FormToggleButtonGroup} > <ToggleButt ...

Problem importing npm module with Meteor 1.3

I've been trying to follow the guide for using npm packages in Meteor 1.3, particularly focusing on installing the moment npm module. However, I can't seem to work it out despite its simplicity. Every time I attempt to use the package in the cli ...

searchByTextContentUnderListItemAnchorTag

I would like to utilize the getByRole function for writing my test. However, I am encountering issues when using linkitem or 'link' as the role. It seems that I cannot find the desired element. // encountered error TestingLibraryElementError: The ...

When using create-react-app with JEST to run tests, TypeScript errors are not displayed

When I write incorrect TypeScript code in my project set up with create-react-app, running tests using npm test does not show any errors in the terminal. Is this normal behavior? It would be helpful to see these errors to avoid writing incorrect TypeScript ...

Obtain output from a callback function

Is there a way to set a variable using the code var myVar = myFunction(); when myFunction contains a callback function that prevents it from returning a value directly? I am unsure of how to modify this code in order to allow for a return value from the ...

In the ajax call, an empty JSON array object is sent as the data

Utilizing JSON data as a parameter for an ajax call: var startDate = dateFormatForSave($("#start_date").val().trim()); var arrayOfStudentsInfo = []; var table = $("#selected_students"); table.find('tr').each(function(i, el) { var rowId = $( ...

What is the best way to switch between three different menus and ensure that the last selected menu remains open when navigating to a new page

My knowledge of javascript, jquery, and php is pretty much non-existent, unfortunately. I only have a grasp on html and css at the moment. However, I will be starting school to learn these languages in the fall! The issue I am currently facing is creating ...

One-of-a-kind browser identification for users, no login required

I have an online boutique and I want to enable customers to make purchases without creating an account. To achieve this, I need a way to associate a selected list of items with a user. Initially, I considered using the IP address for this purpose but fou ...

Using Formik inside Material-UI's table components

My goal is to design a material UI table where each cell acts as a Formik input. However, I've encountered errors with Material UI when attempting to use a Formik Object within TableBody or TableItem tags. Here's an example image of what I' ...

Is it possible to decrease the size of a div by scrolling both vertically and horizontally?

Can a div's height and width both be reduced at the same time while scrolling down a page? Let's say that as the user scrolls, the size of the div changes from 400px by 400px to 200px by 200px, all while remaining centered on the page. I've ...

Transforming Thomas J Bradley's signature pad JSON into a PNG file using C# programming language

I have been experimenting with the Signature Pad plugin developed by Thomas J Bradley and successfully converted JSON signature to PNG using PHP. Now I am looking to achieve the same result using C#. There is a supplemental class called SignatureToImageDo ...