最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ng-if indexOf with JSON Arrays - Stack Overflow

programmeradmin9浏览0评论

I have a JSON Output of items - To display a single item i use ng-repeat="item in items". And I can access the currently logged in user object with user

Each item can belong to multiple wishlists of users. If a user adds an item to his wishlist the user_id gets saved within item.wishlists

The JSON Output of a single item looks simplified 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 current logged in user.

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

My not working approach is:

<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>

Can I use indexOf like this? Or what would be the correct angularJS way to check if user.id is within item.wishlists user_id's?

Update:

View: (ctrl.hasWished changes the icon from 'favorite' if true to '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 the button if its false before, it sends the PUT request, and I also get the ToastService message "added..", if I click again it sends the DELETE request and the ToastService message "removed..". But the Icon doesn't change from "favorite" to "favorite_border". When I reload the page the right Icons are displayed.

I also have this error message within the console:

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

and when clicking also this error:

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

I have a JSON Output of items - To display a single item i use ng-repeat="item in items". And I can access the currently logged in user object with user

Each item can belong to multiple wishlists of users. If a user adds an item to his wishlist the user_id gets saved within item.wishlists

The JSON Output of a single item looks simplified 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 current logged in user.

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

My not working approach is:

<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>

Can I use indexOf like this? Or what would be the correct angularJS way to check if user.id is within item.wishlists user_id's?

Update:

View: (ctrl.hasWished changes the icon from 'favorite' if true to '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 the button if its false before, it sends the PUT request, and I also get the ToastService message "added..", if I click again it sends the DELETE request and the ToastService message "removed..". But the Icon doesn't change from "favorite" to "favorite_border". When I reload the page the right Icons are displayed.

I also have this error message within the console:

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

and when clicking also this error:

TypeError: v2.hasWished is not a function
    at fn (eval at <anonymous> (http://ruby-on-rails-140223.nitrousapp.:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:13323:15), <anonymous>:4:318)
    at Object.expressionInputWatch [as get] (http://ruby-on-rails-140223.nitrousapp.:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:14303:31)
    at Scope.$digest (http://ruby-on-rails-140223.nitrousapp.:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:15819:40)
    at Scope.$apply (http://ruby-on-rails-140223.nitrousapp.:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:16098:24)
    at HTMLButtonElement.<anonymous> (http://ruby-on-rails-140223.nitrousapp.:3000/assets/angular-touch/angular-touch-b4d02ed602708a1c93b51087222e0363.js?body=1:478:13)
    at HTMLButtonElement.eventHandler (http://ruby-on-rails-140223.nitrousapp.:3000/assets/angular/angular-81b9b668c3f93c8ccb76b27ad984d9b6.js?body=1:3299:21)
Share Improve this question edited Nov 17, 2015 at 13:02 Alessandro Santamaria asked Nov 16, 2015 at 20:54 Alessandro SantamariaAlessandro Santamaria 9672 gold badges12 silver badges25 bronze badges 1
  • try to use (item.wishlists|filter:{user_id:user.id}).length==0 – vp_arth Commented Nov 16, 2015 at 21:17
Add a ment  | 

3 Answers 3

Reset to default 4

Filter should works:

<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>

you cannot use indexOf function for this task. instead i remand you to create a function on the scope within the controller which checks if the wishlist contains the user in that manner -

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

on the view -

<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 on each user on the wishlist and return true only if it will find atleast one wishlist which passes this - wishlist.user_id === user.id. you could have used the indexOf function if the wishlist was a list of int's instead list of objects.

i remend you check out the MDN js array functions documentation, you can find there explanation about all the cool array functions thats es out of the box with js.

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

good luck.

Don't use indexOf, check this post: "There is one final aspect to consider: equality. The indexOf method uses strict equality (===) to determine if an element matches your search. This works great for primitives like strings and numbers. But you may have difficulty using indexOf to search for a given object or array" finding-array-elements-with-array-indexof

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

Regards

发布评论

评论列表(0)

  1. 暂无评论