How to use Angular ngRepeat to create multiple select fields that do not show previously selected data with ng-options

Looking at the issue from a high level; I'm fetching data from an api and creating a CRUD page for it. The user can choose from a set of labels provided in the data.

Here is a code snippet illustrating my dilemma. The selected labels are denoted by the user.labels relationship, while the complete list of available labels that can be chosen from is represented by user.parent.grandparent.labels.

I've managed to sync the selection process. However, what's proving to be challenging is how to dynamically remove options that have already been selected from the list of choices in subsequent select fields.

angular.module('app', [])
  .controller('select', ['$scope', '$filter', '$location',
    function($scope, $filter, $location) {
      $scope.user = {
        "parent": {
          "grandparent": {
            "labels": [{
              "id": 28,
              "name": "Label 1",
            }, {
              "id": 17,
              "name": "Label 2",
            }, {
              "id": 39,
              "name": "Label 3",
            }, {
              "id": 77,
              "name": "Label 4"
            }, {
              "id": 100,
              "name": "Label 5"
            }]
          }
        },
        "labels": [{
          "id": 28,
          "name": "Label 1",
          "meta": {
            "score": 3
          }
        }, {
          "id": 17,
          "name": "Label 2",
          "meta": {
            "score": 5
          }
        }]
      };
    }
  ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="app" ng-controller="select">
  <div ng-repeat="label in user.labels track by $index">
    <div class="form-field">
      <span>Label</span>
      <select ng-model="user.labels[$index]" ng-options="department.name for department 
                        in user.parent.grandparent.labels track by department.id">
      </select>
    </div>
    <div>
      <span>Score</span>
      <select ng-model="label.meta.score">
        <option value="1">1 (lowest)</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5 (highest)</option>
      </select>
    </div>
  </div>
  <button ng-click="user.labels.push({})">Add Label</button>
</div>

Answer №1

If you want to filter items inside ng-repeat, you can achieve this by using a filter function. Check out this sample Codepen for reference:

Sample Codepen

Simply pass the filter in the repeat definition like this:

<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | filter:removeSelected track by department.id ">

The filter function is defined on the scope as follows:

      $scope.removeSelected = function(val){
        return !_.find($scope.user.labels, function(label) {
          return label.id === val.id;
        });
      };

However, keep in mind that this approach may cause issues if you also want to include the currently selected label in the options.

Update:

I've come up with an optimized filter function that seems to work well for this scenario:

.filter('duplicatesFilter', function() {
        return function(items, index, selected) { 
          var res = [selected[index]];
          _.forEach(items, function(item){
            if(!_.find(selected, function(label) {
              return label.id === item.id;
            })){
              res.push(item);
            }
          });

          return res;
        };
    })

Usage example:

<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | duplicatesFilter:$index:user.labels track by department.id "></select>

If needed, I'll continue to explore custom filters to enhance this solution further. In the meantime, feel free to use this code for your specific use-case.

Code-pen link for reference:

Codepen Link

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

Issue with Jquery firing function during onunload event

I'm having trouble adding a listener to a form in order to trigger an ajax call when the user leaves it. I can't seem to identify any errors in Firefox and nothing is getting logged in the console, indicating that my code might be incorrect. As s ...

What are the steps to incorporating HTML code into JavaScript?

Can I insert HTML elements into the view using JavaScript? I am hoping to achieve something like this: <script> <% for @m in @messages %> <h1>i</h1> <% end %> </script> I need it to work seamlessly with Ruby. Not s ...

Top-notch strategy for creating Node Package Manager packages that are interdependent

As we work on developing two React-based applications, let's call them app-a and app-b, we also manage two dependencies. One is a shared-components package, which contains components shared between the two applications, and the other is a shared-utili ...

Utilizing Global Variables and Passing Values in Ionic 3

It seems like my issue is rather straightforward, but there is definitely something eluding me. After logging in, I need to store a TOKEN for HTTP requests in a global variable. Upon successful login, the HTTP get method returns an object with the HTTP co ...

Tips for creating a responsive background image that adjusts after resizing the window to a certain width

Is there a way to create a responsive background-image that adjusts when the window is resized to a specific width, similar to the main image on ? ...

nextJS does not recognize the term 'Window'

I'm encountering the error "window is not defined" in my NextJS project. The variable isMobile determines whether the window size is less than 767.98 to handle the hamburger menu functionality. This code worked in ReactJS but seems to be causing issue ...

Entity Framework and the GET request error: Connection Reset

Currently, I am working on developing a straightforward notes application using Entity Framework in ASP.Net Core for the backend and AngularJS for the frontend. The main objective is to have the app load a pre-existing list of notes from my MySQL database ...

Don't forget the last click you made

Looking for a way to style a link differently after it has been clicked and the user navigates away from the page? Check out this code snippet I've been using: $(document).ready(function(){ var url = document.URL; function contains(search, find) { ...

Transmit JSON data using Autobahn Python

I am attempting to use sendMessage to send the json content from a URL to a client. def broadcast(self): response = urllib2.urlopen('http://example.com/json?as_text=1') data = json.load(response) for c in self.clients: c.sendMessage( ...

Using JQuery's change function with a Button Group is a great way

I encountered an issue where my button group works with the on.click function but not with on.change. <div class="ui buttons"> <button class="ui button">Value 1</button> <button class="ui bu ...

Javascript Mouse Events Not Functioning Properly with Three.JS Scene Components

Currently feeling quite perplexed (probably due to fatigue from working on this at an inopportune time). I'm in the midst of trying to configure my three.js application to trigger distinct functions based on different mouse events when the cursor hove ...

step-by-step guide for resolving issues with downloading files in node.js

I've been attempting to download files from my server using node.js with the res.download function from Express, but I keep getting an undefined error. The folder path is D:\program\web\java_script\Node\my_project\ketabk& ...

Why aren't methods for JavaScript objects being identified as expected?

My current project involves creating an avatar that follows the movement of my mouse. After successfully developing a functional avatar, I'm now looking to replicate it using an object constructor. The only difference is that instead of var angleToBe ...

Two Elements Linked Together

I'm facing an issue with my interconnected React components. Despite being separate entities, they appear to share some styling attributes which I find puzzling. The main problem lies in the footer component as it seems linked to another component, p ...

Is there a way to assign the scroll event context to `document.body` instead of `window`?

Discovery As I delved into the intricacies of web development, I stumbled upon a curious observation. In a particular MDN page, I noticed that the left and right sidebars had their scrollbars contained within themselves. However, the content block's ...

A beginner's guide to retrieving random names and images from JSON data for every object using JavaScript

I have a creative idea for a random ruffling game, where it picks a user's name and image randomly. However, I'm facing an issue with ensuring that each image matches the correct user when selected randomly. I want to make sure that every objec ...

The value of insertId is not being properly displayed

I am struggling to retrieve the last insert ID, as it always returns undefined Below is the API code: app.post('/post', (req, res) => { connection.query(`INSERT INTO tradeoffers (DCID, DCNAME, CATEGORY, IGN, ITEM1, Q1, ITEM2, Q2) VALUES (&q ...

Array of initials for full names in JavaScript

const nameList = ['John Doe', 'Jack Lock', 'Nick Load']; const initials = nameList.map([n]) => n); console.log(initials); I'm attempting to display the initials of the array items, but I'm only able to retrieve t ...

Is there a way to adjust the padding temporarily?

Important Note: Despite the misleading title of my question, it doesn't accurately reflect my actual query (sort of). Below is the code snippet in question: .one{ background-color: gray; } .two{ padding: 20px; } <div class = "one"> < ...

Tips for transferring PHP variables into JavaScript variables?

Using PHP variables fetched from a database to populate JavaScript variables is an essential task that needs to be done. One way to achieve this is by defining JavaScript variables as shown in the code example below: var oMain = new CMain({ mon: <?p ...