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

Having a Jquery resizing problem? No worries! When the width is less than 768, simply enable the click option. And when the width is

HTML <div class="profile"> <a href="#" class="hoverdropdown" onclick="return false;">Profile</a> <ul class="dropdown" style="display: none;"> <li><a href="#">Dashboard&l ...

NextJS Router delays data reloading until page receives focus

Struggling with creating an indexing page in NextJS. Attempting to retrieve the page number using the router: let router = useRouter() let page = isNaN(router.query.page) ? 1 : parseInt(router.query.page); This code is part of a React Query function withi ...

Does combineLatest detach this from an angular service function?

Check out this test service on Stackblitz! It utilizes the combineLatest method inside the constructor to invoke a service method: constructor() { console.log("TEST SERVICE CONSTRUCTED") this.setParameters.bind(this) this.assignFixedParamete ...

sw-precache-webpack-plugin for webpack's default service worker template

When utilizing the sw-precache-webpack-plugin to create a service worker for my project, I've noticed that while all my fonts, js, and css files are stored in the cache storage, the index/html file is missing. This has resulted in it not functioning p ...

Transform a log file into a JSON structure

In my log file titled request.log, the following entries are present: [2022-06-30T09:56:40.146Z] ### POST https://test.csdf/auth/send_otp { "method": "POST", "headers": { "User-Agent": "testing&q ...

What are the steps for setting up jScroll?

As a newcomer to JS & jQuery, I appreciate your patience. I've been working on creating a dynamic <ul> list using JS, and I'm happy that it's finally coming together. Now, my next step is to incorporate infinite scrolling into my ...

Controlling the Quantity of Selected Checkboxes with JavaScript

I am facing an issue with implementing multiple checkboxes with limits in JavaScript, as shown below. $(".checkbox-limit").on('change', function(evt) { var limit = parseInt($(this).parent().data("limit")); if($(this).siblings(':checked&ap ...

The issue persists as AJAX data and text box data are not being saved simultaneously

I need assistance with an Ajax setup. I am trying to pass the screenwidth information along with a user input value from a text box to a PHP page. However, I am encountering issues as the only value being passed is from the textbox and the other one is sho ...

Creating sitemaps for multi domain websites using NextJS

We are implementing a next-sitemap package to generate sitemaps for our Next.js pages located in the /pages directory. For pages that come from the CMS, we use server-sitemap.xml with SSR. Despite having 6 different domains, we manage them within a single ...

Maximizing Performance: Enhancing Nested For Loops in Angular with Typescript

Is there a way to optimize the iteration and comparisons in my nested loop? I'm looking to improve my logic by utilizing map, reduce, and filter to reduce the number of lines of code and loops. How can I achieve this? fill() { this.rolesPermiAdd = ...

Sending variable boolean values to a VueJS component

How can I assign dynamic properties to a VueJS Component using VuetifyJS? Below is an example of VuetifyJS code that constructs a select field element: <div id="app"> <v-app id="inspire" style="padding: 10px; "> ...

Use Javascript to display an image based on the date, otherwise hide the div

I'm looking to implement an image change on specific dates (not days of the week, but actual calendar dates like August 18th, August 25th, September 3rd, etc). Here's the div I'm working with: <div id="matchday"> <img id="home ...

Events in the backbone view fail to trigger after a re-render

For some reason, I am struggling to get mouse events to work on my backbone view after it is re-rendered. It seems like the only solution is to use a rather convoluted jQuery statement: $("a").die().unbind().live("mousedown",this.switchtabs); I initially ...

Adjusting the dimensions of the canvas leads to a loss of sharpness

When I click to change the size of the graph for a better view of my data in the PDF, the canvas element becomes blurry and fuzzy. Even though I am using $('canvas').css("width","811"); to resize the canvas, it still results in a blurry graph. I ...

Exploring the applications of the `this` keyword within a jQuery-based JavaScript object

Recently, there has been a challenge in creating a JavaScript object with the specific structure outlined below: function colorDiv(div){ this.div=div; this.div.bind("click",this.changeColor) this.changeColor(){ this.div.css(" ...

The functionality to scroll to the top of the page is not functioning properly in Next.js when navigating to a new page using the Link

While using Next.js, I encountered an issue where opening a new page would maintain the scroll position from the previous page. For instance, if I had scrolled to the bottom of a product listing page and clicked on a specific product, the product details p ...

How can I utilize a filter or pipe to populate product categories onto screens within Ionic 2?

I am considering creating an Ionic 2 app with 6 pages, but I'm unsure whether to utilize a Pipe or a Filter for the individual category pages and how to implement the necessary code. Each category page should be able to display products from the "app ...

Utilize $.get AJAX to extract data from a multidimensional JSON array

Struggling to make two functions work on my form that uses AJAX and jQuery to look up an array. One function is functional while the other seems to be causing confusion with over-analysis and extensive troubleshooting. Any insights into what may be missing ...

Having trouble with a JavaScript function as a novice coder

Hello, I'm still getting the hang of JavaScript - just a few days into learning it. I can't figure out why this function I'm calling isn't functioning as expected. Here's the content of my HTML page: <!doctype html> <htm ...

Ways to emphasize a particular <li> element?

Currently, I am delving into the world of React and facing a challenge. I have been trying to solve the issue below: When fetching some JSON data, it appears in this format: [ { "answerOptions": [ "Answer A", "Answer B", ...