├── .gitignore ├── README.md ├── bower.json ├── gulpfile.config.js ├── gulpfile.js ├── package.json ├── src ├── server │ ├── mock │ │ └── api │ │ │ └── books.js │ └── server.js └── webapp │ ├── app │ ├── bootstrap.ts │ ├── common │ │ └── formInjectables.ts │ ├── models │ │ └── book.ts │ ├── pages │ │ ├── create │ │ │ ├── create-book.html │ │ │ └── create-book.ts │ │ ├── edit │ │ │ ├── edit-book.html │ │ │ └── edit-book.ts │ │ ├── list │ │ │ ├── list-books.html │ │ │ └── list-books.ts │ │ ├── pages.ts │ │ └── view │ │ │ ├── view-book.html │ │ │ └── view-book.ts │ └── services │ │ ├── BookService.ts │ │ └── services.ts │ ├── assets │ └── styles │ │ ├── base.less │ │ └── main.less │ └── index.html ├── tsd.json └── typings ├── _custom ├── browser.d.ts ├── custom.d.ts ├── ng2.d.ts └── webpack.d.ts ├── angular2 └── angular2.d.ts ├── es6-promise └── es6-promise.d.ts ├── rx ├── rx-lite.d.ts └── rx.d.ts ├── tsd.d.ts └── whatwg-fetch └── whatwg-fetch.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE files # 2 | .idea 3 | *.iml 4 | 5 | # OS generated files # 6 | .DS_Store 7 | Thumbs.db 8 | 9 | # Node Files # 10 | node_modules 11 | bower_components 12 | 13 | # Dist # 14 | public 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # README # 2 | 3 | Simple book store application with CRUD operations using Angular 2 (2.0.0-alpha.27) 4 | 5 | ExpressJS serves as the backend with mocked data & services 6 | 7 | Supported browsers: Chrome 8 | 9 | ### Project Setup ### 10 | 11 | * bower install && npm install 12 | * gulp 13 | * Open browser @ http://localhost:7777/ -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-boilerplate", 3 | "version": "1.0.0", 4 | "description": "Simple CRUD application with Angular 2", 5 | "main": "dist/angular2-boilerplate.js", 6 | "moduleType": [ 7 | "es6", 8 | "node" 9 | ], 10 | "keywords": [ 11 | "angular2", 12 | "node", 13 | "express", 14 | "bootstrap", 15 | "postgresql" 16 | ], 17 | "authors": [ 18 | { 19 | "name": "Norbert Annus", 20 | "email": "norbert.annus@opencredo.com" 21 | } 22 | ], 23 | "license": "MIT", 24 | "ignore": [ 25 | "**/.*", 26 | "node_modules", 27 | "bower_components", 28 | "test", 29 | "typings" 30 | ], 31 | "devDependencies": { 32 | "bootstrap": "~3.3.5", 33 | "traceur-runtime": "~0.0.90" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /gulpfile.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var GulpConfig = (function () { 4 | function GulpConfig() { 5 | this.src = './src'; 6 | this.webappSrc = this.src + '/webapp'; 7 | this.dest = './public'; 8 | this.typingsDir = './typings'; 9 | 10 | this.outputFile = 'angular2-boilerplate'; 11 | this.outputCSSDir = '/css'; 12 | this.outputLibDir = '/lib'; 13 | 14 | this.mainLessFile = this.webappSrc + '/assets/styles/main.less'; 15 | this.allHTML = [ 16 | this.webappSrc + '/*.html', 17 | this.webappSrc + '/**/*.html' 18 | ]; 19 | this.allLess = this.webappSrc + '/assets/styles/**/*.less'; 20 | this.allTypeScript = this.webappSrc + '/**/*.ts'; 21 | this.allJavaScript = '/**/*.js'; 22 | this.allJavaScriptSourceMap = '/**/*.js.map'; 23 | this.allLib = [ 24 | 'bower_components/traceur-runtime/traceur-runtime.js' 25 | ]; 26 | 27 | this.serverPath = this.src + '/server/server.js'; 28 | 29 | this.libraryTypeScriptDefinitions = this.typingsDir + '/**/*.ts'; 30 | this.appTypeScriptReferences = this.typingsDir + '/tsd.d.ts'; 31 | } 32 | 33 | return GulpConfig; 34 | })(); 35 | 36 | module.exports = GulpConfig; 37 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | tsc = require('gulp-typescript'), 3 | tslint = require('gulp-tslint'), 4 | sourcemaps = require('gulp-sourcemaps'), 5 | del = require('del'), 6 | rename = require('gulp-rename'), 7 | typescript = require('typescript'), 8 | plumber = require('gulp-plumber'), 9 | less = require('gulp-less'), 10 | runSequence = require('run-sequence'), 11 | gls = require('gulp-live-server'), 12 | Config = require('./gulpfile.config'), 13 | 14 | config = new Config(), 15 | server; 16 | 17 | gulp.task('ts-lint', function () { 18 | return gulp.src(config.allTypeScript) 19 | .pipe(tslint()) 20 | .pipe(tslint.report('prose')); 21 | }); 22 | 23 | gulp.task('compile-ts', function () { 24 | var sourceTsFiles = [ 25 | config.allTypeScript, 26 | config.libraryTypeScriptDefinitions, 27 | config.appTypeScriptReferences 28 | ], 29 | tsResult = gulp.src(sourceTsFiles) 30 | .pipe(sourcemaps.init()) 31 | .pipe(tsc({ 32 | typescript: typescript, 33 | module: 'commonjs', 34 | target: 'ES5', 35 | emitDecoratorMetadata: true, 36 | declarationFiles: false, 37 | noExternalResolve: true 38 | })); 39 | 40 | tsResult.dts 41 | .pipe(gulp.dest(config.dest)); 42 | 43 | return tsResult.js.pipe(sourcemaps.write('.')) 44 | .pipe(gulp.dest(config.dest)); 45 | }); 46 | 47 | gulp.task('clean', function (done) { 48 | del([ 49 | config.dest + '/**' 50 | ], done); 51 | }); 52 | 53 | gulp.task('copy-html', function () { 54 | return gulp.src(config.allHTML) 55 | .pipe(gulp.dest(config.dest)); 56 | }); 57 | 58 | gulp.task('copy-lib', function () { 59 | return gulp.src(config.allLib) 60 | .pipe(gulp.dest(config.dest + config.outputLibDir)); 61 | }); 62 | 63 | gulp.task('styles', function () { 64 | return gulp.src(config.mainLessFile) 65 | .pipe(plumber()) 66 | .pipe(less()) 67 | .pipe(rename(config.outputFile + '.css')) 68 | .pipe(gulp.dest(config.dest + config.outputCSSDir)); 69 | }); 70 | 71 | gulp.task('watch', function() { 72 | gulp.watch([config.allTypeScript], ['ts-lint', 'compile-ts']); 73 | gulp.watch([config.allLess], ['styles']); 74 | gulp.watch([config.allHTML], ['copy-html']); 75 | }); 76 | 77 | gulp.task('local', function () { 78 | server = gls.new(config.serverPath); 79 | server.start(); 80 | }); 81 | 82 | gulp.task('default', function () { 83 | runSequence( 84 | 'clean', 85 | 'ts-lint', 86 | 'compile-ts', 87 | ['copy-html', 'copy-lib', 'styles'], 88 | 'watch', 89 | 'local' 90 | ) 91 | }); 92 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-boilerplate", 3 | "version": "1.0.0", 4 | "description": "Simple CRUD application with Angular 2", 5 | "main": "dist/angular2-boilerplate.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "angular2", 11 | "node", 12 | "express", 13 | "postgresql" 14 | ], 15 | "author": { 16 | "name": "Norbert Annus", 17 | "email": "norbert.annus@opencredo.com" 18 | }, 19 | "license": "MIT", 20 | "devDependencies": { 21 | "body-parser": "^1.13.1", 22 | "del": "^1.2.0", 23 | "express": "^4.13.0", 24 | "gulp": "^3.9.0", 25 | "gulp-less": "^3.0.3", 26 | "gulp-live-server": "0.0.20", 27 | "gulp-plumber": "^1.0.1", 28 | "gulp-rename": "^1.2.2", 29 | "gulp-sourcemaps": "^1.5.2", 30 | "gulp-tslint": "^3.0.2-beta", 31 | "gulp-typescript": "^2.7.7", 32 | "morgan": "^1.6.0", 33 | "run-sequence": "^1.1.1", 34 | "typescript": "1.5.0-beta" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/server/mock/api/books.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | isbn: '099134460X', 4 | title: 'ng-book - The Complete Book on AngularJS', 5 | author: 'Ari Lerner', 6 | publicationDate: '2013-12-29' 7 | }, 8 | { 9 | isbn: '1430264489', 10 | title: 'Pro AngularJS', 11 | author: 'Adam Freeman', 12 | publicationDate: '2014-03-26' 13 | }, 14 | { 15 | isbn: '0596517742', 16 | title: 'JavaScript : The Good Parts: The Good Parts', 17 | author: 'Douglas Crockford ', 18 | publicationDate: '2008-05-01' 19 | }, 20 | { 21 | isbn: '0596806752', 22 | title: 'JavaScript Patterns', 23 | author: 'Stoyan Stefanov', 24 | publicationDate: '2010-10-01' 25 | }, 26 | { 27 | isbn: '1449336361', 28 | title: 'JS.Next : ECMAScript 6', 29 | author: 'Aaron Frost', 30 | publicationDate: '2015-11-25' 31 | } 32 | ]; 33 | -------------------------------------------------------------------------------- /src/server/server.js: -------------------------------------------------------------------------------- 1 | // Ref: http://scotch.io/tutorials/javascript/build-a-restful-api-using-node-and-express-4 2 | var express = require('express'), 3 | path = require('path'), 4 | bodyParser = require('body-parser'), 5 | morgan = require('morgan'), 6 | books = require('./mock/api/books'), 7 | app = express(), 8 | port = 7777, 9 | router = express.Router(), 10 | webAppDir = createSystemFileName('../../public/'), 11 | apiRouterPrefix = '/api', 12 | 13 | ERROR_BOOK_ALREADY_EXISTS = { 14 | errorCode: 'BOOK_ALREADY_EXISTS', 15 | errorMessage: 'Book with isbn already exists' 16 | }; 17 | 18 | // given a file name path relative to this directory, create an absolute path 19 | function createSystemFileName(fileName) { 20 | return path.resolve(path.join(__dirname, fileName)); 21 | } 22 | 23 | function getBooks() { 24 | return books; 25 | } 26 | 27 | function getBookById(id) { 28 | return books.filter(function (book) { 29 | return book.isbn === id; 30 | })[0]; 31 | } 32 | 33 | function updateBook(id, book) { 34 | var _book = getBookById(id), 35 | key; 36 | 37 | for (key in _book) { 38 | if (_book.hasOwnProperty(key) && book.hasOwnProperty(key)) { 39 | _book[key] = book[key]; 40 | } 41 | } 42 | 43 | return _book; 44 | } 45 | 46 | function deleteBook(id) { 47 | var i; 48 | 49 | for (i = 0; i < books.length; i += 1) { 50 | if (books[i].isbn === id) { 51 | books.splice(i, 1); 52 | break; 53 | } 54 | } 55 | } 56 | 57 | function createBook(book) { 58 | var _book = getBookById(book.isbn); 59 | 60 | if (typeof _book === 'undefined') { 61 | books.push(book); 62 | } else { 63 | throw new Error('Book with this id already exists'); 64 | } 65 | } 66 | 67 | // only log requests to the API: 68 | router.use(morgan('dev')); 69 | 70 | router.get('/books', 71 | function (req, res) { 72 | res.status(200).json(getBooks()); 73 | } 74 | ).get('/books/:id', 75 | function (req, res) { 76 | var id = req.params.id; 77 | 78 | res.status(200).json(getBookById(id)); 79 | } 80 | ).put('/books/:id', 81 | function (req, res) { 82 | var id = req.params.id, 83 | book = req.body; 84 | 85 | res.status(200).json(updateBook(id, book)); 86 | } 87 | ).post('/books', 88 | function (req, res) { 89 | var book = req.body; 90 | 91 | try { 92 | createBook(book); 93 | res.status(201).json(); 94 | } catch (error) { 95 | res.status(409).json(ERROR_BOOK_ALREADY_EXISTS); 96 | } 97 | } 98 | ).delete('/books/:id', 99 | function (req, res) { 100 | var id = req.params.id; 101 | 102 | res.status(200).json(deleteBook(id)); 103 | } 104 | ); 105 | 106 | app.use(bodyParser.urlencoded({ extended: true })); 107 | app.use(bodyParser.json()); 108 | // currently, we are fixed to the dev distribution: 109 | app.use(express.static(webAppDir)); 110 | // configure router to handle specific prefix in the path 111 | app.use(apiRouterPrefix, router); 112 | app.listen(port); 113 | 114 | console.log('Web app dir:', webAppDir); 115 | console.log('Logging only service API calls'); 116 | console.log('Open browser at: http://127.0.0.1:' + port + '/'); 117 | -------------------------------------------------------------------------------- /src/webapp/app/bootstrap.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {bootstrap} from 'angular2/angular2'; 5 | 6 | // Angular's router injectables services/bindings 7 | import {routerInjectables} from 'angular2/router'; 8 | 9 | // Angular's form injectables services/bindings 10 | import {formInjectables} from './common/formInjectables'; 11 | 12 | import {appServicesInjectables} from './services/services'; 13 | 14 | import {App} from './pages/pages'; 15 | 16 | bootstrap( 17 | App, 18 | [ 19 | formInjectables, 20 | appServicesInjectables, 21 | routerInjectables 22 | ] 23 | ); 24 | 25 | -------------------------------------------------------------------------------- /src/webapp/app/common/formInjectables.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {FormBuilder} from 'angular2/forms'; 4 | 5 | export var formInjectables: Array = [ 6 | FormBuilder 7 | ]; 8 | -------------------------------------------------------------------------------- /src/webapp/app/models/book.ts: -------------------------------------------------------------------------------- 1 | export class Book { 2 | constructor( 3 | public isbn:string = null, 4 | public title:string = null, 5 | public author:string = null, 6 | public publicationDate:string = null) { 7 | } 8 | 9 | static fromJSON(json:any) { 10 | if (json) { 11 | var isbn:string = json.isbn || null; 12 | var title:string = json.title || null; 13 | var author:string = json.author || null; 14 | var publicationDate:string = json.publicationDate || null; 15 | return new Book(isbn, title, author, publicationDate); 16 | } else { 17 | return new Book(null, null, null, null); 18 | } 19 | } 20 | 21 | toJSON() { 22 | var json = { 23 | isbn: this.isbn, 24 | title: this.title, 25 | author: this.author, 26 | publicationDate: this.publicationDate 27 | }; 28 | 29 | return json; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/webapp/app/pages/create/create-book.html: -------------------------------------------------------------------------------- 1 | 3 | {{ createFailedMsg }} 4 | 5 | 6 | 10 | 11 | 13 | ISBN: 15 | 16 | 23 | 24 | 26 | This field is required. 27 | 28 | 29 | 30 | 32 | Title: 34 | 35 | 41 | 42 | 44 | This field is required. 45 | 46 | 47 | 48 | 49 | Author: 51 | 52 | 58 | 59 | 60 | 61 | 62 | Publication Date: 64 | 65 | 71 | 72 | 73 | 74 | 75 | Create 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/webapp/app/pages/create/create-book.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View, Directive, coreDirectives} from 'angular2/angular2'; 5 | import {formDirectives, FormBuilder, Control, ControlGroup, Validators} from 'angular2/forms'; 6 | import {Router} from 'angular2/router'; 7 | 8 | import {BookService} from '../../services/BookService'; 9 | import {Book} from '../../models/Book'; 10 | 11 | // Simple component 12 | @Component({ 13 | selector: 'create-book' 14 | }) 15 | 16 | @View({ 17 | templateUrl: './app/pages/create/create-book.html', 18 | directives: [coreDirectives, formDirectives] 19 | }) 20 | 21 | export class CreateBook { 22 | createBookForm: ControlGroup; 23 | isbnInput: Control; 24 | titleInput: Control; 25 | authorInput: Control; 26 | publicationDateInput: Control; 27 | 28 | book: Book; 29 | 30 | canShowCreateFailedMsg: boolean; 31 | createFailedMsg: string; 32 | 33 | constructor(public router:Router, public bookService:BookService, public formBuilder: FormBuilder) { 34 | this.book = new Book(); 35 | this.createFailedMsg = null; 36 | this.canShowCreateFailedMsg = false; 37 | 38 | this.createBookForm = formBuilder.group({ 39 | 'isbn': ['', Validators.required], 40 | 'title': ['', Validators.required], 41 | 'author': [''], 42 | 'publicationDate': [''] 43 | }); 44 | 45 | this.isbnInput = this.createBookForm.controls.isbn; 46 | this.titleInput = this.createBookForm.controls.title; 47 | this.authorInput = this.createBookForm.controls.author; 48 | this.publicationDateInput = this.createBookForm.controls.publicationDate; 49 | } 50 | 51 | createBook_successHandler(response) { 52 | if (response.status !== 201) { 53 | response.json().then(data => { 54 | this.canShowCreateFailedMsg = true; 55 | this.createFailedMsg = data.errorMessage || 'An error has occurred'; 56 | }); 57 | } else { 58 | this.listBooks(); 59 | } 60 | } 61 | 62 | createBook_errorHandler(error) { 63 | this.createFailedMsg = error; 64 | } 65 | 66 | createBook() { 67 | this.canShowCreateFailedMsg = false; 68 | 69 | this.bookService.createBook(this.book.toJSON()) 70 | .then(response => this.createBook_successHandler(response)) 71 | .catch(error => this.createBook_errorHandler(error)); 72 | } 73 | 74 | listBooks() { 75 | this.router.parent.navigate('/list'); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/webapp/app/pages/edit/edit-book.html: -------------------------------------------------------------------------------- 1 | 3 | Book has been successfully updated. 4 | 5 | 6 | 8 | {{ updateFailedMsg }} 9 | 10 | 11 | 14 | 15 | 16 | ISBN: 18 | 19 | {{ book.isbn }} 21 | 22 | 23 | 24 | 26 | Title: 28 | 29 | 36 | 37 | 39 | This field is required. 40 | 41 | 42 | 43 | 44 | Author: 46 | 47 | 53 | 54 | 55 | 56 | 57 | Publication Date: 59 | 60 | 66 | 67 | 68 | 69 | 70 | Save 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/webapp/app/pages/edit/edit-book.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View, Directive, coreDirectives} from 'angular2/angular2'; 5 | import {formDirectives, FormBuilder, Control, ControlGroup, Validators} from 'angular2/forms'; 6 | import {RouteParams} from 'angular2/router'; 7 | import {Inject} from 'angular2/di'; 8 | 9 | import {BookService} from '../../services/BookService'; 10 | import {Book} from '../../models/Book'; 11 | 12 | // Simple component 13 | @Component({ 14 | selector: 'edit-book' 15 | }) 16 | 17 | @View({ 18 | templateUrl: './app/pages/edit/edit-book.html', 19 | directives: [coreDirectives, formDirectives] 20 | }) 21 | 22 | export class EditBook { 23 | editBookForm: ControlGroup; 24 | titleInput: Control; 25 | authorInput: Control; 26 | publicationDateInput: Control; 27 | 28 | book: Book; 29 | 30 | canShowUpdateSuccessMsg: boolean; 31 | canShowUpdateFailedMsg: boolean; 32 | updateFailedMsg: string; 33 | 34 | constructor(@Inject(RouteParams) params, public bookService:BookService, public formBuilder: FormBuilder) { 35 | this.book = new Book(); 36 | this.canShowUpdateFailedMsg = false; 37 | this.canShowUpdateSuccessMsg = false; 38 | this.updateFailedMsg = null; 39 | 40 | this.getBook(params.get('id')); 41 | 42 | this.editBookForm = formBuilder.group({ 43 | 'title': ['', Validators.required], 44 | 'author': [''], 45 | 'publicationDate': [''] 46 | }); 47 | 48 | this.titleInput = this.editBookForm.controls.title; 49 | this.authorInput = this.editBookForm.controls.author; 50 | this.publicationDateInput = this.editBookForm.controls.publicationDate; 51 | } 52 | 53 | getBook(id:string) { 54 | this.bookService.getBook(id) 55 | .map(res => res.json()) 56 | .subscribe(res => this.book = Book.fromJSON(res)); 57 | } 58 | 59 | updateBook_successHandler(response) { 60 | if (response.status !== 200) { 61 | this.canShowUpdateFailedMsg = true; 62 | this.updateFailedMsg = 'Update has failed'; 63 | } 64 | 65 | response.json().then(data => { 66 | this.canShowUpdateSuccessMsg = true; 67 | this.book = Book.fromJSON(data); 68 | }); 69 | } 70 | 71 | updateBook_errorHandler(error) { 72 | this.updateFailedMsg = error; 73 | } 74 | 75 | updateBook() { 76 | this.canShowUpdateSuccessMsg = false; 77 | this.canShowUpdateFailedMsg = false; 78 | 79 | this.bookService.updateBook(this.book.isbn, this.book.toJSON()) 80 | .then(response => this.updateBook_successHandler(response)) 81 | .catch(error => this.updateBook_errorHandler(error)); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/webapp/app/pages/list/list-books.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ISBN 5 | Title 6 | Author 7 | Publication Date 8 | Action 9 | 10 | 11 | 12 | 13 | {{ book.isbn }} 14 | {{ book.title }} 15 | {{ book.author }} 16 | {{ book.publicationDate }} 17 | 18 | View 22 | Edit 26 | Delete 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/webapp/app/pages/list/list-books.ts: -------------------------------------------------------------------------------- 1 | 2 | /// 3 | 4 | // Angular 2 5 | import {Component, View, Directive, coreDirectives} from 'angular2/angular2'; 6 | import {Router} from 'angular2/router'; 7 | 8 | import {BookService} from '../../services/BookService'; 9 | 10 | @Component({ 11 | selector: 'list-books' 12 | }) 13 | 14 | @View({ 15 | directives: [coreDirectives], 16 | templateUrl: './app/pages/list/list-books.html' 17 | }) 18 | 19 | export class ListBooks { 20 | books: Array; 21 | 22 | constructor(public router:Router, public bookService:BookService) { 23 | this.getBooks(); 24 | } 25 | 26 | getBooks() { 27 | this.bookService.getBooks() 28 | .map(res => res.json()) 29 | .subscribe(res => this.books = res); 30 | } 31 | 32 | viewBook(book) { 33 | this.router.parent.navigate('/view/' + book.isbn); 34 | } 35 | 36 | editBook(book) { 37 | this.router.parent.navigate('/edit/' + book.isbn); 38 | } 39 | 40 | deleteBook(book) { 41 | this.bookService.deleteBook(book.isbn) 42 | .subscribe(res => this.getBooks()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/webapp/app/pages/pages.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View, coreDirectives} from 'angular2/angular2'; 5 | import {RouteConfig, RouterOutlet, RouterLink, Router} from 'angular2/router'; 6 | import {BrowserLocation} from 'angular2/src/router/browser_location'; 7 | 8 | import {CreateBook} from './create/create-book'; 9 | import {EditBook} from './edit/edit-book'; 10 | import {ListBooks} from './list/list-books'; 11 | import {ViewBook} from './view/view-book'; 12 | 13 | @Component({ 14 | selector: 'app', 15 | }) 16 | 17 | @View({ 18 | directives: [ RouterOutlet, RouterLink, coreDirectives ], 19 | template: ` 20 | 21 | 22 | 23 | {{ title }} 24 | 25 | 26 | 27 | 28 | List 29 | 30 | 31 | Create 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ` 42 | }) 43 | 44 | @RouteConfig([ 45 | { path: '/list', as: 'list', component: ListBooks }, 46 | { path: '/create', as: 'create', component: CreateBook }, 47 | { path: '/edit/:id', as: 'edit', component: EditBook }, 48 | { path: '/view/:id', as: 'view', component: ViewBook } 49 | ]) 50 | 51 | export class App { 52 | title: string; 53 | constructor(router: Router, browserLocation: BrowserLocation) { 54 | this.title = 'Angular 2 CRUD Application'; 55 | 56 | // we need to manually go to the correct uri until the router is fixed 57 | let uri = browserLocation.path(); 58 | router.navigate(uri); 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/webapp/app/pages/view/view-book.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | ISBN: 9 | 10 | {{ book.isbn }} 12 | 13 | 14 | 15 | 16 | Title: 18 | 19 | {{ book.title }} 21 | 22 | 23 | 24 | 25 | Author: 27 | 28 | {{ book.author }} 30 | 31 | 32 | 33 | 34 | Publication Date: 36 | 37 | {{ book.publicationDate }} 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/webapp/app/pages/view/view-book.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // Angular 2 4 | import {Component, View, Directive} from 'angular2/angular2'; 5 | import {RouteParams} from 'angular2/router'; 6 | import {Inject} from 'angular2/di'; 7 | 8 | import {BookService} from '../../services/BookService'; 9 | import {Book} from '../../models/Book'; 10 | 11 | @Component({ 12 | selector: 'view-book' 13 | }) 14 | 15 | @View({ 16 | templateUrl: './app/pages/view/view-book.html' 17 | }) 18 | 19 | export class ViewBook { 20 | book: Book = new Book(); 21 | 22 | constructor(@Inject(RouteParams) params, public bookService:BookService) { 23 | this.getBook(params.get('id')); 24 | } 25 | 26 | getBook(id:string) { 27 | this.bookService.getBook(id) 28 | .map(res => res.json()) 29 | .subscribe(res => this.book = Book.fromJSON(res)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/webapp/app/services/BookService.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {Inject} from 'angular2/di'; 4 | import {Http, BaseRequestOptions, Headers, httpInjectables} from 'angular2/http'; 5 | 6 | export class BookService { 7 | http: Http; 8 | baseURL: string; 9 | baseRequestOptions: BaseRequestOptions; 10 | 11 | constructor(@Inject(Http) http, @Inject(BaseRequestOptions) baseRequestOptions) { 12 | this.http = http; 13 | this.baseURL = '/api/books'; 14 | this.baseRequestOptions = baseRequestOptions; 15 | } 16 | 17 | _callAPI(url:string, method:string, data:any) { 18 | return window.fetch(url, { 19 | method: method, 20 | headers: { 21 | 'Accept': 'application/json', 22 | 'Content-Type': 'application/json' 23 | }, 24 | body: JSON.stringify(data) 25 | }) 26 | } 27 | 28 | getBooks() { 29 | return this.http.get(this.baseURL); 30 | } 31 | 32 | getBook(id:string) { 33 | return this.http.get(this.baseURL + '/' + id); 34 | } 35 | 36 | updateBook(id:string, data:any) { 37 | return this._callAPI(this.baseURL + '/' + id, 'PUT', data); 38 | 39 | /*var headers = new Headers(); 40 | headers.set('Content-Type', 'application/json'); 41 | return this.http.put( 42 | this.baseURL + '/' + id, 43 | JSON.stringify(data), 44 | this.baseRequestOptions.merge({ 45 | headers: headers 46 | }) 47 | );*/ 48 | } 49 | 50 | createBook(data:any) { 51 | return this._callAPI(this.baseURL, 'POST', data); 52 | 53 | /*var headers = new Headers(); 54 | headers.set('Content-Type', 'application/json'); 55 | return this.http.post( 56 | this.baseURL + '/' + id, 57 | JSON.stringify(data), 58 | this.baseRequestOptions.merge({ 59 | headers: headers 60 | }) 61 | );*/ 62 | } 63 | 64 | deleteBook(id:string) { 65 | return this.http.delete(this.baseURL + '/' + id); 66 | } 67 | } 68 | 69 | export let bookServiceInjectables = [ 70 | BookService, 71 | httpInjectables 72 | ]; 73 | -------------------------------------------------------------------------------- /src/webapp/app/services/services.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import {bookServiceInjectables} from './BookService'; 3 | 4 | export var appServicesInjectables:Array = [ 5 | bookServiceInjectables 6 | ]; 7 | -------------------------------------------------------------------------------- /src/webapp/assets/styles/base.less: -------------------------------------------------------------------------------- 1 | main { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | } 5 | 6 | table.table > thead > tr > th, 7 | table.table > tbody > tr > td { 8 | vertical-align: middle; 9 | } 10 | -------------------------------------------------------------------------------- /src/webapp/assets/styles/main.less: -------------------------------------------------------------------------------- 1 | @import "../../../../bower_components/bootstrap/less/bootstrap"; 2 | @import "base"; 3 | -------------------------------------------------------------------------------- /src/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular 2 Boilerplate 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | Loading ... 20 | 21 | 22 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "es6-promise/es6-promise.d.ts": { 9 | "commit": "84dfeeac378552c22297a5d555b1999a396d7e7c" 10 | }, 11 | "rx/rx.d.ts": { 12 | "commit": "84dfeeac378552c22297a5d555b1999a396d7e7c" 13 | }, 14 | "rx/rx-lite.d.ts": { 15 | "commit": "84dfeeac378552c22297a5d555b1999a396d7e7c" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /typings/_custom/browser.d.ts: -------------------------------------------------------------------------------- 1 | interface ObjectConstructor { 2 | assign(target: any, ...sources: any[]): any; 3 | observe(target: any, callback: Function, acceptList?: Array): void; 4 | } 5 | -------------------------------------------------------------------------------- /typings/_custom/custom.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | -------------------------------------------------------------------------------- /typings/_custom/ng2.d.ts: -------------------------------------------------------------------------------- 1 | declare var zone: any; 2 | declare var Zone: any; 3 | 4 | declare module "angular2/http" { 5 | class Http { 6 | get(url: string): any; 7 | delete(url: string): any; 8 | } 9 | class BaseRequestOptions {} 10 | var Headers: any; 11 | var httpInjectables: any; 12 | } 13 | 14 | declare module "angular2/change_detection" { 15 | class Pipe {} 16 | class NullPipeFactory {} 17 | class PipeRegistry { 18 | constructor(pipes: any) 19 | } 20 | class JitChangeDetection {} 21 | class ChangeDetection {} 22 | class DynamicChangeDetection {} 23 | var defaultPipes: any; 24 | } 25 | 26 | 27 | declare module "angular2/src/core/zone/ng_zone" { 28 | class NgZone { 29 | runOutsideAngular(func: Function): any 30 | } 31 | } 32 | 33 | declare module 'angular2/src/services/url_resolver' { 34 | class UrlResolver {} 35 | } 36 | 37 | declare module "angular2/src/facade/async" { 38 | class Observable {} 39 | class EventEmitter { 40 | next(val:any) 41 | return(val:any) 42 | throw(val:any) 43 | } 44 | } 45 | 46 | declare module "angular2/src/render/dom/shadow_dom/style_url_resolver" { 47 | class StyleUrlResolver {} 48 | } 49 | 50 | declare module "angular2/src/core/life_cycle/life_cycle" { 51 | class LifeCycle { 52 | tick(): any; 53 | } 54 | } 55 | 56 | declare module "zone.js" { 57 | var zone: any; 58 | var Zone: any; 59 | } 60 | 61 | declare module "angular2/directives" { 62 | function NgSwitch(): void; 63 | function NgSwitchWhen(): void; 64 | function NgSwitchDefault(): void; 65 | function NgNonBindable(): void; 66 | function NgIf(): void; 67 | function NgFor(): void; 68 | 69 | var formDirectives: any; 70 | var coreDirectives: any; 71 | 72 | } 73 | 74 | declare module "angular2/forms" { 75 | var formDirectives: any; 76 | class FormBuilder { 77 | group(controls: any): any; 78 | } 79 | class Control { 80 | constructor(controls: any) 81 | updateValue(value: any) 82 | _valueChanges: any 83 | valueChanges: any 84 | } 85 | class ControlArray { 86 | removeAt(index: any) 87 | push(item: any) 88 | } 89 | class ControlGroup { 90 | constructor(controls: any) 91 | controls: any; 92 | valueChanges: any; 93 | } 94 | class Validators { 95 | static required: any; 96 | } 97 | } 98 | 99 | declare module "angular2/render" { 100 | class EmulatedScopedShadowDomStrategy { 101 | constructor(styleInliner: any, styleUrlResolver: any, styleHost: any) 102 | } 103 | class EmulatedUnscopedShadowDomStrategy { 104 | constructor(styleUrlResolver: any, styleHost: any) 105 | } 106 | class NativeShadowDomStrategy { 107 | constructor(styleUrlResolver: any) 108 | } 109 | class ShadowDomStrategy {} 110 | } 111 | 112 | declare module "angular2/src/facade/browser" { 113 | var __esModule: boolean; 114 | var win: any; 115 | var document: any; 116 | var location: any; 117 | var gc: () => void; 118 | const Event: any; 119 | const MouseEvent: any; 120 | const KeyboardEvent: any; 121 | } 122 | 123 | declare module "angular2/src/router/browser_location" { 124 | class BrowserLocation { 125 | path(): string 126 | } 127 | } 128 | 129 | declare module "angular2/src/router/location" { 130 | class Location { 131 | normalize(url: string): string 132 | } 133 | } 134 | 135 | declare module "angular2/router" { 136 | class Instruction {} 137 | class Router { 138 | parent: any; 139 | navigate(url: string): Promise; 140 | config(config: any): Promise; 141 | deactivate(): Promise; 142 | activate(instruction: Instruction): Promise; 143 | recognize(url: string): Instruction; 144 | recognize(url: string): Instruction; 145 | renavigate(): Promise; 146 | generate(name:string, params:any): string; 147 | subscribe(onNext: Function): void; 148 | } 149 | var RouterOutlet: any; 150 | var RouterLink: any; 151 | var RouteParams: any; 152 | var routerInjectables: any; 153 | var RouteConfigAnnotation: any; 154 | var RouteConfig: any; 155 | } 156 | 157 | 158 | declare module "angular2/src/dom/browser_adapter" { 159 | class BrowserDomAdapter { 160 | static makeCurrent(): void; 161 | logError(error: any): void; 162 | attrToPropMap: any; 163 | query(selector: string): any; 164 | querySelector(el: any, selector: string): Node; 165 | querySelectorAll(el: any, selector: string): List; 166 | on(el: any, evt: any, listener: any): void; 167 | onAndCancel(el: any, evt: any, listener: any): Function; 168 | dispatchEvent(el: any, evt: any): void; 169 | createMouseEvent(eventType: string): MouseEvent; 170 | createEvent(eventType: any): Event; 171 | getInnerHTML(el: any): any; 172 | getOuterHTML(el: any): any; 173 | nodeName(node: Node): string; 174 | nodeValue(node: Node): string; 175 | type(node: HTMLInputElement): string; 176 | content(node: Node): Node; 177 | firstChild(el: any): Node; 178 | nextSibling(el: any): Node; 179 | parentElement(el: any): any; 180 | childNodes(el: any): List; 181 | childNodesAsList(el: any): List; 182 | clearNodes(el: any): void; 183 | appendChild(el: any, node: any): void; 184 | removeChild(el: any, node: any): void; 185 | replaceChild(el: Node, newChild: any, oldChild: any): void; 186 | remove(el: any): any; 187 | insertBefore(el: any, node: any): void; 188 | insertAllBefore(el: any, nodes: any): void; 189 | insertAfter(el: any, node: any): void; 190 | setInnerHTML(el: any, value: any): void; 191 | getText(el: any): any; 192 | setText(el: any, value: string): void; 193 | getValue(el: any): any; 194 | setValue(el: any, value: string): void; 195 | getChecked(el: any): any; 196 | setChecked(el: any, value: boolean): void; 197 | createTemplate(html: any): HTMLElement; 198 | createElement(tagName: any, doc?: Document): HTMLElement; 199 | createTextNode(text: string, doc?: Document): Text; 200 | createScriptTag(attrName: string, attrValue: string, doc?: Document): HTMLScriptElement; 201 | createStyleElement(css: string, doc?: Document): HTMLStyleElement; 202 | createShadowRoot(el: HTMLElement): DocumentFragment; 203 | getShadowRoot(el: HTMLElement): DocumentFragment; 204 | getHost(el: HTMLElement): HTMLElement; 205 | clone(node: Node): Node; 206 | hasProperty(element: any, name: string): boolean; 207 | getElementsByClassName(element: any, name: string): any; 208 | getElementsByTagName(element: any, name: string): any; 209 | classList(element: any): List; 210 | addClass(element: any, classname: string): void; 211 | removeClass(element: any, classname: string): void; 212 | hasClass(element: any, classname: string): any; 213 | setStyle(element: any, stylename: string, stylevalue: string): void; 214 | removeStyle(element: any, stylename: string): void; 215 | getStyle(element: any, stylename: string): any; 216 | tagName(element: any): string; 217 | attributeMap(element: any): any; 218 | hasAttribute(element: any, attribute: string): any; 219 | getAttribute(element: any, attribute: string): any; 220 | setAttribute(element: any, name: string, value: string): void; 221 | removeAttribute(element: any, attribute: string): any; 222 | templateAwareRoot(el: any): any; 223 | createHtmlDocument(): Document; 224 | defaultDoc(): Document; 225 | getBoundingClientRect(el: any): any; 226 | getTitle(): string; 227 | setTitle(newTitle: string): void; 228 | elementMatches(n: any, selector: string): boolean; 229 | isTemplateElement(el: any): boolean; 230 | isTextNode(node: Node): boolean; 231 | isCommentNode(node: Node): boolean; 232 | isElementNode(node: Node): boolean; 233 | hasShadowRoot(node: any): boolean; 234 | isShadowRoot(node: any): boolean; 235 | importIntoDoc(node: Node): Node; 236 | isPageRule(rule: any): boolean; 237 | isStyleRule(rule: any): boolean; 238 | isMediaRule(rule: any): boolean; 239 | isKeyframesRule(rule: any): boolean; 240 | getHref(el: Element): string; 241 | getEventKey(event: any): string; 242 | getGlobalEventTarget(target: string): EventTarget; 243 | getHistory(): History; 244 | getLocation(): Location; 245 | getBaseHref(): any; 246 | } 247 | } 248 | 249 | declare module "angular2/di" { 250 | 251 | function bind(token: any): any; 252 | class Injector { 253 | resolveAndCreateChild(bindings: [any]): Injector; 254 | } 255 | var Binding: any; 256 | var ResolvedBinding: any; 257 | var Dependency: any; 258 | var Key: any; 259 | var KeyRegistry: any; 260 | var TypeLiteral: any; 261 | var NoBindingError: any; 262 | var AbstractBindingError: any; 263 | var AsyncBindingError: any; 264 | var CyclicDependencyError: any; 265 | var InstantiationError: any; 266 | var InvalidBindingError: any; 267 | var NoAnnotationError: any; 268 | var OpaqueToken: any; 269 | var ___esModule: any; 270 | var InjectAnnotation: any; 271 | var InjectPromiseAnnotation: any; 272 | var InjectLazyAnnotation: any; 273 | var OptionalAnnotation: any; 274 | var InjectableAnnotation: any; 275 | var DependencyAnnotation: any; 276 | var Inject: any; 277 | var InjectPromise: any; 278 | var InjectLazy: any; 279 | var Optional: any; 280 | var Injectable: any; 281 | } 282 | -------------------------------------------------------------------------------- /typings/_custom/webpack.d.ts: -------------------------------------------------------------------------------- 1 | declare var require: any; 2 | declare var __filename: string; 3 | declare var __dirname: string; 4 | declare var global: any; 5 | -------------------------------------------------------------------------------- /typings/es6-promise/es6-promise.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for es6-promise 2 | // Project: https://github.com/jakearchibald/ES6-Promise 3 | // Definitions by: François de Campredon , vvakame 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | interface Thenable { 7 | then(onFulfilled?: (value: R) => U | Thenable, onRejected?: (error: any) => U | Thenable): Thenable; 8 | then(onFulfilled?: (value: R) => U | Thenable, onRejected?: (error: any) => void): Thenable; 9 | } 10 | 11 | declare class Promise implements Thenable { 12 | /** 13 | * If you call resolve in the body of the callback passed to the constructor, 14 | * your promise is fulfilled with result object passed to resolve. 15 | * If you call reject your promise is rejected with the object passed to resolve. 16 | * For consistency and debugging (eg stack traces), obj should be an instanceof Error. 17 | * Any errors thrown in the constructor callback will be implicitly passed to reject(). 18 | */ 19 | constructor(callback: (resolve : (value?: R | Thenable) => void, reject: (error?: any) => void) => void); 20 | 21 | /** 22 | * onFulfilled is called when/if "promise" resolves. onRejected is called when/if "promise" rejects. 23 | * Both are optional, if either/both are omitted the next onFulfilled/onRejected in the chain is called. 24 | * Both callbacks have a single parameter , the fulfillment value or rejection reason. 25 | * "then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve. 26 | * If an error is thrown in the callback, the returned promise rejects with that error. 27 | * 28 | * @param onFulfilled called when/if "promise" resolves 29 | * @param onRejected called when/if "promise" rejects 30 | */ 31 | then(onFulfilled?: (value: R) => U | Thenable, onRejected?: (error: any) => U | Thenable): Promise; 32 | then(onFulfilled?: (value: R) => U | Thenable, onRejected?: (error: any) => void): Promise; 33 | 34 | /** 35 | * Sugar for promise.then(undefined, onRejected) 36 | * 37 | * @param onRejected called when/if "promise" rejects 38 | */ 39 | catch(onRejected?: (error: any) => U | Thenable): Promise; 40 | } 41 | 42 | declare module Promise { 43 | /** 44 | * Make a new promise from the thenable. 45 | * A thenable is promise-like in as far as it has a "then" method. 46 | */ 47 | function resolve(value?: R | Thenable): Promise; 48 | 49 | /** 50 | * Make a promise that rejects to obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error 51 | */ 52 | function reject(error: any): Promise; 53 | 54 | /** 55 | * Make a promise that fulfills when every item in the array fulfills, and rejects if (and when) any item rejects. 56 | * the array passed to all can be a mixture of promise-like objects and other objects. 57 | * The fulfillment value is an array (in order) of fulfillment values. The rejection value is the first rejection value. 58 | */ 59 | function all(promises: (R | Thenable)[]): Promise; 60 | 61 | /** 62 | * Make a Promise that fulfills when any item fulfills, and rejects if any item rejects. 63 | */ 64 | function race(promises: (R | Thenable)[]): Promise; 65 | } 66 | 67 | declare module 'es6-promise' { 68 | var foo: typeof Promise; // Temp variable to reference Promise in local context 69 | module rsvp { 70 | export var Promise: typeof foo; 71 | } 72 | export = rsvp; 73 | } 74 | -------------------------------------------------------------------------------- /typings/rx/rx-lite.d.ts: -------------------------------------------------------------------------------- 1 | // DefinitelyTyped: partial 2 | 3 | // This file contains common part of defintions for rx.d.ts and rx.lite.d.ts 4 | // Do not include the file separately. 5 | 6 | declare module Rx { 7 | export module internals { 8 | function isEqual(left: any, right: any): boolean; 9 | function addRef(xs: Observable, r: { getDisposable(): IDisposable; }): Observable; 10 | 11 | // Priority Queue for Scheduling 12 | export class PriorityQueue { 13 | constructor(capacity: number); 14 | 15 | length: number; 16 | 17 | isHigherPriority(left: number, right: number): boolean; 18 | percolate(index: number): void; 19 | heapify(index: number): void; 20 | peek(): ScheduledItem; 21 | removeAt(index: number): void; 22 | dequeue(): ScheduledItem; 23 | enqueue(item: ScheduledItem): void; 24 | remove(item: ScheduledItem): boolean; 25 | 26 | static count: number; 27 | } 28 | 29 | export class ScheduledItem { 30 | constructor(scheduler: IScheduler, state: any, action: (scheduler: IScheduler, state: any) => IDisposable, dueTime: TTime, comparer?: (x: TTime, y: TTime) => number); 31 | 32 | scheduler: IScheduler; 33 | state: TTime; 34 | action: (scheduler: IScheduler, state: any) => IDisposable; 35 | dueTime: TTime; 36 | comparer: (x: TTime, y: TTime) => number; 37 | disposable: SingleAssignmentDisposable; 38 | 39 | invoke(): void; 40 | compareTo(other: ScheduledItem): number; 41 | isCancelled(): boolean; 42 | invokeCore(): IDisposable; 43 | } 44 | } 45 | 46 | export module config { 47 | export var Promise: { new (resolver: (resolvePromise: (value: T) => void, rejectPromise: (reason: any) => void) => void): IPromise; }; 48 | } 49 | 50 | export module helpers { 51 | function noop(): void; 52 | function notDefined(value: any): boolean; 53 | function isScheduler(value: any): boolean; 54 | function identity(value: T): T; 55 | function defaultNow(): number; 56 | function defaultComparer(left: any, right: any): boolean; 57 | function defaultSubComparer(left: any, right: any): number; 58 | function defaultKeySerializer(key: any): string; 59 | function defaultError(err: any): void; 60 | function isPromise(p: any): boolean; 61 | function asArray(...args: T[]): T[]; 62 | function not(value: any): boolean; 63 | function isFunction(value: any): boolean; 64 | } 65 | 66 | export interface IDisposable { 67 | dispose(): void; 68 | } 69 | 70 | export class CompositeDisposable implements IDisposable { 71 | constructor (...disposables: IDisposable[]); 72 | constructor (disposables: IDisposable[]); 73 | 74 | isDisposed: boolean; 75 | length: number; 76 | 77 | dispose(): void; 78 | add(item: IDisposable): void; 79 | remove(item: IDisposable): boolean; 80 | toArray(): IDisposable[]; 81 | } 82 | 83 | export class Disposable implements IDisposable { 84 | constructor(action: () => void); 85 | 86 | static create(action: () => void): IDisposable; 87 | static empty: IDisposable; 88 | 89 | dispose(): void; 90 | } 91 | 92 | // Single assignment 93 | export class SingleAssignmentDisposable implements IDisposable { 94 | constructor(); 95 | 96 | isDisposed: boolean; 97 | current: IDisposable; 98 | 99 | dispose(): void ; 100 | getDisposable(): IDisposable; 101 | setDisposable(value: IDisposable): void ; 102 | } 103 | 104 | // SerialDisposable it's an alias of SingleAssignmentDisposable 105 | export class SerialDisposable extends SingleAssignmentDisposable { 106 | constructor(); 107 | } 108 | 109 | export class RefCountDisposable implements IDisposable { 110 | constructor(disposable: IDisposable); 111 | 112 | dispose(): void; 113 | 114 | isDisposed: boolean; 115 | getDisposable(): IDisposable; 116 | } 117 | 118 | export interface IScheduler { 119 | now(): number; 120 | 121 | schedule(action: () => void): IDisposable; 122 | scheduleWithState(state: TState, action: (scheduler: IScheduler, state: TState) => IDisposable): IDisposable; 123 | scheduleWithAbsolute(dueTime: number, action: () => void): IDisposable; 124 | scheduleWithAbsoluteAndState(state: TState, dueTime: number, action: (scheduler: IScheduler, state: TState) =>IDisposable): IDisposable; 125 | scheduleWithRelative(dueTime: number, action: () => void): IDisposable; 126 | scheduleWithRelativeAndState(state: TState, dueTime: number, action: (scheduler: IScheduler, state: TState) =>IDisposable): IDisposable; 127 | 128 | scheduleRecursive(action: (action: () =>void ) =>void ): IDisposable; 129 | scheduleRecursiveWithState(state: TState, action: (state: TState, action: (state: TState) =>void ) =>void ): IDisposable; 130 | scheduleRecursiveWithAbsolute(dueTime: number, action: (action: (dueTime: number) => void) => void): IDisposable; 131 | scheduleRecursiveWithAbsoluteAndState(state: TState, dueTime: number, action: (state: TState, action: (state: TState, dueTime: number) => void) => void): IDisposable; 132 | scheduleRecursiveWithRelative(dueTime: number, action: (action: (dueTime: number) =>void ) =>void ): IDisposable; 133 | scheduleRecursiveWithRelativeAndState(state: TState, dueTime: number, action: (state: TState, action: (state: TState, dueTime: number) =>void ) =>void ): IDisposable; 134 | 135 | schedulePeriodic(period: number, action: () => void): IDisposable; 136 | schedulePeriodicWithState(state: TState, period: number, action: (state: TState) => TState): IDisposable; 137 | } 138 | 139 | export interface Scheduler extends IScheduler { 140 | } 141 | 142 | export interface SchedulerStatic { 143 | new ( 144 | now: () => number, 145 | schedule: (state: any, action: (scheduler: IScheduler, state: any) => IDisposable) => IDisposable, 146 | scheduleRelative: (state: any, dueTime: number, action: (scheduler: IScheduler, state: any) => IDisposable) => IDisposable, 147 | scheduleAbsolute: (state: any, dueTime: number, action: (scheduler: IScheduler, state: any) => IDisposable) => IDisposable): Scheduler; 148 | 149 | normalize(timeSpan: number): number; 150 | 151 | immediate: IScheduler; 152 | currentThread: ICurrentThreadScheduler; 153 | timeout: IScheduler; 154 | } 155 | 156 | export var Scheduler: SchedulerStatic; 157 | 158 | // Current Thread IScheduler 159 | interface ICurrentThreadScheduler extends IScheduler { 160 | scheduleRequired(): boolean; 161 | } 162 | 163 | // Notifications 164 | export class Notification { 165 | accept(observer: IObserver): void; 166 | accept(onNext: (value: T) => TResult, onError?: (exception: any) => TResult, onCompleted?: () => TResult): TResult; 167 | toObservable(scheduler?: IScheduler): Observable; 168 | hasValue: boolean; 169 | equals(other: Notification): boolean; 170 | kind: string; 171 | value: T; 172 | exception: any; 173 | 174 | static createOnNext(value: T): Notification; 175 | static createOnError(exception: any): Notification; 176 | static createOnCompleted(): Notification; 177 | } 178 | 179 | /** 180 | * Promise A+ 181 | */ 182 | export interface IPromise { 183 | then(onFulfilled: (value: T) => IPromise, onRejected: (reason: any) => IPromise): IPromise; 184 | then(onFulfilled: (value: T) => IPromise, onRejected?: (reason: any) => R): IPromise; 185 | then(onFulfilled: (value: T) => R, onRejected: (reason: any) => IPromise): IPromise; 186 | then(onFulfilled?: (value: T) => R, onRejected?: (reason: any) => R): IPromise; 187 | } 188 | 189 | // Observer 190 | export interface IObserver { 191 | onNext(value: T): void; 192 | onError(exception: any): void; 193 | onCompleted(): void; 194 | } 195 | 196 | export interface Observer extends IObserver { 197 | toNotifier(): (notification: Notification) => void; 198 | asObserver(): Observer; 199 | } 200 | 201 | interface ObserverStatic { 202 | create(onNext?: (value: T) => void, onError?: (exception: any) => void, onCompleted?: () => void): Observer; 203 | fromNotifier(handler: (notification: Notification, thisArg?: any) => void): Observer; 204 | } 205 | 206 | export var Observer: ObserverStatic; 207 | 208 | export interface IObservable { 209 | subscribe(observer: Observer): IDisposable; 210 | subscribe(onNext?: (value: T) => void, onError?: (exception: any) => void, onCompleted?: () => void): IDisposable; 211 | 212 | subscribeOnNext(onNext: (value: T) => void, thisArg?: any): IDisposable; 213 | subscribeOnError(onError: (exception: any) => void, thisArg?: any): IDisposable; 214 | subscribeOnCompleted(onCompleted: () => void, thisArg?: any): IDisposable; 215 | } 216 | 217 | export interface Observable extends IObservable { 218 | forEach(onNext?: (value: T) => void, onError?: (exception: any) => void, onCompleted?: () => void): IDisposable; // alias for subscribe 219 | toArray(): Observable; 220 | 221 | catch(handler: (exception: any) => Observable): Observable; 222 | catchException(handler: (exception: any) => Observable): Observable; // alias for catch 223 | catch(handler: (exception: any) => IPromise): Observable; 224 | catchException(handler: (exception: any) => IPromise): Observable; // alias for catch 225 | catch(second: Observable): Observable; 226 | catchException(second: Observable): Observable; // alias for catch 227 | combineLatest(second: Observable, resultSelector: (v1: T, v2: T2) => TResult): Observable; 228 | combineLatest(second: IPromise, resultSelector: (v1: T, v2: T2) => TResult): Observable; 229 | combineLatest(second: Observable, third: Observable, resultSelector: (v1: T, v2: T2, v3: T3) => TResult): Observable; 230 | combineLatest(second: Observable, third: IPromise, resultSelector: (v1: T, v2: T2, v3: T3) => TResult): Observable; 231 | combineLatest(second: IPromise, third: Observable, resultSelector: (v1: T, v2: T2, v3: T3) => TResult): Observable; 232 | combineLatest(second: IPromise, third: IPromise, resultSelector: (v1: T, v2: T2, v3: T3) => TResult): Observable; 233 | combineLatest(second: Observable, third: Observable, fourth: Observable, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4) => TResult): Observable; 234 | combineLatest(second: Observable, third: Observable, fourth: IPromise, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4) => TResult): Observable; 235 | combineLatest(second: Observable, third: IPromise, fourth: Observable, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4) => TResult): Observable; 236 | combineLatest(second: Observable, third: IPromise, fourth: IPromise, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4) => TResult): Observable; 237 | combineLatest(second: IPromise, third: Observable, fourth: Observable, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4) => TResult): Observable; 238 | combineLatest(second: IPromise, third: Observable, fourth: IPromise, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4) => TResult): Observable; 239 | combineLatest(second: IPromise, third: IPromise, fourth: Observable, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4) => TResult): Observable; 240 | combineLatest(second: IPromise, third: IPromise, fourth: IPromise, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4) => TResult): Observable; 241 | combineLatest(second: Observable, third: Observable, fourth: Observable, fifth: Observable, resultSelector: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5) => TResult): Observable; 242 | combineLatest(souces: Observable[], resultSelector: (firstValue: T, ...otherValues: TOther[]) => TResult): Observable; 243 | combineLatest(souces: IPromise[], resultSelector: (firstValue: T, ...otherValues: TOther[]) => TResult): Observable; 244 | concat(...sources: Observable[]): Observable; 245 | concat(...sources: IPromise[]): Observable; 246 | concat(sources: Observable[]): Observable; 247 | concat(sources: IPromise[]): Observable; 248 | concatAll(): T; 249 | concatObservable(): T; // alias for concatAll 250 | concatMap(selector: (value: T, index: number) => Observable, resultSelector: (value1: T, value2: T2, index: number) => R): Observable; // alias for selectConcat 251 | concatMap(selector: (value: T, index: number) => IPromise, resultSelector: (value1: T, value2: T2, index: number) => R): Observable; // alias for selectConcat 252 | concatMap(selector: (value: T, index: number) => Observable): Observable; // alias for selectConcat 253 | concatMap(selector: (value: T, index: number) => IPromise): Observable; // alias for selectConcat 254 | concatMap(sequence: Observable): Observable; // alias for selectConcat 255 | merge(maxConcurrent: number): T; 256 | merge(other: Observable): Observable; 257 | merge(other: IPromise): Observable; 258 | mergeAll(): T; 259 | mergeObservable(): T; // alias for mergeAll 260 | skipUntil(other: Observable): Observable; 261 | skipUntil(other: IPromise): Observable; 262 | switch(): T; 263 | switchLatest(): T; // alias for switch 264 | takeUntil(other: Observable): Observable; 265 | takeUntil(other: IPromise): Observable; 266 | zip(second: Observable, resultSelector: (v1: T, v2: T2) => TResult): Observable; 267 | zip(second: IPromise, resultSelector: (v1: T, v2: T2) => TResult): Observable; 268 | zip(second: Observable, third: Observable, resultSelector: (v1: T, v2: T2, v3: T3) => TResult): Observable; 269 | zip(second: Observable, third: IPromise, resultSelector: (v1: T, v2: T2, v3: T3) => TResult): Observable; 270 | zip(second: IPromise, third: Observable, resultSelector: (v1: T, v2: T2, v3: T3) => TResult): Observable; 271 | zip(second: IPromise, third: IPromise, resultSelector: (v1: T, v2: T2, v3: T3) => TResult): Observable; 272 | zip(second: Observable
{{ book.isbn }}
{{ book.title }}
{{ book.author }}
{{ book.publicationDate }}