Skip to content

Instantly share code, notes, and snippets.

@dimitardanailov
Last active August 11, 2022 01:25
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save dimitardanailov/81ccb87f16eab46a9759e7eefb127afd to your computer and use it in GitHub Desktop.
Save dimitardanailov/81ccb87f16eab46a9759e7eefb127afd to your computer and use it in GitHub Desktop.
Angular 2 and Typescript. Thank you to John Papa for awesome online course: http://www.johnpapa.net/angular-2-first-look

Angular 1

<body ng-controller="StoryController as vm">
  <h3>{{ vm.story.name }}</h3>
  <h3 ng-bind="vm.story.name"></h3>
</body>
(function () {
  angular
    .module('app')
    .controller('StoryController', StoryController);
    
    function StoryController() {
      var vm = this;
      vm.story = {
        'id': 100,
        'name': 'The Force Awekens'
      }
    }
})();

Demo

Angular 2

import { Component } from 'angular2/core';

@Component({
  'selector': 'my-story',
  'template': '<h3>{{story.name}}</h3>'
});

export class StoryComponent {
  story = {
    'id': 100,
    'name': 'The Force Awekens'
  }
}

Demo

Angular 1

<html ng-app="html">

Angular 2

import { bootstrap } from 'angular2/platform/browser';
import { AppComponent } from './app.component';

bootstrap(AppComponent); 

Angular 1

<ul>
  <li ng-repeat="vehicle in vm.vehicles, #i=index">
    {{i}}. {{ vehicle.name }}
  </li>
</ul>
<div ng-if="vm.vehicles.lenght">
  <h3>You have {{ vm.vehicles.lenght }} vehicles</h3>
</div>

Demo

Angular 2

<!-- 
  Structural Directives: 
  1. Indicated by the * prefix 
  2. Change the final output structure 
-->

<ul>
  <li *ngFor="#vehicle of vehicles">
    {{ vehicle.name }}
  </li>
</ul>
<div *ngIf="vehicles.lenght">
  <h3>You have {{ vm.vehicles.lenght }} vehicles</h3>
</div>

Demo

Angular 1

<h3>{{ vm.story.name }}</h3>

Angular 2

<h3>{{story.name}}</h3>

<!-- Оptional param -->
<h3>{{story?.name}}</h3>

Angular 1

<h3 ng-bind="vm.story.name></h3>

Demo

Angular 2

<h3 [innerText]="story.name"></h3>
<div [style.cole]="color">{{story.name}}</div>
<!-- Element property -->
<img [src]="vehicle.imageUrl"/>

<!-- Component property -->
<vehicle-detail [vehicle]="currentVehicle"></vehicle-detail>

<!-- Directive property -->
<div [ngClass]="{selected: isSelected}">X-wing</div>
<!--
  Property binding:
  1. for attibutes use attr
  2. User dots for nested properties
-->

<!-- Attibute binding -->
<button [attr.arial-label]="ok">ok</button>

<!-- Class property binding -->
<div [class.isStopped]="isStopped">Stopped</div>

<!-- Style Property binding -->
<button [style.color]="isStopped ? 'red' : 'blue'>

Angular 1

<button
  ng-click="vm.log('click')"
  ng-blur="vm.log('blur')">OK</button>

Angular 2

<button
  (click)="log('click')"
  (blur)="log('blur')">OK</button>

Angular 1

<input ng-model="vm.story.name"/>

Angular 2

<!-- 
Banana in a Box 
[()] sends a value from Component to Template, and sends value changes in the Template to the Component
-->
<input [(ngModel)]="story.name" />

Demo

Angular 1

<div ng-style="vm.story ? { visibility : 'visible'} : {'visibility: 'hidden'}">
  <div>
    <img ng-src="{{vm.imagePath}}" />
  </div>
  <div>
    <a ng-href="{{vm.link}}">
      {{vm.story}}
    </a>
  </div>
</div>

Demo

Angular 2

<!--
  Angular 2 Template Concepts Remove 40+ Angular 1 Built-In Directives
-->
<div [style.visibility] = "story ? 'visible' : 'hidden'>
  <div>
    <img [src]="imagePath" />
  </div>
  <div>
    <a [href]="link">{{story}}</a>
  </div>
</div>

Demo

Angular 1

angular
  .module('app')
  .service('VehicleService', VehicleService);

function VehicleService() {
  this.getVehicles = function() {
    return [
      { 'id': 1, 'name': 'X-Wing Fighter' },
      { 'id': 2, 'name': 'Tie Fighter' },
      { 'id': 3, 'name': 'Y-Wing Fighter' }
    ]
  }
}

Angular 2

/**
 * Factories ---------|
 * Services           |
 * Providers          | ============> Class
 * Constants          |
 * Values ------------|
 */

import { Injectable } from 'angular2/core';

@Injectable()
export class VehicleService {
  getVehicles = () => [
    { 'id': 1, 'name': 'X-Wing Fighter' },
    { 'id': 2, 'name': 'Tie Fighter' },
    { 'id': 3, 'name': 'Y-Wing Fighter' }
  ]
}

Angular 1

angular
  .module('app')
  .service('VehicleService', VehicleService); // Service registration

function VehicleService() {
  this.getVehicles = function() {
    return [
      { 'id': 1, 'name': 'X-Wing Fighter' },
      { 'id': 2, 'name': 'Tie Fighter' },
      { 'id': 3, 'name': 'Y-Wing Fighter' }
    ];
  }
}

Angular 2

import { VehicleService } from './vehicle.service';

@Component({
  'selector': 'my-vehicles'.
  'templateUrl': 'app/vehicles.component.html'.
  'providers': [VehicleService] // Service Registration
})
export class VehiclesComponent {
  constructor (private _vehicleService: VehicleService) {
  }
  vehicles = this._vehicleService.getVehicles();
}

Dependency Injection is how we provide an instance of a class to another Angular feature

Angular 1

angular
  .module('app')
  .controller('VehiclesController', VehiclesController);

VehiclesController.$inject = ['VehiclesService']; // Injection
function VehiclesController(VehiclesService) { // Injection
  var vm = this;
  vm.tile = 'Services';
  vm.vehicles = VehiclesService.getVehicles();
}

Demo

Angular 2

import { VehicleService } from './vehicle.service';

@Component({
  'selector': 'my-vehicles',
  'templateUrl': 'app/vehicles.component.html',
  'providers': [VehicleService]
})
export class VehiclesComponent {
  constructor (private _vehicleService: VehicleService) { // Injection
  }
  vehicles = this._vehicleService.getVehicles();
}

Demo

Angular 2

// CharacterListComponent

import { Component } from 'angular2/core';
import { Character } from './character';
import { CharacterComponent } from './character.component';

@Component({
  'selector': 'my-chracter-list',
  'templateUrl': 'app/character-list-component.html',
  'directives': [CharacterComponent] // Nested component
})
export class CharacterListComponent {
  selectedCharacter: Character;
  
  characters = [
    new Character(1, 'Han Solo'),
    new Character(2, 'Luke Skywalker'),
    new Character(3, 'BB-8'),
    new Character(4, 'Rey')
  ];
  
  select(character: Character) {
    this.selectedCharacter = character;
  }
}
<!-- app/character-list-component.html -->
<ul>
  <li *ngFor="#character of characters" (click)=select(character)>
    {{ character.name }}
  </li>
</ul>

<my-character *ngIf="selectedCharacter" [character]="selectedCharacter"></my-character>
// CharacterComponent

import { Component, Input } from 'angular2/core';
import { Character } from './character';

@Component({
  'selector': 'my-character',
  'templateUrl': 'app/character.component.html'
})
export class CharacterComponent {
  @Input() character: Character;
}

Demo

Angular 2

@Component({
  'selector': 'story-characters', // selector is the name of the element in the Template
  'templateUrl': './app/characters.component.html', // templateUrl point to the template  
  'styleUrls': ['./app.characters.component.css'], // styleUrls point to the styles
  'directives': [CharacterDetailComponent], // directives declare custom directives it uses
  'providers': [HTTP_PROVIDERS, CharacterService] // providers declare services the Component needs
})

Angular 2

@Component({
  'selector': 'story-characters', // selector is the name of the element in the Template
  'templateUrl': './app/characters.component.html', // templateUrl point to the template  
  'styleUrls': ['./app.characters.component.css'], // styleUrls point to the styles
  'directives': [CharacterDetailComponent], // directives declare custom directives it uses
  'providers': [HTTP_PROVIDERS, CharacterService] // providers declare services the Component needs
})

export class CharactersComponent implements OnInit {
  // Component can communite to anyone hosting it.
  @Output() changed = new EventEmitter<Character>();
  
  // Pass values into the nested component
  @Input() storyId: number;
  
  characters: Character[];
  selectedCharacter: Character;
  
  constructor(private _characterService: CharacterService) { }
  
  ngOnInit() {
    this._characterService.getCharacters(this.storyId)
      .subscribe(characters => this.characters = characters);
  }
  
  select(selectedCharacter: Character) {
    this.selectedCharacter = selectedCharacter;
    
    // Component emits events via output
    this.changed.emit(selectedCharacter);
  }
}

Demo

Angular 2 ViewChild

/**
 * Child
 */
export class FilterComponent {
  @Output() changed: EventEmitter<string>;
  filter: string;
  
  /**
   * Child Component's function
   */
  clear() {
    this.filter = '';
  }
}
/**
 * Parent
 */
export class CharacterListComponent {
  characters: Character[];
  
  // Grab the child
  @ViewChild(FilterComponent) filter: FilterComponent;
  
  filtered = this.characters;
  
  getCharacters() {
    this._characterService.getCharacters()
      .subscribe(characters => {
        this.characters = this.filtered = characters;
        this.filter.clear(); // Call child method
      });
  }
}

Angular 2

<p>{{ charachter.name | uppercase }}</p>
<p>{{ charachter.name | lowercase }}</p>
<!-- Date pipe -->
<p>{{ eventDate | date:'medium' }}</p>
<p>{{ eventDate | date:'yMMMd' }}</p>
<!-- Number pipe -->
<p>{{ price | currency }}</p>
<p>{{ value | percent:'1.1-1'}}</p>
<p>{{ value | number:'1.1-3'}}</p>
<!-- Async Pipe: Subscribes to a Promise or an Observable, returning the latest value emmited.  -->
// Custom Pipe
import { Pipe, PipeTransform} from 'angular2/core';

@Pipe({ 'name': 'myCustomPipe' })
export class MyCustomPipe implements PipeTransform {
  transform(value: string, args: any[]) {
    return // transformed value
  }
}

We use Http to get and save data with Promises or Observables. We isolate the http calls in a shared Service.

Angular 1

this.getVehicles = function() {
  return $http.get('api/vehicles')
    .then(function(response) {
      return reponse.data.data;
    })
    .catch(handleError);
}

Angular 2

getVehicles() {
  return this._http.get('api/vehicles')
    .map((reponse: Reponse) =>
      <Vehicle[]>.response.json.data
    )
    .catch(this.handleError);
}

Http is in a seperate module

Angular 2

<script src="../node_modules/angular2/bundles/http.dev.js"></script>
// app.component.ts
import { Component } from 'angular2/core';
import { HTTP_PROVIDERS } from 'angular2/http';

import { Vehicle, VehicleService } from './vehicle.service';
import { VehicleListComponent } from '.vehicle-list.component';

@Component({
  'selector': 'my-app',
  'template': '<my-vehicle-list></my-vehicle-list>',
  'directives': [ VehicleListComponent ],
  'providers': [
    HTTP_PROVIDERS,
    VehicleService
  ]
})
export class AppComponent() {
  
}
// vehicle.service.ts
@Injectable()

export class VehicleService() {
  constructor(private _http: Http) { }
  
  getVehicles() {
    return this._http.get('api/vehicles.json') //  Make and return the async GET call
      .map((response: Response) => <Vehicle[]>response.json().data) // Map the response
      .catch(this.handleError);
  }
  
  /**
   * Method tracking http error responses. 
   */
  private handleError(error: Response) {
    console.log(error);
    
    return Observable.throw(error.json().error || 'Server error');
  }
}
// vehicle-list.component.ts
constructor(private _vehicleService: VehicleService) { }
ngOnInit() { this.getHeroes(); }
getHeroes() {
  this._vehicleService.getVehicles()
    .subscribe(
      vehicles => this.vehicles = vehicles,
      error = this.errorMessage = <any>error
    );
}

The Async Pipe receives a Promisise or Observable as input and subscribres to the input, eventually emitting the value(s) as changes arrive.

// vehicle-list.component.ts

vehicles: Observable<Vehicle[]>; // Property becomes Observable

getHeroes() {
  this.vehicles = this._vehicleService.getVehicles(); // Set the observable from the Service.
}
<ul>
  <li *ngFor="#vehicle of vehicles | async>
    {{ vehicle.name }} 
  </li>
</ul>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment