user3788671
user3788671

Reputation: 2047

Using Angular and Youtube API to display playlists and video details

I am new to Angular but I thought I would get my feet wet with it by using the Youtube API v3. I am struggling getting the playlists from a channel to display in a dropdown on the html page. Also, when a playlist is selected from the dropdown I want to display the title and thumbnail of every video in the selected playlist. I am new to this so I would really appreciate some help.

Here is what I have:

<html lang="en">
<head>
    <title>Angular Example</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <script src="js/jquery-1.11.3.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <script src="js/angular.min.js"></script>

    <script>

        var app = angular.module('ph', []);
        var key = '';

        app.factory('youtubeService', ['$http', function ($http) {

            function getPlaylists(channelId) {
                return $.get("https://www.googleapis.com/youtube/v3/channels", { params: {part: 'snippet', channelId: channelId, key: key} });
            }

            function getPlaylistVideos(id) {
                return $http.get('https://www.googleapis.com/youtube/v3/videos', { params: { part: 'snippet', id: id, key: key } });
            }

            return { getPlaylists: getPlaylists, getPlaylistVideos: getPlaylistVideos }

        }]);


        app.controller('ctrl', ['$http', '$scope', 'youtubeService', function ($http, $scope, youtubeService) {

            youtubeService.getPlaylists('UC1P0NQW6aixa5SUTbPF5CjQ').then(function (response) {
                $scope.playlists = response.data.items;
            });

            $scope.getPlaylistVideos = function (selection) {
                youtubeService.getPlaylistVideos(selection.snippets.id).then(function (response) {
                    $scope.playlistvideos = response.data.items;
                });
            }
        }]);
    </script>
</head>

<body ng-app="ph">
<div class="row">
    <!-- BEGIN Playlist Section -->
    <section id="playlistsection">
        <div class="col-lg-12">
            <div class="col-lg-6">
                <table id="playlistvideostable" class="table table-responsive table-striped">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Thumbnail</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr ng-repeat="video in playlistvideos">
                            <td>
                                {{video.snippet.title}}
                            </td>
                            <!--<td>
                                <img src="{{video.snippet.thumbnails.default.url}}" alt="Video Image"/>
                            </td>-->
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class="col-lg-6">
                <h3>Available</h3>
                <hr>
                <select id="playlists"
                        ng-options="playlist.snippet.title for playlist in playlists track by playlist.snippet.id"
                        ng-model="data.selectedOption"
                        ng-change="getPlaylistVideos(data.selectedOption)"
                        class="form-control">
                </select>
            </div>
        </div>
    </section>
    <!-- END Playlist Section -->
</div>


</body>

</html>

Here is an example of what getPlaylists brings back in JSON:

{
 "kind": "youtube#channelListResponse",
 "etag": "\"0KG1mRN7bm3nResDPKHQZpg5-do/mtu1ek5RgV1XsIgIoPS7GNv8NkI\"",
 "pageInfo": {
  "totalResults": 1,
  "resultsPerPage": 1
 },
 "items": [
  {
   "kind": "youtube#channel",
   "etag": "\"0KG1mRN7bm3nResDPKHQZpg5-do/TEgtFpLB_KhJ-XEwy-yOJneYIYw\"",
   "id": "UC1P0NQW6aixa5SUTbPF5CjQ",
   "snippet": {
    "title": "Aaron Johnson",
    "description": "",
    "publishedAt": "2014-07-11T15:19:25.000Z",
    "thumbnails": {
     "default": {
      "url": "https://yt3.ggpht.com/-py7sd_PnqBI/AAAAAAAAAAI/AAAAAAAAAAA/Q6pYI0EC7No/s88-c-k-no/photo.jpg"
     },
     "medium": {
      "url": "https://yt3.ggpht.com/-py7sd_PnqBI/AAAAAAAAAAI/AAAAAAAAAAA/Q6pYI0EC7No/s240-c-k-no/photo.jpg"
     },
     "high": {
      "url": "https://yt3.ggpht.com/-py7sd_PnqBI/AAAAAAAAAAI/AAAAAAAAAAA/Q6pYI0EC7No/s240-c-k-no/photo.jpg"
     }
    },
    "localized": {
     "title": "Aaron Johnson",
     "description": ""
    }
   }
  }
 ]
}

Upvotes: 1

Views: 1717

Answers (1)

Shaun
Shaun

Reputation: 927

You have several issues with your code:

  1. You do not have a controller defined in your code, without it, your scope will not update.
  2. The API call is lacking a filter, such as categoryid.
  3. You are using $ to get the playlists, which is a Jquery request. Use $http
  4. Because of the above, you are coming outside of angular which then causes it to lose track of scope updates. Wrapping the assignment with $scope.$apply, will fix this. However, using $http will make this not necessary.

Please see below an updated version of your code which works. I have not continued on to the Video Playlist side of things, which you can do for practice.

<html lang="en">
<head>
  <title>Angular Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="css/bootstrap.min.css">
  <script src="js/jquery-1.11.3.js"></script>
  <script src="js/bootstrap.min.js"></script>
  <script src="js/angular.min.js"></script>

  <script>

        var app = angular.module('ph', []);
        var key = 'AIzaSyAYPrc9K2Fa2GopcBMuFNRxpAQrVJJvzC0';

        app.factory('youtubeService', ['$http', function ($http) {

            function getPlaylists(channelId) {
              return $.get("https://www.googleapis.com/youtube/v3/channels", { part: 'snippet', channelId: channelId, key: key, categoryId: "GCQmVzdCBvZiBZb3VUdWJl" });
            }

            function getPlaylistVideos(id) {
                return $http.get('https://www.googleapis.com/youtube/v3/videos', { params: { part: 'snippet', id: id, key: key } });
            }

            return { getPlaylists: getPlaylists, getPlaylistVideos: getPlaylistVideos }

        }]);


        app.controller('ctrl', ['$http', '$scope', 'youtubeService', function ($http, $scope, youtubeService) {

          youtubeService.getPlaylists('UC1P0NQW6aixa5SUTbPF5CjQ').then(function (response) {
              $scope.$apply(function () {
                $scope.playlists = response.items;
            })
            });

            $scope.getPlaylistVideos = function (selection) {
                youtubeService.getPlaylistVideos(selection.snippets.id).then(function (response) {
                    $scope.playlistvideos = response.data.items;
                });
            }
        }]);
  </script>
</head>

<body ng-app="ph">
  <div class="row">
    <!-- BEGIN Playlist Section -->
    <section id="playlistsection">
      <div class="col-lg-12" ng-controller="ctrl">
        <div class="col-lg-6">
          <table id="playlistvideostable" class="table table-responsive table-striped">
            <thead>
              <tr>
                <th>Name</th>
                <th>Thumbnail</th>
              </tr>
            </thead>
            <tbody>
              <tr ng-repeat="video in playlistvideos">
                <td>
                  {{video.snippet.title}}
                </td>
                <!--<td>
                    <img src="{{video.snippet.thumbnails.default.url}}" alt="Video Image"/>
                </td>-->
              </tr>
            </tbody>
          </table>
        </div>
        <div class="col-lg-6">
          <h3>Available</h3>
          <hr>
          <select id="playlists"
                  ng-options="playlist.snippet.title for playlist in playlists track by playlist.snippet.id"
                  ng-model="data.selectedOption"
                  ng-change="getPlaylistVideos(data.selectedOption)"
                  class="form-control"></select>
        </div>
      </div>
    </section>
    <!-- END Playlist Section -->
  </div>


</body>

</html>

The changes being: Add a ng-controller attribute

<div class="col-lg-12" ng-controller="ctrl">

Send in a filter. This should also use $http not $.get - Also note the removal of the params wrapper.

            function getPlaylists(channelId) {
              return $.get("https://www.googleapis.com/youtube/v3/channels", { part: 'snippet', channelId: channelId, key: key, categoryId: "GCQmVzdCBvZiBZb3VUdWJl" });
            }

Wrap apply because you step outside of angular

              $scope.$apply(function () {
                $scope.playlists = response.items;
            })

Upvotes: 1

Related Questions