Ng-if indexOf with JSON arrays

I have the output of JSON items - to display a single item, I use ng-repeat="item in items" . And I can access the currently registered user object using user

Each item can belong to several user wish lists. If the user adds an item to his wishlist, user_id stored in item.wishlists

The JSON output of one item looks something like this:

 {"id":1,"title":"This is a tile","wishlists":[{"user_id":2},{"user_id":3}]} 

when I do user.id , I get the ID of the currently logged in user.

Now I want to use ng-if in ng-repeat="item in items" to check if current_user has added this item to my wish list, and then to display this user the "remove from wish list" button instead of "add to wish list ",.

My non-working approach:

 <div ng-repeat="item in items"> <h3>{{item.title}}</h3> <a href="" ng-click="addToWishlist(item)" ng-if="item.wishlists.indexOf(user.id) == -1">Wish</a> <a href="" ng-click="removeFromWishlist(item)" ng-if="item.wishlists.indexOf(user.id) > -1">Undo-Wish</a> </div> 

Is it possible to use indexOf like this? Or what would be the correct way for angularJS to check if user.id is in item.wishlists user_id?

Update:

View: (ctrl.hasWired changes the icon from the "favorite" if true for "favorite_border", if false)

 <div ng-repeat="item in items"> <md-button class="md-icon-button feed-wish md-warn" aria-label="Wish" ng-click="ctrl.toggleWish(item)"> <i class="material-icons">favorite{{ctrl.hasWished(item) ? '' : '_border' }}</i> </md-button> </div> 

Controller:

  // Check if User has wished this item already: Should return true or false this.hasWished = function(item) { return item.wishlists.some(function(wishlist) { return wishlist.user_id === Auth._currentUser.id; // returns true if currently logged in user id is on wishlist }); }; this.toggleWish = function(item) { if (!this.hasWished) { this.hasWished = true; items.wish(item); // sends PUT request ToastService.show(item.product + ' added to Wish List'); } else { this.hasWished = false; items.unWish(item); // sends DELETE request ToastService.show(item.product + ' removed from Wish List'); } } 

When I click on a button, if its false before, it sends a PUT request, and I also get a ToastService message "added ..", if I click it again, it sends a DELETE request, and the ToastService message is "deleted ..". But the icon does not change from "favorite" to "favorite_border". When I reload the page, the corresponding icons are displayed.

I also have this error message in the console:

 TypeError: Cannot read property 'id' of null at http://ruby-on-rails-140223.nitrousapp.com:3000/assets/auctions/auctionCtrl-f2cb59b8ad51e03a2264ef2c6e759a54.js?body=1:33:52 at Array.some (native) at hasWished (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/auctions/auctionCtrl-f2cb59b8ad51e03a2264ef2c6e759a54.js?body=1:32:30) at fn (eval at <anonymous> (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:13323:15), <anonymous>:4:318) at Object.expressionInputWatch [as get] (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:14303:31) at Scope.$digest (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:15819:40) at Scope.$apply (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:16098:24) at done (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:10547:47) at completeRequest (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:10745:7) at XMLHttpRequest.requestLoaded (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:10686:9) 

and when clicking this error:

 TypeError: v2.hasWished is not a function at fn (eval at <anonymous> (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:13323:15), <anonymous>:4:318) at Object.expressionInputWatch [as get] (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:14303:31) at Scope.$digest (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:15819:40) at Scope.$apply (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:16098:24) at HTMLButtonElement.<anonymous> (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular-touch/angular-touch-b4d02ed602708a1c93b51087222e0363.js?body=1:478:13) at HTMLButtonElement.eventHandler (http://ruby-on-rails-140223.nitrousapp.com:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:3299:21) 
+5
source share
3 answers

The filter should work:

 <div ng-repeat="item in items"> <h3>{{item.title}}</h3> <a href="" ng-click="addToWishlist(item)" ng-if="!(item.wishlists|filter:{user_id:user.id}).length">Wish</a> <a href="" ng-click="removeFromWishlist(item)" ng-if="(item.wishlists|filter:{user_id:user.id}).length">Undo-Wish</a> </div> 
+2
source

you cannot use the indexOf function for this task. instead, I recommend that you create a function in the area inside the controller that checks if the user list contains the wish list in this way

 function isUserOnWishlist(item) { return item.wishlists.some(function(wishlist) { return wishlist.user_id === user.id; // ( on $scope ? ) }); } 

by the look -

 <a href="" ng-click="addToWishlist(item)" ng-if="!isUserOnWishlist(item.wishlists)">Wish</a> <a href="" ng-click="addToWishlist(item)" ng-if="isUserOnWishlist(item.wishlists)">Undo-Wish</a> 

the isUserOnWishlist function will iterate over each user in the wish list and return true only if he finds at least one wish list that passes this - wishlist.user_id === user.id you could use the indexOf function if the wish list was an int list instead of a list of objects.

I recommend that you check the documentation on the functions of the MDN js array, you can find there an explanation of all the interesting array functions that go out of the box with js.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

good luck.

+2
source

Do not use indexOf, check this message: "There is one last aspect to consider the following issues: Equality The IndexOf method uses strict equality (===) to determine whether your search item is matched. This works great for primitives such as strings. and number But it may be difficult to use IndexOf to search .. for a given object or array " finding-array-elements-with-array-indexof

You can use the $ filter API / ng / filter components reference in ng / filter , or maybe you should create a function in the controller by passing the current element and user.id as paremeters to do this or create a custom directive. Check this out if you need an idea for your custom function: how-to-find-index-of-an-item-in-javascript-object-array /

Hello

+1
source

Source: https://habr.com/ru/post/1236081/


All Articles