peggy angular 2 in meteor
TRANSCRIPT
Angular 2 in MeteorPEGGY2015-09-11
Install Angular 2
Angular 2 Package meteor add shmck:angular2
TypeScript meteor add netanelgilad:angular2-typescript
System.js
System.js is a module loader built into the shmck:angular2 package. We'll use it to load our root component.
Import bootstrap component with System.js<body>
<p>Nothing here</p> <script>System.import("client/app");</script>
</body>
Root Component - client/index.html
A component is a controller with an attached view. Think of it like a brick in the castle of your app.
We'll create a root component tag called app. Let's include that component into our main index.html file:
<body> <app></app><script>System.import("client/app");</script>
</body>
client/app.ts
First we're importing the dependencies we needed from angular2/angular2. This is not a folder and file in your directory, but referring to an alias provided to System.js in the shmck:angular2 package.
Notice the @ syntax. In Angular 2, these are called Annotations.
import {Component, View, bootstrap} from 'angular2/angular2'; @Component({ selector: 'app' }) @View({ template: "<p>Hello World!</p>" }) class Socially {} bootstrap(Socially);
templateUrl
client/app.ts
client/index.ng.html
import {Component, View, bootstrap} from 'angular2/angular2'; @Component({ selector: 'app' }) @View({ templateUrl: "client/index.ng.html" }) class Socially {} bootstrap(Socially);
<p>Nothing here {{ 'yet' + '!' }}</p>
View
The syntax is very easy: {{ expression | pipe }} - Angular 2 interpolation, #variable – local variables available in the scope of the component. The
variable can be later referred in the component’s template, (event) - binding to events of element or directive, [property] - binding to properties of element. *property - the star means that it is a template
Ref. http://blog.codeleak.pl/2015/06/angular2hello-world.html
Data in the View
The *ng-for="party of parties" attribute in the li tag is an Angular repeater directive.
<div> <ul>
<li *ng-for="#party of parties"> {{party.name}}
<p>{{party.description}}</p> </li>
</ul> </div>
Model and Controller
import {Component, View, NgFor, bootstrap} from 'angular2/angular2'; @Component({ selector: 'app' }) @View({
templateUrl: "client/index.ng.html", directives: [NgFor] })
class Socially { constructor () {
this.parties = [ {'name': 'Dubstep-Free Zone', 'description': 'Can we please just for an evening not listen to dubstep.'}, {'name': 'All dubstep all the time', 'description': 'Get it on!'}, {'name': 'Savage lounging', 'description': 'Leisure suit required. And only fiercest manners.'} ];
} }bootstrap(Socially);
Use Collection
Use Meteor Tracker, a reactive wrapper that we will run data when a change occurs.
The fat arrow syntax => is also from ES2015, and tells the function to run in it's parents context.
model/parties.ts
client/app.tsParties = new Mongo.Collection("parties");
constructor() { this.parties = Parties.find().fetch(); }
Meteor Tracker
A reactive wrapper that we will run data when a change occurs. We will bind it to Angular's change detection system, Zone.js.
class Socially { constructor () {
Tracker.autorun(zone.bind(() => { this.parties = Parties.find().fetch();
})); }
}
Model Driven Forms
We are binding this.partiesForm here to a Control Group. Think of a control group as a wrapper for a group of form controls.
export class PartiesForm { constructor() {
this.partiesForm = new ControlGroup({ name: new Control(''), description: new Control('')
}); }
<form [ng-form-model]="partiesForm"><label>Name</label> <input type="text" ng-control="name"> <label>Description</label> <input type="text" ng-control="description"> <button>Add</button>
</form>
Two-way Bindings
Property bindings are used to pass data from the parent to the child, and event bindings are used to pass data from the child to the parent. So we can use the two to implement two-way bindings.
And since this is such a common pattern, Angular provides syntax sugar to remove the boilerplate.
Ref. http://victorsavkin.com/post/119943127151/angular-2-template-syntax
<input [ng-model]="todo.text" (ng-model)="todo.text=$event"></input>
<input [(ng-model)]="todo.text"></input>
Router
Router
Install meteor add shmck:angular2-router
import {Component, View, bootstrap} from 'angular2/angular2'; import {routerInjectables, routerDirectives, Router, RouteConfig} from 'angular2/router';@Component({ selector: 'app' }) @View({
template: '<router-outlet></router-outlet>‘,Directives: [routerDirectives]
}) @RouteConfig() class Socially {} bootstrap(Socially, [routerInjectables]);
Router - 2
imports from 'angular2/router' @RouteConfig() which will specify our routes View directives adding routerDirectives, allowing us to communicate
with the view inject routerInjectables into the child components a location where components will be created, the
<router-outlet></router-outlet> declare the base route in index.html (required when using the
HTML5LocationStrategy, rather than the HashLocationStategy)
Configuring Routes - client/app.ts
as: alias
import {PartiesList} from 'client/parties-list/parties-list';import {PartyDetails} from 'client/party-details/party-details'; @Component( ... ) @View( ... ) @RouteConfig([
{path: '/', component: PartiesList}, {path: '/party/:partyId', as: 'party-details', component: PartyDetails}
])
Problem
Event Bubbling
Clicking elements inside that div won’t trigger the event handler.
We have to be explicit by adding ^ symbol to our binding Ref. http://
blog.thoughtram.io/angular/2015/08/11/angular-2-template-syntax-demystified-part-1.html
<div (click)="statement()"> <div></div>
</div>
<div (^click)="statement()"> <div></div>
</div>
<div (click)="statement()"> </div>
Problem
Zone.js Zone.bind()
Meteor.call("test", function(e, n){ this.result = n;
}) ;
Meteor.call("test", (e, n)=>{ this.result = n;
}) ;
Meteor.call("test", zone.bind((e, n)=>{ this.result = n;
})) ;