Verify if a certain value exists in an array while using ng-if inside ng-repeat

Currently, I have a loop using ng-repeat that goes through a list of wines obtained from an API. Alongside this, there is an array variable containing all the IDs of wines that have been marked as favorites and retrieved from the database. My goal is to show an "Add To Favorites" button if a specific wine from the result list has not yet been added by the user. This is what I had in mind for achieving this:

HTML:

<tr ng-repeat="wine in wines">
    <td>{{$index+1}}</td>
    <td>{{ wine.Name }}</td>
    <td>{{ wine.Appellation.Name }}</td>
    <td>${{ wine.PriceMin }} - ${{ wine.PriceMax }}</td>
    <td>
        <!-- Show "Add Button" if wine.Id is not in the favorite ids array -->
        <a href="#" class="btn btn-primary btn-dark" ng-click="addToFavorites(wine.Id)" ng-if="favorites.indexOf(wine.Id) !> -1"> Add </a>
        <!-- Display "Added" if already in favorites -->
        <span ng-if="favorites.indexOf(wine.Id) > -1">Added</span>
    </td>
</tr>

Below is my JS code:

app.controller("MainController", function($scope, $http){
    $scope.favorites = [];
    var getAllFavorites = function(){
        $http.get("/home/getAllFavoriteIds").success(function(response) {
            angular.forEach(response, function(r) {
                $scope.favorites.push(r);
            });
        });
    };
});

I am still new to .indexOf() so there may be an issue with its usage in my case. Any tips or guidance would be greatly appreciated.

Answer №1

If you prefer, you can implement your own filtering function in Angular using the "contains" filter from angular-filter:

<span ng-if="customFilters | contains:searchTerm">Match found</span>

Alternatively, you can create a custom filter with the same functionality:

angular.module('app').filter('contains', function() {
  return function (items, query) {
    return items.includes(query);
  };
});

Answer №2

I suggest transferring this logic to the controller to maintain a cleaner view:

   $scope.checkFavorites = function(id) {
       return $scope.favorites.indexOf(id) !== -1;
   }

Your view should then look like this:

<!-- Show "Add" button if wine.Id is not in the favorite ids array -->
<a href="#" class="btn btn-primary btn-dark" ng-click="addToFavorites(wine.Id)" ng-if="!checkFavorites(wine.Id)">Add</a>
<!-- Display "Added" if wine.Id is already a favorite -->
<span ng-if="checkFavorites(wine.Id)>Added</span>

Answer №3

In my opinion, you should make a modification

favorites.includes(wine.Id) ? false : true

to

favorites.includes(wine.Id) === false

Answer №4

The expression

favorites.indexOf(wine.Id) !> -1
is not a proper Angular syntax. In Angular templates, only basic JavaScript conditionals are allowed. For more information on what is acceptable, refer to the documentation.

Rather than managing separate lists for all wines and favorite wines, it's recommended to enhance the list of all wines by adding a boolean property called isFavorite. This approach not only improves performance but also eliminates the need to search through the second list during each iteration.

A quick solution within the response callback loop would be:

var index = $scope.favorites.indexOf(r.id);
if(index > -1) {
  $scope.favorites[index].isFavorite = true;
} // if not found, isFavorite defaults to falsy

For more efficient array operations like this, consider using libraries such as Underscore or Lodash.

Also, keep in mind that if you have an object containing wines with IDs as keys, you can retrieve wines by ID without the need for index lookup every time. Similar to arrays, ngRepeat supports objects as well.

In your template:

<!-- Display "Add Button" if the wine.ID is not already in the array of favorite IDs -->
<a href="#" class="btn btn-primary btn-dark" ng-click="addToFavorites(wine.ID)" ng-if="!wine.isFavorite"> Add </a>
<!-- Show "Added" if already favorited -->
<span ng-if="wine.isFavorite">Added</span>

Answer №5

Using !> is invalid. You can only use ! with =, or a boolean value. Instead, try:

favorites.indexOf(wine.Id) == -1

The indexOf method returns -1 if the element cannot be found in the array. Thank you for pointing out the mistake. I was stuck on !>

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

Customizing the "Actions" Dropdown in APEX Interactive Grid

Is there a way to modify the choices available in the Selection section of a Row Actions Menu in Apex? I managed to alter the options in the Line Menu, but I'm facing challenges when trying to make changes in the Selection Menu. The Selection Menu i ...

Conceal one element and reveal a different one upon submitting a form

On a web page, I want to hide the form upon submission (either by clicking or pressing enter) and display the results. However, this functionality does not seem to work when the Go web server is running. When I test the HTML file (without executing the Go ...

I'm not skilled in programming, so I'm not sure what the problem is with the code

While working on my Blogger blog, I encountered the need to add a fixed sidebar ad widget that would float along the screen. After trying multiple codes, I finally found one that worked. However, using the template's built-in variable functions led to ...

Error with replacing regular expressions in IE11 for the variable $0

Having both a string and a message: str = "Test $0 $1 $2"; message = "Hi %2 Hello %2" ; The goal is to replace all occurrences of %2 with str in the message using RegExp, like so: message = message.replace(new RegExp("%2" , "g"), str); While this works ...

Guide to creating a delayed response that does not block in Node and Express

I want to implement a delayed response to the browser after 500ms has elapsed. app.post('/api/login', function(req, res) { setTimeout(function() { res.json({message: "Delayed for half a second"}); }, 500); }); The code snippet a ...

The JQUERY code for refreshing a div requires a timeout delay

I'm looking for a way to refresh a specific div on my website that's used for chat. Here's the code I currently have: var refreshId = setInterval(function() { $('#chat_grab').load('chat_grab.php?randval=' + Math.rand ...

Inspect the data attribute and modify the class

I am looking to determine if a data attribute has a specific value and then update the class associated with it. For example, in my HTML code: <li class="country active" data-country-code="ca"><div class="flag ca"& ...

Challenge with setting asynchronous default value in React Material UI Autocomplete

Utilizing the 'Material UI' Autocomplete component to show a dropdown in my form. Whenever the user wishes to edit an item, the dropdown should autofill with the corresponding value fetched from the database. Attempting to simulate this scenario ...

Angular utilizes ZoneAwarePromise rather than a plain String output

I expected the giver code to return a string, but it is returning ZoneAwarePromise. Within the service: getCoveredPeriod() { let loanDetails = this.getLoanDetails().toPromise(); loanDetails.then((res: any) => { const coveredPeriodStart ...

Access user connections through Discord.js bot

Hi there, I'm currently working on creating a bot that can retrieve a user's connected battle.net account and display their game rank. I am utilizing the discord.js library and have been attempting to access the UserProfile through the bot. Unfor ...

How can I dynamically update the URL parameter based on the selected option in a dropdown list?

There is a single select option box with three options. When a user selects an option, the corresponding value should be appended to the URL (e.g., value=needbyDate). If another option is selected later, the previous value in the URL should be replaced w ...

Vue: The function "priceFilter" is not defined in this context

function sanitizeInput(event) { event.target.value = event.target.value.replace(/[^\d.]/g, ""); event.target.value = event.target.value.replace(/^\./g, ""); event.target.value = event.target.value.replace(/\.{2,}/g, "."); event.targe ...

Issue with AngularJs: $http post only posting single item to collection inside a for loop

I have a collection that requires me to post multiple items in a for loop. Below is the code snippet: for(i = 0; i < 28; i++) { var request = $http({ method: "post", url: "/students", ...

Is it possible to deceive Array.isArray?

Although I have a good understanding of prototypes, I encountered some confusion when I attempted the following: var obj = {}; Object.setPrototypeOf(obj, Array.prototype); console.log(Array.isArray(obj)); // false? What's even more perplexing: var ar ...

Ways to Enhance jQuery Efficiency in a Broader Sense

Utilizing jQuery functions is a common practice for us. However, there has been talk about its impact on performance. While it is simple to write, understand, and maintain, some say that it is slower compared to using traditional raw JavaScript code. But ...

What is the reason for the jQuery callBack handler returning [object Object]?

Recently, I created a SessionMgr.cfc file in ColdFusion to manage session variables for my $.ajax calls. However, it seems like I might have made a mistake somewhere. Despite scouring through numerous pages on Stack Overflow and Google, I still can't ...

The email validation UI dialog is failing to display any dialog

<html> <head> <link rel="stylesheet" href="//code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css"> <script src="//code.jquery.com/jquery-1.10.2.js"></script> <script src="//code.jquery.com/ui/1.11.1/jquery-ui.js"& ...

Redirect middleware for Next.js

I am currently working on implementing a log-in/log-out feature in my project using nextjs, redux-saga, and mui libraries. // middleware.ts import { NextRequest, NextResponse } from 'next/server'; import { RequestCookies } from 'next/dist/c ...

Updating a component from a different source

As a newcomer to React, I'm curious about the ability to update one component's content based on events from another component. I have two React components set up. The first component loads data when the page initializes, while the second compon ...

Creating a webpage header with Javascript to mimic an existing design

I am in the process of building a website with 5 different pages, but I want the header to remain consistent across all pages. To achieve this, I plan to use an external JavaScript file (.js). The header includes the website name (displayed as an image) an ...