<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Angular2 + Youtube Search</title>
    <link rel="stylesheet" href="styles.css">
    <!-- ES6-related imports -->
<script src="http://cdn.rawgit.com/google/traceur-compiler/90da568c7aa8e53ea362db1fc211fbb4f65b5e94/bin/traceur-runtime.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/systemjs/0.18.4/system.js"></script>
<script src="config.js"></script>
<!-- Angular2 import -->
<script src="http://code.angularjs.org/2.0.0-alpha.35/angular2.dev.js"></script>
<script src="http://code.angularjs.org/2.0.0-alpha.35/http.dev.js"></script>

<script>
    //bootstrap the Angular2 application
    System.import('app').catch(console.log.bind(console));
</script>
</head>

<body>
    <youtube-app>Loading...</youtube-app> 
</body> 



</html>
import {
  bind,
  bootstrap,
  Component,
  View,
  Injectable,
  CORE_DIRECTIVES,
  ON_PUSH
} from 'angular2/angular2';

import {
  Http, HTTP_BINDINGS
} from 'http/http'
import {
  FormBuilder, 
  Validators,
  FORM_BINDINGS,
  FORM_DIRECTIVES
} from 'angular2/forms';

import {RxPipe} from './rxPipe';
import {YouTubeAPI} from './YouTube'


@Component({
  selector: 'search-result',
  properties: ['video'],
  changeDetection: ON_PUSH
})
@View({
  template: `
    <div style="border: 1px solid black">
      <h3>{{video.snippet.title}}</h3>
      <h4>{{video.snippet.channelTitle}}</h4>
      <div>
        <img [src]="video.snippet.thumbnails.default.url"></img>
      </div>
    </div>
  `
})
class SearchResult {}

@Component({
    selector: 'youtube-app',
    changeDetection: ON_PUSH
})
@View({
  template: `
   <div>
     <h3>angular2 + youtube search</h3>
     <form  [ng-form-model]="youtubeQuery">
      <input type="text" ng-control="title">
     </form>
   
     <div *ng-for="#video of videos | rx">
      <search-result [video]="video"></search-result>
     </div>
     
   </div>
  `,
  directives: [CORE_DIRECTIVES, FORM_DIRECTIVES, SearchResult],
  pipes: [RxPipe]
})
export class YouTubeApp {
  constructor(youtube: YouTubeAPI,formBuilder:FormBuilder){
    this.youtubeQuery = formBuilder.group({
      title: ["", Validators.required]
    });
    
    let queries = this.youtubeQuery.valueChanges.toRx();

    this.videos = queries.flatMapLatest(query => youtube.search(query.title));
  }
}

bootstrap(YouTubeApp,[FORM_BINDINGS, HTTP_BINDINGS, YouTubeAPI])
  .catch(err => console.log(err));
/// https://gist.github.com/jashmenn/d8f5cbf5fc20640bac30

/// <reference path="../../typings/app.d.ts" />
//
//  Creates a pipe suitable for a RxJS observable:
//
//        @View({
//          template: '{{ someObservable | rx}}'
//          pipes: [RxPipe]
//        })
// 
// Originally written by @gdi2290 but updated for 2.0.0.alpha-35 and use AsyncPipe
// (Soon the Angular team will be using RxJS natively and this pipe will be
// unnecessary because we'll be able to use the `async` pipe.)
// 
// References:
// * rxPipeRegistry.ts https://gist.github.com/gdi2290/e9b2880a1d13057197d7 by @gdi2290
// * AsyncPipe https://github.com/angular/angular/blob/master/modules/angular2/src/pipes/async_pipe.ts

import {PipeFactory, Pipe, Injectable, bind, ChangeDetectorRef} from "angular2/angular2";
import {AsyncPipe} from "angular2/pipes";
import * as Rx from 'rx';
import {Observable} from 'rx';

function isObservable(obs) {
  console.log(obs)
  return obs && typeof obs.subscribe === 'function';
}

class RxStrategy {
  createSubscription(async: any, updateLatestValue: any): any {
    return async.subscribe((values) => {
      updateLatestValue(values);
    }, e => { throw e; });
  }
  dispose(subscription: any): void { subscription.dispose(); }
  onDestroy(subscription: any): void { subscription.dispose(); }
}

var _rxStrategy = new RxStrategy();
 
@Pipe({name: 'rx'})
export class RxPipe extends AsyncPipe {
  constructor(public _ref: ChangeDetectorRef) { super(_ref); }

  supports(obs) { return isObservable(obs); }

  _selectStrategy(obj: Observable<any>): any {
    return _rxStrategy;
  }
}
 
export var rxPipeInjectables: Array<any> = [
  bind(RxPipe).toValue(RxPipe)
];
System.config({
        defaultJSExtensions: true,
        transpiler: 'typescript',
        typescriptOptions: {
          emitDecoratorMetadata: true
        },
        map: {
          typescript: 'https://cdn.rawgit.com/robwormald/9883afae87bffa2f4e00/raw/8bca570a696c47a4f8dd03a52c98734676e94cea/typescript.js',
          'rx.all': 'https://cdnjs.cloudflare.com/ajax/libs/rxjs/3.1.1/rx.all.js',
          'redux': 'https://cdn.rawgit.com/rackt/redux/master/src/index.js'
        },
        paths: {
          app: 'src'
        },
        packages: {
          app: {
            main: 'app.ts',
            defaultExtension: 'ts',
          }
        }
    });
.completed {
  color:red;
  text-decoration:line-through;
}
### angular2 + http

searchin' youtube with ng2http and pipes
import {Http, HttpConfig} from 'http/http';
import {Injectable} from 'angular2/angular2';
import {Observable} from 'rx'

const BASE_URL = 'https://www.googleapis.com/youtube/v3/search';
const API_TOKEN = 'AIzaSyAJk1xUI72YYfBMgEc84gjHUX-k2AN6-B0';

@Injectable()
export class YouTubeAPI {
  constructor(http:Http){
    this.http = http;
  }
  
  search(query){
    //wouldnt need this if .partition was in angular2's rx :(
    if(!query.length){
      return Observable.just([])
    }
    return this.http.get(`${BASE_URL}?q=${query}&part=snippet&key=${API_TOKEN}`)
     .toRx()
     .map(res => res.json())
     .map(json => json.items);
  }
}