└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # SoundCloud API with Angular 2 | 3 | Today we are going to build an app with AngularJS using the SoundCloud API. This app will allow us to search SoundClouds databases via username, and listen to the tracks that user has uploaded. An example of this app can be viewed [here](http://eanplatter.github.io/sounder) 4 | 5 | Try searching for: Yahtzel, or Carmadamusic. 6 | 7 | ## Step 1 - Set Up 8 | Let's get our basic Angular app set up. 9 | 10 | - Create an index.html file. 11 | - Set up the html file with its basic needs: 12 | - html tags 13 | - head tags 14 | - body tags 15 | - Create an app.js file 16 | - Create a mainController.js file 17 | - Create a soundService.js file 18 | - Link the files you just created at the bottom of the body of the html file with script tags 19 | - Create a styles.css file, and link it in the tags 20 | 21 | Next, we have some CDNs we'll need to add. Mainly Bootstrap and AngularJS and jQuery 22 | ``` html 23 | 24 | 25 | 26 | 27 | ``` 28 | - Link the bootstrap css file above our styles.css file in the tags 29 | - Link the angular, jQuery, and bootstrap js files at the tail end of the body tag. 30 | 31 | Our files should appear in index.html file in the following order: 32 | - HEAD 33 | - bootstrap.css 34 | - style.css 35 | - BODY 36 | - angular.min.js 37 | - jquery.min.js 38 | - bootstrap.min.js 39 | - app.js 40 | - mainController.js 41 | - soundService.js 42 | 43 | ## Step 2 - Initialize Angular 44 | 45 | - In app.js, create a new angular module called 'sounder' 46 | - Include the module in our index.html file by adding ng-app="sounder" to our `` tag. 47 | 48 | ### soundService.js 49 | - Set up the soundService, initializing the sounder module and building out the basic structure for the service 50 | - Inject the $http service into soundService 51 | 52 | ### mainController.js 53 | - Set up the mainController.js file with the basic structure for the controller 54 | - In our index.html's opening body tag, add the controller: `ng-controller="mainController"` 55 | - Inject our soundService into our mainController 56 | 57 | ## Step 3 - Our first endpoint 58 | 59 | We will be using the official SoundCloud api, which you can view at: https://developers.soundcloud.com or more specifically [here](https://developers.soundcloud.com/docs/api/reference). 60 | 61 | Whenever you make an app with SoundCloud, you need to register your app, and get an API key. Rather than having everyone go register we will use a key for the class. 62 | 63 | API key 64 | ``` 65 | bda4ada8694db06efcac9cf97b872b3e 66 | ``` 67 | 68 | *Note: using our api key (or any other kind of private stuff) in our front end code is a bad habit. Typically, sensitive information like this is kept in a file that our web server will access. A file that is not committed to github to ensure privacy. Someone could easily find our API key and use it in their own app. In future projects we will discuss some ways to better secure our apps. It'll work fine for our small project, but you would never want to share API keys publicly.* 69 | 70 | - Our endpoint is going to get all of the tracks a user has uploaded. 71 | - Write a getUser function in our soundService.js file that is attached to our service using the 'this' keyword 72 | - `this.getUser = function() {}` 73 | - getUser should expect a "username" parameter 74 | - Use angular's $http service to get data for the getUser function 75 | - GET `'http://api.soundcloud.com/users/' + username + '/tracks.json?client_id=bda4ada8694db06efcac9cf97b872b3e'` 76 | - This url will be our main point of contact between the SoundCloud API and our app 77 | 78 | The url we used above has an interesting anatomy: 79 | - Main URL: http://api.soundcloud.com/ 80 | - Where we want to go: users/' + username + '/tracks.json 81 | - API Key: ?client_id=bda4ada8694db06efcac9cf97b872b3e 82 | 83 | This tells SoundCloud that we want to hit their users by the username of the variable username and download all of their tracks in JSON format. The API Key tells SoundCloud who we are. 84 | 85 | ## Step 4 - Our controller (part 1) 86 | 87 | - Create a "getUser" function on our controller's scope object 88 | - Within `$scope.getUser` call `soundService.getUser` function in order to get the data from the service. Remember, the soundService.getUser needs to have a username passed into it. Pass a test value, like 'Yahtzel' (a SoundCloud user): 89 | 90 | `soundService.getUser('Yahtzel')` 91 | 92 | - Remember that $http returns a promise, so use `.then` on soundService.getUser and console.log(data.data) within that function 93 | - Invoke $scope.getUser function at the bottom of the controller 94 | 95 | Try out your app so far. You can run your app by using http-server (which should already be installed) from the root of the application folder. Once the server is running, check out localhost:8080 (or whatever port your http-server is running on). 96 | 97 | Open the console, you should see some data from Yahtzel. Obviously we don't always want to get data from the same username (Yahtzel), so in our $scope.getUser function, let's change 'Yahtzel' to $scope.searchText. 98 | 99 | ## Step 5 - Our view (part 1) 100 | 101 | - In our index.html page let's create a form with an input field that has an ng-model of 'searchText' 102 | - Add a button in the form that calls `getUser()` on ng-click 103 | - Take out the automatic call to `getUser` from the controller. 104 | 105 | Now angular will see the input text, apply that text to $scope.searchText and pass it through to the function via our button's ng-click. Click the button, and we end up console.logging the data for the person we searched. 106 | 107 | Search some cool usernames! 'yahtzel', 'carmadamusic', 'flightfacilities' 'the-gtw'. 108 | 109 | ## Step 6 - Our controller (part 2) 110 | 111 | - Inside our $scope.getUser function we are console.logging our data. Let's apply it to our $scope object so that we can render it in our view. 112 | - Do this in place of the console.log: `$scope.userData = data.data` 113 | 114 | - Now in our view, we can ng-repeat through the data 115 | 116 | `ng-repeat="song in userData"` 117 | 118 | Here's an example of how we can markup the data using Bootstrap: 119 | 120 | ``` html 121 |
122 |
123 |
124 | 125 | 126 |
127 |
128 |
129 | ``` 130 | 131 | This will give us the album art of each song. Notice that we put an ng-click on each img that will allow us to call `play`. Now let's actually play the song. 132 | 133 | We need to access the SoundCloud JavaScript SDK. SDK stands for Software Development Kit. It's essentially a fancy API made for JavaScript specifically. We won't spend too much time talking about how the SoundCloud SDK works. We just need it to play our tunes! 134 | 135 | ## Step 7 - SoundCloud SDK 136 | We are going to use the SoundCloud SDK to inject some HTML into our app which will play the song we selected. 137 | 138 | - Inject the SoundCloud SDK into our app, like so: 139 | ```html 140 | 141 | ``` 142 | 143 | - In our controller, let's create a $scope.play function that takes in a parameter called track_url 144 | - The following bit of code is going to do all of magic for us. Put it in the $scope.play function: 145 | 146 | ``` javascript 147 | SC.oEmbed(track_url, { auto_play: true }, function(oEmbed) { 148 | $scope.$apply($scope.player_html = $sce.trustAsHtml(oEmbed.html)); 149 | }); 150 | ``` 151 | $sce is an angular tool being used to escape certain characters. We need to inject it in our controller in order for us to be able to use the `trustAsHtml` method as shown above. 152 | 153 | This code is essentially calling SoundCloud's function oEmbed, and then in the callback is doing some angular magic so as to sanitize the code and pass it into our DOM. oEmbed comes with a lot of data, this bit of code strips out the HTML for our use. 154 | 155 | - Next, in our view we want to render the code. AngularJS has a very useful directive called ng-bind-html. If we try to say 156 | 157 | ```$scope.player_html = '
Crazy SoundCloud player code!
'``` 158 | 159 | and then attempt to render it in the DOM, the user will end up seeing something like this in the browser: 160 | 161 | ![bad image](https://s3.amazonaws.com/f.cl.ly/items/0J2e45002w242k3v2m34/Screen%20Shot%202015-02-24%20at%205.13.29%20PM.png) 162 | 163 | Instead, we want our browser to actually render it like it would any other html. ng-bind-html does that for us. All we need to do is tell it what to render. Let's add a div to index.html and use ng-bind-html to point it to our player_html scope var. 164 | 165 | ng-bind-html="player_html" 166 | 167 | Once we are rendering the player HTML, we should now get to play any song we've clicked on! 168 | 169 | ## Step 8 (Black Diamond): Build a user view 170 | 171 | Use ng-route to divide your app into two routes, `/#/tracks` and `/#/users/:userId`. Create views and controllers for each. 172 | 173 | In the tracks view, modify the markup so that the track's username is listed. When that username is clicked, take the user to `/#/users/:userId`, substituting userId with the userId found for that SoundCloud user. 174 | 175 | In your controller that handles users, inject a service that uses the [users.json endpoint](https://developers.soundcloud.com/docs/api/reference#users) to list the SoundCloud information for that user. 176 | 177 | 178 | 179 | ## Copyright 180 | 181 | © DevMountain LLC, 2016. Unauthorized use and/or duplication of this material without express and written permission from DevMountain, LLC is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given to DevMountain with appropriate and specific direction to the original content. 182 | --------------------------------------------------------------------------------