javascript - ng-if indexOf med JSON-arrays


Jeg har en JSON-output af items - For at vise et enkelt element bruger jeg ng-repeat="item in items". Og jeg kan få adgang til det aktuelt loggede brugerobjekt med user

Hver vare kan tilhøre flere brugeres ønskelister. Hvis en bruger tilføjer en vare til sin ønskeliste, gemmes user_id inden i item.wishlists.

JSON-outputtet af et enkelt item ser forenklet nogenlunde sådan ud:

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

når jeg gør user.id får jeg ID'et på den aktuelt indloggede bruger.

Nu vil jeg bruge ng-if inden for ng-repeat="item in items" for at tjekke, om current_user allerede har tilføjet denne vare til sin ønskeliste, og derefter vise denne bruger en "fjern fra ønskeliste"-knap i stedet for "tilføj til ønskeliste".

Min ikke-fungerende tilgang er:

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

Kan jeg bruge indexOf sådan her? Eller hvad ville være den korrekte AngularJS-måde at tjekke, om user.id er inden for item.wishlists user_id's?

Opdatering:

Vis: (ctrl.hasWished ændrer ikonet fra 'favorit', hvis sandt, til 'favorit_border', hvis falsk)

<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');
    }
  }

Når jeg klikker på knappen, hvis den før var falsk, sender den PUT-forespørgslen, og jeg får også ToastService-beskeden "added..", hvis jeg klikker igen, sender den DELETE-forespørgslen og ToastService-beskeden "removed..". Men ikonet ændrer sig ikke fra "favorite" til "favorite_border". Når jeg genindlæser siden, vises de rigtige ikoner.

Jeg har også denne fejlmeddelelse i konsollen:

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)

og når man klikker, også denne fejl:

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)

Svar #1

Filter skal fungere:

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

Svar #2

du kan ikke bruge indexOf-funktionen til denne opgave. i stedet anbefaler jeg, at du opretter en funktion på omfanget inden for controlleren, som tjekker, om ønskelisten indeholder brugeren på den måde -

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

på udsigten -

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

funktionen isUserOnWishlist vil iterere over hver bruger på ønskelisten og returnere sandt kun hvis den finder mindst en ønskeliste, som opfylder dette - wishlist.user_id === user.id. du kunne have brugt indexOf-funktionen, hvis ønskelisten var en liste af int'ere i stedet for en liste af objekter.

Jeg anbefaler, at du tjekker MDN-dokumentationen for JS-array-funktioner, du kan finde der forklaring om alle de seje array-funktioner, der følger med JS.

https://developer.mozilla.org/da/docs/Web/JavaScript/Reference/Global_Objects/Array

held og lykke.