AngularJS -在ng-repeat中向单个项附加HTML

AngularJS - Issue appending HTML to single item in ng-repeat

本文关键字:单个项 HTML ng-repeat AngularJS      更新时间:2023-09-26

情况:

我正在用它重新构建一个以前的项目来探索AngularJS。我使用的是angularjs-rails gem版本1.2.16。我有一个页面,我在其中进行API调用,返回音乐事件对象数组。控制器:

d2jiveControllers.controller('VenueResultsCtrl', ['$scope','$http','$routeParams',
  '$compile', '$sce', 'spotifyFactory', function($scope, $http, $routeParams, 
    $compile, $sce, spotifyFactory){
    "use strict";
    var venueId = $routeParams.venueId;
    var baseUrl = 'http://api.songkick.com/api/3.0/venues/';
    var apiKey = '/calendar.json?apikey=************';
    var url = baseUrl + venueId + apiKey  + '&jsoncallback=JSON_CALLBACK' ;
    var init = function(url){
      $http.jsonp(url)
        .success(function (data) {
          $scope.events = data.resultsPage.results.event;
          console.log(data);
        }).
        error(function(){
          console.log('failure');
        });
    };
    $scope.tracks = function(artistName){
      var artistTracks = spotifyFactory.getArtistTracks(artistName);
      var spotifyIframe = $('spotifyIframe');
      $scope.show_tracks = $sce.trustAsHtml("<iframe src='https://embed.spotify.com/?uri=spotify:trackset:Playlist:"+artistTracks.spotifyTracks + "'"+ 
        "&theme=white'width='300' height='300'frameborder='0' allowtransparency='true'></iframe>")
      console.log(artistTracks)
    };
    init(url);
}]);

我使用ng-repeat列出它们,并在每个清单上附加一个ng-click。HTML模板:

<div class="eventContainer row" ng-controller="VenueResultsCtrl">
  <div ng-repeat="event in events">
    <h4>
      {{event.displayName}} 
    </h4>
    <p>
      <a href="{{event.uri}}" target="_blank"> Buy Tickets</a>
    </p>
    <div ng-repeat="artist in event.performance">
      <button ng-click="tracks(artist.displayName)">Discover 
        {{artist.displayName}}<br> -- {{artist.billing}}</button><br><br>
      <div ng-bind-html="show_tracks"></div> 
    </div>
  </div>
</div>

点击后,我想让另一个API调用Spotify,以获得我然后放入iframe的轨道id。为了做到这一点,我尝试在指令和工厂中进行调用:

指令:

d2jive.directive('getSpotifyTracks', [function () { 
//      <div get-spotify-tracks="artist.displayName"></div>

  var spotifyUrl = "http://ws.spotify.com/search/1/track.json?callback=JSON_CALLBACK&q=";
  return {
    restrict: 'AEC',
    scope: {
      artistName: '='
    },
    templateUrl: 'assets/d2jive/templates/artistTracks.html',
    controller: ['$scope', '$http', function($scope, $http){
      $scope.getTracks = function(artistName){
        $http.jsonp(spotifyUrl + encodeURIComponent(artistName))
          .success(function (data) {
            var trackArray = [];
            var tracks = data.tracks.slice(0,9);
            for (var track in tracks){
              grabbedTrack = tracks[track].href.slice(
                14, tracks[track].href.length);
              trackArray.push(grabbedTrack);
            }
            $scope.artistTracks = trackArray;
            console.log(data);
          });
      };
    }],
    link: function(scope, element, attrs, ctrl){
      scope.$watch('artist.displayName', function(displayName){
        if (displayName){
          scope.getTracks(displayName);
        }
      })
    }
  }
}]);

工厂::

d2jive.factory('spotifyFactory', ['$http','$q', function($http, $q){
  var factory = {}
  factory.getArtistTracks = function(artistName){
    var tracks = {}
    var spotifyUrl = "http://ws.spotify.com/search/1/track.json?q=";
    var deferred = $q.defer();
    var getTracks = function(artistName){
      $http.get(spotifyUrl + encodeURIComponent(artistName))
        .success(function (data) {
          deferred.resolve(data);
        });
      return deferred.promise;
    };

    // tracks.spotifyTrakcs = getTracks(artistName);
    var spotifyTracks = getTracks(artistName);
    spotifyTracks.then(function(result){
        var trackArray = [];
        var tracks = result.tracks.slice(0,9);
        for (var track in tracks){
          grabbedTrack = tracks[track].href.slice(
            14, tracks[track].href.length);
          trackArray.push(grabbedTrack);
        }  
      tracks.spotifyTracks = trackArray;    
    });
    return tracks;
  }

return factory;

}]);

问题:

我找不到将iframe HTML附加到特定项目而不是列出的每个事件的方法。这个指令似乎没有起作用,因为它立即加载,使应用程序速度变慢了很多。这就是为什么我去了一个工厂,使API调用Spotify和附加iframe。

目标:

On ng-click使API调用Spotify,返回轨道ID,将它们插入iframe,然后将其插入点击项目的下方,而不是在所有项目的下方。

任何帮助将非常感激!谢谢。

在指令的link函数中的$watch中,在newVal和oldVal参数相等时提前返回:

link: function(scope, element, attrs, ctrl){
  scope.$watch('artist.displayName', function(displayName, oldVal){
    if (displayName === oldVal) { return }
    if (displayName){
      scope.getTracks(displayName);
    }
  })
}

这样可以防止getTracks()在指令链接时被调用。