sathyalog.files.wordpress.com · 1.1 1.2 1.3 2.1 2.1.1 2.1.1.1 2.1.1.2 2.1.1.3 2.1.1.4 2.1.1.5...
TRANSCRIPT
-
1.1
1.2
1.3
2.1
2.1.1
2.1.1.1
2.1.1.2
2.1.1.3
2.1.1.4
2.1.1.5
2.1.1.6
2.1.1.7
2.1.1.8
2.1.1.9
2.1.1.10
2.1.2
2.1.2.1
2.1.2.2
2.1.2.3
2.1.2.4
2.1.2.5
2.1.2.6
2.1.2.7
2.1.2.8
2.1.2.9
2.1.2.10
2.1.2.11
2.1.2.12
2.1.2.13
2.1.2.14
TableofContentsIntroduction
License
WhyAngular2?
EcmaScript6andTypeScriptFeatures
ES6
Classes
Refresheron'this'
ArrowFunctions
TemplateStrings
Inheritance
Delegation
ConstantsandBlockScopedVariables
...spreadand...rest
Destructuring
Modules
TypeScript
GettingStartedWithTypeScript
WorkingWithtsc
Typings
Linting
TypeScriptFeatures
TypeScriptClasses
Interfaces
Shapes
TypeInference
TypeKeyword
Decorators
PropertyDecorators
ClassDecorators
ParameterDecorators
2
-
3.1
3.1.1
3.1.2
3.1.3
3.1.4
3.1.5
3.1.6
4.1
4.1.1
4.1.2
5.1
5.1.1
5.1.2
5.1.2.1
5.1.2.2
5.1.2.3
5.1.2.4
5.1.3
5.1.4
5.1.5
6.1
6.1.1
6.1.1.1
6.1.1.2
6.1.2
6.1.2.1
6.1.2.2
6.1.2.3
6.1.2.4
7.1
7.1.1
7.1.2
7.1.3
7.1.4
TheJavaScriptToolchain
SourceControl:git
TheCommandLine
CommandLineJavaScript:NodeJS
Back-EndCodeSharingandDistribution:npm
ModuleLoading,BundlingandBuildTasks:Webpack
Chrome
BootstrappinganAngular2Application
UnderstandingtheFileStructure
BootstrappingProviders
ComponentsinAngular2
CreatingComponents
ApplicationStructurewithComponents
PassingDataintoaComponent
RespondingtoComponentEvents
UsingTwo-WayDataBinding
AccessingChildComponentsfromTemplate
Projection
StructuringApplicationswithComponents
UsingOtherComponents
Directives
AttributeDirectives
NgStyleDirective
NgClassDirective
StructuralDirectives
NgIfDirective
NgForDirective
NgSwitchDirectives
UsingMultipleStructuralDirectives
AdvancedComponents
ComponentLifecycle
AccessingOtherComponents
ViewEncapsulation
ElementRef
3
-
8.1
8.1.1
8.1.2
8.1.3
8.1.4
8.1.5
8.1.6
8.1.7
8.1.8
9.1
9.1.1
9.1.2
9.1.3
9.1.3.1
9.1.3.2
9.1.3.3
9.1.3.4
10.1
10.1.1
10.1.2
10.1.2.1
10.1.2.2
10.1.2.3
10.1.3
10.1.4
11.1
11.1.1
11.1.2
11.1.3
11.1.4
11.1.5
11.1.6
12.1
Observables
UsingObservables
ErrorHandling
DisposingSubscriptionsandReleasingResources
ObservablesvsPromises
UsingObservablesFromOtherSources
ObservablesArrayOperations
ColdvsHotObservables
Summary
Angular2DependencyInjection
WhatisDI?
DIFramework
Angular2'sDI
@Inject()and@Injectable
InjectionBeyondClasses
AvoidingInjectionCollisions:OpaqueToken
TheInjectorTree
Http
MakingRequests
CatchingRejections
CatchandRelease
CancelaRequest
Retry
Searchwithflatmap
RequestsasPromises
ChangeDetection
ChangeDetectionStrategiesinAngular1vsAngular2
HowChangeDetectionWorks
ChangeDetectorClasses
ChangeDetectionStrategy:OnPush
EnforcingImmutability
AdditionalResources
Zone.js
4
-
13.1
13.1.1
13.1.1.1
13.1.1.1.1
13.1.1.1.2
13.1.1.2
13.1.1.2.1
13.1.1.2.2
13.1.2
13.1.2.1
13.1.2.2
14.1
14.1.1
14.1.2
14.1.3
14.1.3.1
14.1.3.2
14.1.4
14.1.4.1
14.1.4.1.1
14.1.4.2
14.1.4.2.1
14.1.4.2.2
14.1.4.3
14.1.4.4
14.1.4.5
15.1
15.1.1
15.1.2
15.1.3
16.1
16.1.1
16.1.2
16.1.2.1
AdvancedAngular
Directives
CreatinganAttributeDirective
ListeningtoanElementHost
SettingPropertiesinaDirective
CreatingaStructuralDirective
ViewContainersandEmbeddedViews
ProvidingContextVariablestoDirectives
AoT
AoTlimitations
AoTConfiguration
Immutable.js
WhatisImmutability?
TheCaseforImmutability
JavaScriptSolutions
Object.assign
Object.freeze
Immutable.jsBasics
Immutable.Map
Map.merge
NestedObjects
DeletingKeys
MapsareIterable
Immutable.List
PerformanceandTransientChanges
OfficialDocumentation
Pipes
UsingPipes
CustomPipes
StatefulPipes
Forms
GettingStarted
Template-DrivenForms
NestingFormData
5
-
16.1.2.2
16.1.2.3
16.1.3
16.1.3.1
16.1.3.2
16.1.3.3
16.1.4
17.1
17.1.1
17.1.2
17.1.3
17.1.4
17.1.5
17.1.6
17.1.7
17.1.8
18.1
18.1.1
18.1.2
18.1.3
18.1.4
18.1.5
18.1.6
18.1.7
18.1.8
18.1.9
18.1.10
19.1
19.1.1
19.1.2
19.1.3
19.1.4
19.1.5
UsingTemplateModelBinding
ValidatingTemplate-DrivenForms
Reactive/Model-DrivenForms
FormBuilderBasics
ValidatingFormBuilderForms
FormBuilderCustomValidation
VisualCuesforUsers
Modules
WhatisanAngular2Module?
AddingComponents,PipesandServicestoaModule
CreatingaFeatureModule
DirectiveDuplications
LazyLoadingaModule
LazyLoadingandtheDependencyInjectionTree
SharedModulesandDependencyInjection
SharingtheSameDependencyInjectionTree
Routing
WhyRouting?
ConfiguringRoutes
RedirectingtheRoutertoAnotherRoute
DefiningLinksBetweenRoutes
DynamicallyAddingRouteComponents
UsingRouteParameters
DefiningChildRoutes
ControllingAccesstoorfromaRoute
PassingOptionalParameterstoaRoute
UsingAuxiliaryRoutes
ReduxandNgrx
ReviewofReducersandPureFunctions
ReducersasStateManagement
ReduxActions
ConfiguringyourApplicationtouseRedux
UsingReduxwithComponents
6
-
19.1.6
19.1.7
20.1
20.1.1
20.1.2
20.1.2.1
20.1.2.2
20.1.2.3
20.1.2.4
20.1.2.5
20.1.3
20.1.4
20.1.5
20.1.5.1
20.1.5.2
20.1.5.2.1
20.1.5.3
20.1.5.4
20.1.6
20.1.6.1
20.1.6.2
20.1.6.2.1
20.1.6.2.2
20.1.6.2.3
20.1.6.3
20.1.7
20.1.7.1
20.1.7.2
20.1.7.3
20.1.7.4
21.1
21.1.1
21.1.1.1
21.1.1.2
ReduxandComponentArchitecture
GettingMoreFromReduxandNgrx
TDDTesting
TheTestingToolchain
TestSetup
FilenameConventions
KarmaConfiguration
TestBedConfiguration(Optional)
Typings
ExecutingTestScripts
SimpleTest
UsingChai
TestingComponents
VerifyingMethodsandProperties
InjectingDependenciesandDOMChanges
OverridingComponentsforTesting
TestingAsynchronousActions
RefactoringHard-to-TestCode
TestingServices
TestingStrategiesforServices
TestingHTTPRequests
UsingMockBackend
AlternativeMockingStrategy
TestingJSONPandXHRBack-Ends
ExecutingTestsAsynchronously
TestingRedux
TestingSimpleActions
TestingComplexActions
TestingReducers
Afterthoughts
MigratingAngular1.xProjectstoAngular2
MigrationPrep
UpgradingToAngular1.3+Style
UsingWebpack
7
-
21.1.1.3
21.1.2
21.1.3
21.1.4
21.1.4.1
21.1.4.2
21.1.5
21.1.5.1
21.1.5.2
21.1.5.3
21.1.5.4
21.1.5.5
21.1.5.6
21.1.5.7
21.1.5.8
22.1
22.1.1
22.1.1.1
22.1.1.2
22.1.1.3
22.1.1.4
22.1.2
23.1
23.1.1
23.1.2
23.1.3
23.1.4
23.1.5
23.1.6
23.1.7
23.1.8
23.1.9
23.1.10
MigratingToTypeScript
ChoosinganUpgradePath
AvoidingTotalConversion
Usingng-metadata(Angular1.xUsing2Style)
Bootstrappingng-metadata
ComponentsandServices
Usingng-upgrade(Angular1.xCoexistingWithAngular2)
OrderofOperations
ReplacingServiceswithTypeScriptClasses
Bootstrappingng-upgrade
DowngradingComponents
UpgradingComponents
ProjectingAngular1ContentintoAngular2Components
TranscludingAngular2ComponentsintoAngular1Directives
InjectingAcrossFrameworks
ProjectSetup
Webpack
InstallationandUsage
Loaders
Plugins
Summary
NPMScriptsIntegration
AngularCLI
Setup
CreatingaNewApp
ServingtheApp
CreatingComponents
CreatingRoutes
CreatingOtherThings
Testing
Linting
CLICommandOverview
AddingThirdPartyLibraries
8
-
23.1.11
24.1
24.1.1
24.1.2
24.1.2.1
24.1.2.2
24.1.2.3
24.1.3
24.1.3.1
24.1.3.2
24.1.3.3
24.1.3.4
24.1.4
25.1
25.1.1
25.1.2
25.1.3
25.1.4
25.1.4.1
25.1.4.2
26.1
26.2
IntegratinganExistingApp
AccessibilityinAngular2
WhyMakemyApplicationAccessible?
KeyConcernsofAccessibleWebApplications
SemanticMarkup
KeyboardAccessibility
VisualAssistance
TestingforAccessibility
IsmyApplicationReadable?
IsmyApplicationPredictable?
IsmyApplicationNavigable?
TestingwithScreenReaders
AdditionalResources
InternationalizationinAngular2
Whatistheprocesslikeandhowisinvolved?
Markingtextinourtemplates
ExtractingtranslationtextusingtheAngularCLI
Howtoimportthecompletedtranslationfiles
UsingtheAoTCompiler
UsingtheJiTCompiler
Glossary
FurtherReadingAndReference
9
-
Rangle'sAngular2TrainingBook
Overthelastthreeandahalfyears,AngularJShasbecometheleadingopensourceJavaScriptapplicationframeworkforhundredsofthousandsofprogrammersaroundtheworld.The"1.x"versionofAngularJShasbeenwidelyusedandbecameextremelypopularforcomplexapplications.Thenew"Angular2"hasalsoannounceditsfinalreleaseversion.
AboutRangle’sAngular2TrainingBookWedevelopedthisbooktobeusedascoursematerialforRangle'sAngular2training,butmanypeoplehavefoundittobeusefulforlearningAngular2ontheirown.ThisbookwillcoverthemostimportantAngular2topics,fromgettingstartedwiththeAngular2toolchaintowritingAngular2applicationsinascalableandmaintainablemanner.
Ifyoufindthismaterialuseful,youshouldalsoconsiderregisteringforoneofRangle’strainingcourses,whichfacilitatehands-onlearningandareagreatfitforcompaniesthatneedtotransitiontheirtechnologytoAngular2,orindividualslookingtoupgradetheirskills.
Rangle.ioalsohasanAngular1.xbookwhichisgearedtowardswritingAngular1.xapplicationsinanAngular2style.Wehopeyouenjoythisbook.WewelcomeyourfeedbackintheDiscussionArea.
Introduction
10
http://angularjs.blogspot.ca/2016/09/angular2-final.htmlhttp://go.rangle.io/angular-2-traininghttp://go.rangle.io/angular-2-traininghttp://ngcourse-1.rangle.io/https://www.gitbook.com/book/rangle-io/ngcourse2/discussions
-
Introduction
11
-
LicenseCreativeCommonsAttribution-ShareAlike4.0International(CCBY-SA4.0)
Thisisahuman-readablesummaryof(andnotasubstitutefor)thelicense.
Youarefreeto:Share—copyandredistributethematerialinanymediumorformat
Adapt—remix,transformandbuilduponthematerialforanypurpose,evencommercially.
Thelicensorcannotrevokethesefreedomsaslongasyoufollowthelicenseterms.
Underthefollowingterms:Attribution—Youmustgiveappropriatecredit,providealinktothelicense,andindicateifchangesweremade.Youmaydosoinanyreasonablemanner,butnotinanywaythatsuggeststhelicensorendorsesyouoryouruse.
ShareAlike—Ifyouremix,transformorbuilduponthematerial,youmustdistributeyourcontributionsunderthesamelicenseastheoriginal.
Noadditionalrestrictions—Youmaynotapplylegaltermsortechnologicalmeasuresthatlegallyrestrictothersfromdoinganythingthelicensepermits.
License
12
https://creativecommons.org/licenses/by-sa/4.0/legalcodehttps://creativecommons.org/licenses/by-sa/4.0/legalcode
-
WhyAngular2?Therearemanyfront-endJavaScriptframeworkstochoosefromtoday,eachwithitsownsetoftrade-offs.ManypeoplewerehappywiththefunctionalitythatAngular1.xaffordedthem.Angular2improvedonthatfunctionalityandmadeitfaster,morescalableandmoremodern.OrganizationsthatfoundvalueinAngular1.xwillfindmorevalueinAngular2.
Angular2'sAdvantagesThefirstreleaseofAngularprovidedprogrammerswiththetoolstodevelopandarchitectlargescaleJavaScriptapplications,butitsagehasrevealedanumberofflawsandsharpedges.Angular2wasbuiltonfiveyearsofcommunityfeedback.
Angular2IsEasier
ThenewAngular2codebaseismoremodern,morecapableandeasierfornewprogrammerstolearnthanAngular1.x,whilealsobeingeasierforprojectveteranstoworkwith.
WithAngular1,programmershadtounderstandthedifferencesbetweenControllers,Services,Factories,Providersandotherconceptsthatcouldbeconfusing,especiallyfornewprogrammers.
Angular2isamorestreamlinedframeworkthatallowsprogrammerstofocusonsimplybuildingJavaScriptclasses.Viewsandcontrollersarereplacedwithcomponents,whichcanbedescribedasarefinedversionofdirectives.EvenexperiencedAngularprogrammersarenotalwaysawareofallthecapabilitiesofAngular1.xdirectives.Angular2componentsareconsiderablyeasiertoread,andtheirAPIfeatureslessjargonthanAngular1.x'sdirectives.Additionally,tohelpeasethetransitiontoAngular2,theAngularteamhasaddeda.componentmethodtoAngular1.5,whichhasbeenback-portedbycommunitymemberToddMottotov1.3.
TypeScript
Angular2waswritteninTypeScript,asupersetofJavaScriptthatimplementsmanynewES2016+features.
WhyAngular2?
13
https://toddmotto.com/angular-component-method-back-ported-to-1.3/
-
Byfocusingonmakingtheframeworkeasierforcomputerstoprocess,Angular2allowsforamuchricherdevelopmentecosystem.Programmersusingsophisticatedtexteditors(orIDEs)willnoticedramaticimprovementswithauto-completionandtypesuggestions.TheseimprovementshelptoreducethecognitiveburdenoflearningAngular2.FortunatelyfortraditionalES5JavaScriptprogrammersthisdoesnotmeanthatdevelopmentmustbedoneinTypeScriptorES2015:programmerscanstillwritevanillaJavaScriptthatrunswithouttranspilation.
Familiarity
Despitebeingacompleterewrite,Angular2hasretainedmanyofitscoreconceptsandconventionswithAngular1.x,e.g.astreamlined,"nativeJS"implementationofdependencyinjection.ThismeansthatprogrammerswhoarealreadyproficientwithAngularwillhaveaneasiertimemigratingtoAngular2thananotherlibrarylikeReactorframeworklikeEmber.
PerformanceandMobile
Angular2wasdesignedformobilefromthegroundup.Asidefromlimitedprocessingpower,mobiledeviceshaveotherfeaturesandlimitationsthatseparatethemfromtraditionalcomputers.Touchinterfaces,limitedscreenrealestateandmobilehardwarehaveallbeenconsideredinAngular2.
Desktopcomputerswillalsoseedramaticimprovementsinperformanceandresponsiveness.
Angular2,likeReactandothermodernframeworks,canleverageperformancegainsbyrenderingHTMLontheserveroreveninawebworker.Dependingonapplication/sitedesignthisisomorphicrenderingcanmakeauser'sexperiencefeelevenmoreinstantaneous.
Thequestforperformancedoesnotendwithpre-rendering.Angular2makesitselfportabletonativemobilebyintegratingwithNativeScript,anopensourcelibrarythatbridgesJavaScriptandmobile.Additionally,theIonicteamisworkingonanAngular2versionoftheirproduct,providinganotherwaytoleveragenativedevicefeatureswithAngular2.
ProjectArchitectureandMaintenance
ThefirstiterationofAngularprovidedwebprogrammerswithahighlyflexibleframeworkfordevelopingapplications.Thiswasadramaticshiftformanywebprogrammers,andwhilethatframeworkwashelpful,itbecameevidentthatitwasoftentooflexible.Overtime,bestpracticesevolved,andacommunity-drivenstructurewasendorsed.
WhyAngular2?
14
https://www.nativescript.org/
-
Angular1.xtriedtoworkaroundvariousbrowserlimitationsrelatedtoJavaScript.Thiswasdonebyintroducingamodulesystemthatmadeuseofdependencyinjection.Thissystemwasnovel,butunfortunatelyhadissueswithtooling,notablyminificationandstaticanalysis.
Angular2.xmakesuseoftheES2015modulesystem,andmodernpackagingtoolslikewebpackorSystemJS.Modulesarefarlesscoupledtothe"Angularway",andit'seasiertowritemoregenericJavaScriptandplugitintoAngular.Theremovalofminificationworkaroundsandtheadditionofrigidprescriptionsmakemaintainingexistingapplicationssimpler.Thenewmodulesystemalsomakesiteasiertodevelopeffectivetoolingthatcanreasonbetteraboutlargerprojects.
NewFeatures
SomeoftheotherinterestingfeaturesinAngular2are:
FormBuilderChangeDetectionTemplatingRoutingAnnotationsObservablesShadowDOM
DifferencesBetweenAngular1&2Notethat"TransitionalArchitecture"referstoastyleofAngular1applicationwritteninawaythatmimicsAngular2'scomponentstyle,butwithcontrollersanddirectivesinsteadofTypeScriptclasses.
WhyAngular2?
15
-
OldSchoolAngular1.x
Angular1.xBest
Practices
TransitionalArchitecture Angular2
Nestedscopes("$scope",watches)
Usedheavily Avoided Avoided Gone
Directivesvscontrollers
Useasalternatives Usedtogether
Directivesascomponents
Componentdirectives
Controllerandserviceimplementation
Functions Functions ES6classes ES6classes
Modulesystem Angular'smodulesAngular'smodules ES6modules
ES6modules
Transpilerrequired No No TypeScript TypeScript
WhyAngular2?
16
-
EcmaScript6andTypeScriptFeatures
Figure:ES6andTypeScript
Thelanguageweusuallycall"JavaScript"isformallyknownas"EcmaScript".ThenewversionofJavaScript,knownas"ES6",offersanumberofnewfeaturesthatextendthepowerofthelanguage.
ES6isnotwidelysupportedintoday'sbrowsers,soitneedstobetranspiledtoES5.Youcanchoosebetweenseveraltranspilers,butwe'llbeusingTypeScript,whichiswhattheAngularteamusestowriteAngular2.Angular2makesuseofanumberoffeaturesofES6andTypeScript.
EcmaScript6andTypeScriptFeatures
17
-
ES6JavaScriptwascreatedin1995,butthelanguageisstillthrivingtoday.Therearesubsets,supersets,currentversionsandthelatestversionES6thatbringsalotofnewfeatures.
Someofthehighlights:
ClassesArrowFunctionsTemplateStringsInheritanceConstantsandBlockScopedVariablesSpreadandRestoperatorsDestructuringModules
ES6
18
-
ClassesClassesareanewfeatureinES6,usedtodescribetheblueprintofanobjectandmakeEcmaScript'sprototypicalinheritancemodelfunctionmorelikeatraditionalclass-basedlanguage.
classHamburger{constructor(){//Thisistheconstructor.}listToppings(){//Thisisamethod.}}
Traditionalclass-basedlanguagesoftenreservethewordthistoreferencethecurrent(runtime)instanceoftheclass.InJavascriptthisreferstothecallingcontextandthereforecanchangetobesomethingotherthantheobject.
ObjectAnobjectisaninstanceofaclasswhichiscreatedusingthenewoperator.Whenusingadotnotationtoaccessamethodontheobject,thiswillrefertotheobjecttotheleftofthedot.
letburger=newHamburger();burger.listToppings();
Inthesnippetabove,wheneverthisisusedfrominsideclassHamburger,itwillrefertoobjectburger.
ChangingCallerContextJavaScriptcodecanoptionallysupplythistoamethodatcalltimeusingoneofthefollowing.
Function.prototype.call(object[,arg,...])Function.prototype.bind(object[,arg,...])Function.prototype.apply(object[,argsArray])
Classes
19
-
Classes
20
-
ARefresheron thisInsideaJavaScriptclasswe'llbeusingthiskeywordtorefertotheinstanceoftheclass.E.g.,considerthiscase:
classToppings{...
formatToppings(){/*implementationdetails*/}
list(){returnthis.formatToppings(this.toppings);}}
HerethisreferstoaninstanceoftheToppingsclass.Aslongasthelistmethodiscalledusingdotnotation,likemyToppings.list(),thenthis.formatToppings(this.toppings)invokestheformatToppings()methoddefinedontheinstanceoftheclass.ThiswillalsoensurethatinsideformatToppings,thisreferstothesameinstance.
However,thiscanalsorefertootherthings.Therearetwobasiccasesthatyoushouldremember.
1. Methodinvocation:
someObject.someMethod();
Here,thisusedinsidesomeMethodwillrefertosomeObject,whichisusuallywhatyouwant.
2. Functioninvocation:
someFunction();
Here,thisusedinsidesomeFunctioncanrefertodifferentthingsdependingonwhetherwearein"strict"modeornot.Withoutusingthe"strict"mode,thisreferstothecontextinwhichsomeFunction()wascalled.Thisrarelywhatyouwant,anditcanbeconfusingwhenthisisnotwhatyouwereexpecting,becauseofwherethefunctionwascalledfrom.In"strict"mode,thiswouldbeundefined,whichisslightlylessconfusing.
Refresheron'this'
21
-
ViewExample
Oneoftheimplicationsisthatyoucannoteasilydetachamethodfromitsobject.Considerthisexample:
varlog=console.log;log('Hello');
Inmanybrowsersthiswillgiveyouanerror.That'sbecauselogexpectsthistorefertoconsole,butthereferencewaslostwhenthefunctionwasdetachedfromconsole.
Thiscanbefixedbysettingthisexplicitly.Onewaytodothisisbyusingbind()method,whichallowsyoutospecifythevaluetouseforthisinsidetheboundfunction.
varlog=console.log.bind(console);log('Hello');
YoucanalsoachievethesameusingFunction.callandFunction.apply,butwewon'tdiscussthishere.
Anotherinstancewherethiscanbeconfusingiswithrespecttoanonymousfunctions,orfunctionsdeclaredwithinotherfunctions.Considerthefollowing:
classServerRequest{notify(){...}fetch(){getFromServer(functioncallback(err,data){this.notify();//thisisnotgoingtowork});}}
Intheabovecasethiswillnotpointtotheexpectedobject:in"strict"modeitwillbeundefined.ThisleadstoanotherES6feature-arrowfunctions,whichwillbecoverednext.
Refresheron'this'
22
http://jsbin.com/vekawimihe/2/edit?js,console
-
ArrowFunctionsES6offerssomenewsyntaxfordealingwiththis:"arrowfunctions".Arrowfunctionsalsomakehigherorderfunctionsmucheasiertoworkwith.
Thenew"fatarrow"notationcanbeusedtodefineanonymousfunctionsinasimplerway.
Considerthefollowingexample:
items.forEach(function(x){console.log(x);incrementedItems.push(x+1);});
Thiscanberewrittenasan"arrowfunction"usingthefollowingsyntax:
items.forEach((x)=>{console.log(x);incrementedItems.push(x+1);});
Functionsthatcalculateasingleexpressionandreturnitsvaluescanbedefinedevensimpler:
incrementedItems=items.map((x)=>x+1);
Thelatterisalmostequivalenttothefollowing:
incrementedItems=items.map(function(x){returnx+1;});
Thereisoneimportantdifference,however:arrowfunctionsdonotsetalocalcopyofthis,arguments,super,ornew.target.WhenthisisusedinsideanarrowfunctionJavaScriptusesthethisfromtheouterscope.Considerthefollowingexample:
ArrowFunctions
23
-
classToppings{constructor(toppings){this.toppings=Array.isArray(toppings)?toppings:[];}outputList(){this.toppings.forEach(function(topping,i){console.log(topping,i+'/'+this.toppings.length);//nothis})}}
varctrl=newToppings(['cheese','lettuce']);
ctrl.outputList();
Let'strythiscodeonES6Fiddle(http://www.es6fiddle.net/).Aswesee,thisgivesusanerror,sincethisisundefinedinsidetheanonymousfunction.
Now,let'schangethemethodtousethearrowfunction:
classToppings{constructor(toppings){this.toppings=Array.isArray(toppings)?toppings:[];}outputList(){this.toppings.forEach((topping,i)=>console.log(topping,i+'/'+this.toppings.length)//`this`works!)}}
varctrl=newToppings(['cheese','lettuce']);
Herethisinsidethearrowfunctionreferstotheinstancevariable.
Warningarrowfunctionsdonothavetheirownargumentsvariable,whichcanbeconfusingtoveteranJavaScriptprogrammers.superandnew.targetarealsoscopedfromtheouterenclosure.
ArrowFunctions
24
http://www.es6fiddle.net/
-
TemplateStringsIntraditionalJavaScript,textthatisenclosedwithinmatching"or'marksisconsideredastring.Textwithindoubleorsinglequotescanonlybeononeline.Therewasnowaytoinsertdataintothesestrings.Thisresultedinalotofuglyconcatenationcodethatlookedlike:
varname='Sam';varage=42;
console.log('hellomynameis'+name+'Iam'+age+'yearsold');
ES6introducesanewtypeofstringliteralthatismarkedwithbackticks(`).Thesestringliteralscanincludenewlines,andthereisastringinterpolationforinsertingvariablesintostrings:
varname='Sam';varage=42;
console.log(`hellomynameis${name},andIam${age}yearsold`);
Thereareallsortsofplaceswherethiskindofstringcancomeinhandy,andfront-endwebdevelopmentisoneofthem.
TemplateStrings
25
-
InheritanceJavaScript'sinheritanceworksdifferentlyfrominheritanceinotherlanguages,whichcanbeveryconfusing.ES6classesprovideasyntacticsugarattemptingtoalleviatetheissueswithusingprototypicalinheritancepresentinES5.
Toillustratethis,let'simagewehaveazooapplicationwheretypesofbirdsarecreated.Inclassicalinheritance,wedefineabaseclassandthensubclassittocreateaderivedclass.
SubclassingTheexamplecodebelowshowshowtoderivePenguinfromBirdusingtheextendskeyword.AlsopayattentiontothesuperkeywordusedinthesubclassconstructorofPenguin,itisusedtopasstheargumenttothebaseclassBird'sconstructor.
TheBirdclassdefinesthemethodwalkwhichisinheritedbythePenguinclassandisavailableforusebyinstanceofPenguinobjects.LikewisethePenguinclassdefinesthemethodswimwhichisnotavilabletoBirdobjects.Inheritanceworkstop-downfrombaseclasstoitssubclass.
ObjectInitializationTheclassconstructoriscalledwhenanobjectiscreatedusingthenewoperator,itwillbecalledbeforetheobjectisfullycreated.Aconsturctorisusedtopassinargumentstoinitializethenewlycreatedobject.
Theorderofobjectcreationstartsfromitsbaseclassandthenmovesdowntoanysubclass(es).
Inheritance
26
-
//BaseClass:ES6classBird{constructor(weight,height){this.weight=weight;this.height=height;}
walk(){console.log('walk!');}}
//SubclassclassPenguinextendsBird{constructor(weight,height){super(weight,height);}
swim(){console.log('swim!');}}
//Penguinobjectletpenguin=newPenguin(...);penguin.walk();//walk!penguin.swim();//swim!
BelowweshowhowprototypalinheritancewasdonebeforeclasswasintroducedtoJavaScript.
Inheritance
27
-
//JavaScriptclassicalinheritance.
//BirdconstructorfunctionBird(weight,height){this.weight=weight;this.height=height;}
//AddmethodtoBirdprototype.Bird.prototype.walk=function(){console.log("walk!");};
//Penguinconstructor.functionPenguin(weight,height){Bird.call(this,weight,height);}
//Prototypalinheritance(Penguinis-aBird).Penguin.prototype=Object.create(Bird.prototype);Penguin.prototype.constructor=Penguin;
//AddmethodtoPenguinprototype.Penguin.prototype.swim=function(){console.log("swim!");};
//CreateaPenguinobject.letpenguin=newPenguin(50,10);
//CallsmethodonBird,sinceit'snotdefinedbyPenguin.penguin.walk();//walk!
//CallsmethodonPenguin.penguin.swim();//swim!
Inheritance
28
-
DelegationIntheinheritancesectionwelookedatonewaytoextendaclassfunctionality,thereissecondwayusingdelegationtoextendfunctionality.Withdelegation,oneobjectwillcontainareferencetoadifferentobjectthatitwillhandoffarequesttoperformthefunctionality.
ThecodebelowshowshowtousedelegationwiththeBirdclassandPenguinclass.ThePenguinclasshasareferencetotheBirdclassanditdelegratescallmadetoit'swalkmethodovertoBird'swalkmethod.
//ES6classBird{constructor(weight,height){this.weight=weight;this.height=height;}walk(){console.log('walk!');}}
classPenguin{constructor(bird){this.bird=bird;}walk(){this.bird.walk();}swim(){console.log('swim!');}}
constbird=newBird(...);constpenguin=newPenguin(bird);penguin.walk();//walk!penguin.swim();//swim!
Agooddiscussionon'behaviourdelegation'canbefoundhere.
Delegation
29
https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch6.md
-
ConstantsandBlockScopedVariablesES6introducestheconceptofblockscoping.BlockscopingwillbefamiliartoprogrammersfromotherlanguageslikeC,Java,orevenPHP.InES5JavaScriptandearlier,varsarescopedtofunctions,andtheycan"see"outsidetheirfunctionstotheoutercontext.
varfive=5;varthreeAlso=three;//error
functionscope1(){varthree=3;varfiveAlso=five;//==5varsevenAlso=seven;//error}
functionscope2(){varseven=7;varfiveAlso=five;//==5varthreeAlso=three;//error}
InES5functionswereessentiallycontainersthatcouldbe"seen"outof,butnotinto.
InES6varstillworksthatway,usingfunctionsascontainers,buttherearetwonewwaystodeclarevariables:constandlet.
constandletuse{and}blocksascontainers,hence"blockscope".Blockscopingismostusefulduringloops.Considerthefollowing:
vari;for(i=0;i<10;i+=1){varj=i;letk=i;}console.log(j);//9console.log(k);//undefined
Despitetheintroductionofblockscoping,functionsarestillthepreferredmechanismfordealingwithmostloops.
letworkslikevarinthesensethatitsdataisread/write.letisalsousefulwhenusedinaforloop.Forexample,withoutlet,thefollowingexamplewouldoutput5,5,5,5,5:
ConstantsandBlockScopedVariables
30
-
for(varx=0;xconsole.log(x),0)}
However,whenusingletinsteadofvar,thevaluewouldbescopedinawaythatpeoplewouldexpect.
for(letx=0;xconsole.log(x),0)}
Alternatively,constisread-only.Onceconsthasbeenassigned,theidentifiercannotbereassigned.
Forexample:
constmyName='pat';letyourName='jo';
yourName='sam';//assignsmyName='jan';//error
Theread-onlynaturecanbedemonstratedwithanyobject:
constliteral={};
literal.attribute='test';//fineliteral=[];//error;
Howevertherearetwocaseswhereconstdoesnotworkasyouthinkitshould.
1. Aconstobjectliteral.2. Aconstreferencetoanobject.
ConstObjectLiteral
constperson={name:'Tammy'};
person.name='Pushpa';//OK,namepropertychanged.
person=null;//"TypeError:Assignmenttoconstantvariable.
ConstantsandBlockScopedVariables
31
-
Theexampleabovedemonstratesthatweareabletochangethenamepropertyofobjectperson,butweareunabletoresetthereferencepersonsinceithasbeenmarkedasconst.
ConstReferenceToAnObjectSomethingsimilartotheabovecodeisusingaconstreference,belowwe'veswitchtousingletfortheliteralobject.
letperson={name:'Tammy'};
constp=person;
p.name='Pushpa';//OK,namepropertychanged.
p=null;//"TypeError:Assignmenttoconstantvariable.
Takeaway,markinganobjectreferenceconstdoesnotmakepropertiesinsidetheobjectconst.
Ref:.
ConstantsandBlockScopedVariables
32
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
-
OperatorsSpreadandRestASpreadoperatorallowsin-placeexpansionofanexpressionforthefollowingcases:
1. Array2. Functioncall3. Multiplevariabledestructuring
TheRestoperatorworksintheoppositedirectionofthespreadoperator,itcollectsanindefinitenumberofcommaseparatedexpressionsintoanarray.
OperatorSpreadSpreadexample:
constadd=(a,b)=>a+b;letargs=[3,5];add(...args);//sameas`add(args[0],args[1])`,or`add.apply(null,args)`
Functionsaren'ttheonlyplaceinJavaScriptthatmakesuseofcommaseparatedlists-arrayscannowbeconcatenatedwithease:
letcde=['c','d','e'];letscale=['a','b',...cde,'f','g'];//['a','b','c','d','e','f','g']
Similarly,objectliteralscandothesamething:
letmapABC={a:5,b:6,c:3};letmapABCD={...mapABC,d:7};//{a:5,b:6,c:3,d:7}
OperatorRestRestargumentssharetheellipsislikesyntaxofrestoperatorsbutareusedforadifferentpurpose.Restargumentsareusedtoaccessavariablenumberofargumentspassedtoafunction.Forexample:
...spreadand...rest
33
-
functionaddSimple(a,b){returna+b;}
functionadd(...numbers){returnnumbers[0]+numbers[1];}
addSimple(3,2);//5add(3,2);//5
//orines6style:constaddEs6=(...numbers)=>numbers.reduce((p,c)=>p+c,0);
addEs6(1,2,3);//6
TechnicallyJavaScriptalreadyhadanargumentsvariablesetoneachfunction(exceptforarrowfunctions),howeverargumentshasalotofissues,oneofwhichisthefactthatitisnottechnicallyanarray.
Restargumentsareinfactarrays.Theotherimportantdifferenceisthatrestargumentsonlyincludeargumentsnotspecificallynamedinafunctionlikeso:
functionprint(a,b,c,...more){console.log(more[0]);console.log(arguments[0]);}
print(1,2,3,4,5);//4//1
...spreadand...rest
34
-
DestructuringDestructuringisawaytoquicklyextractdataoutofan{}or[]withouthavingtowritemuchcode.
ToborrowfromtheMDN,destructuringcanbeusedtoturnthefollowing:
letfoo=['one','two','three'];
letone=foo[0];lettwo=foo[1];letthree=foo[2];
into
letfoo=['one','two','three'];let[one,two,three]=foo;console.log(one);//'one'
Thisisprettyinteresting,butatfirstitmightbehardtoseetheusecase.ES6alsosupportsobjectdestructuring,whichmightmakeusesmoreobvious:
letmyModule={drawSquare:functiondrawSquare(length){/*implementation*/},drawCircle:functiondrawCircle(radius){/*implementation*/},drawText:functiondrawText(text){/*implementation*/},};
let{drawSquare,drawText}=myModule;
drawSquare(5);drawText('hello');
Destructuringcanalsobeusedforpassingobjectsintoafunction,allowingyoutopullspecificpropertiesoutofanobjectinaconcisemanner.Itisalsopossibletoassigndefaultvaluestodestructuredarguments,whichcanbeausefulpatternifpassinginaconfigurationobject.
Destructuring
35
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
-
letjane={firstName:'Jane',lastName:'Doe'};letjohn={firstName:'John',lastName:'Doe',middleName:'Smith'}functionsayName({firstName,lastName,middleName='N/A'}){console.log(`Hello${firstName}${middleName}${lastName}`)}
sayName(jane)//->HelloJaneN/ADoesayName(john)//->HeloJohnSmithDoe
Therearemanymoresophisticatedthingsthatcanbedonewithdestructuring,andtheMDNhassomegreatexamples,includingnestedobjectdestructuringanddynamicdestructuringwithfor...inoperators".
Destructuring
36
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
-
ES6ModulesES6introducedmodulesupport.AmoduleinES6issinglefilethatallowscodeanddatatobeisolated,ithelpsinorganizingandgroupingcodelogically.Inotherlanguagesit'scalledapackageorlibrary.
Allcodeanddatainsidethemodulehasfilescope,whatthismeansistheyarenotaccessiblefromcodeoutsidethemodule.Tosharecodeordataoutsideamodule,itneedstobeexportedusingtheexportkeyword.
//File:circle.js
exportconstpi=3.141592;
exportconstcircumference=diameter=>diameter*pi;
ThecodeaboveusestheArrowfunctionforcircumference,whichwasintroducedinES6,andisashortformforthefollowing.
exportfunctioncircumference(diameter){returndiameter*pi;}
ModuleSystemsUsingamoduleonthebackend(serverside)isrelativelystraightforward,yousimplymakeuseoftheimportkeyword.HoweverWebBrowsershavenoconceptofmodulesorimport,theyjustknowhowtoloadjavascriptcode.Weneedawaytobringinajavascriptmoduletostartusingitfromotherjavascriptcode.Thisiswhereamoduleloadercomesin.
Wewon'tgetintothevariousmodulesystemsoutthere,butit'sworthunderstandingtherearevariousmoduleloadersavailable.Thepopularchoicesoutthereare:
RequireJSSystemJSWebpack
LoadingaModuleFromaBrowser
Modules
37
-
BelowwemakeuseofSystemJStoloadamodule.ThescriptfirstloadsthecodefortheSystemJSlibrary,thenthefunctioncallSystem.importisusetoimport(load)theappmodule.
LoadingES6modulesisalittletrickier.InanES6-compliantbrowseryouusetheSystemkeywordtoloadmodulesasynchronously.Tomakeourcodeworkwithcurrentbrowsers,however,wewillusetheSystemJSlibraryasapolyfill:
varpromise=System.import('app').then(function(){console.log('Loaded!');}).then(null,function(error){console.error('Failedtoload:',error);});
Modules
38
-
TypeScriptES6isthecurrentversionofJavaScript.TypeScriptisasupersetofES6,whichmeansallES6featuresarepartofTypeScript,butnotallTypeScriptfeaturesarepartofES6.Consequently,TypeScriptmustbetranspiledintoES5toruninmostbrowsers.
OneofTypeScript'sprimaryfeaturesistheadditionoftypeinformation,hencethename.ThistypeinformationcanhelpmakeJavaScriptprogramsmorepredictableandeasiertoreasonabout.
Typesletdeveloperswritemoreexplicit"contracts".Inotherwords,thingslikefunctionsignaturesaremoreexplicit.
WithoutTS:
functionadd(a,b){returna+b;}
add(1,3);//4add(1,'3');//'13'
WithTS:
functionadd(a:number,b:number){returna+b;}
add(1,3);//4//compilererrorbeforeJSisevenproducedadd(1,'3');//'13'
TypeScript
39
-
GettingStartedWithTypeScriptInstalltheTypeScripttranspilerusingnpm:
$npminstall-gtypescript
ThenusetsctomanuallycompileaTypeScriptsourcefileintoES5:
$tsctest.ts$nodetest.js
NoteAboutES6Examples
OurearlierES6classwon'tcompilenow.TypeScriptismoredemandingthanES6anditexpectsinstancepropertiestobedeclared:
classPizza{toppings:string[];constructor(toppings:string[]){this.toppings=toppings;}}
Notethatnowthatwe'vedeclaredtoppingstobeanarrayofstrings,TypeScriptwillenforcethis.Ifwetrytoassignanumbertoit,wewillgetanerroratcompilationtime.
Ifyouwanttohaveapropertythatcanbesettoavalueofanytype,however,youcanstilldothis:justdeclareitstypetobe"any":
classPizza{toppings:any;//...}
GettingStartedWithTypeScript
40
-
WorkingWith tscSofartschasbeenusedtocompileasinglefile.Typicallyprogrammershavealotmorethanonefiletocompile.Thankfullytsccanhandlemultiplefilesasarguments.
Imaginetwoultrasimplefiles/modules:
a.ts
exportconstA=(a)=>console.log(a);
b.ts
exportconstB=(b)=>console.log(b);
$tsc./a.ts./b.tsa.ts(1,1):errorTS1148:Cannotcompilemodulesunlessthe'--module'flagisprovided.
Hmmm.What'sthedealwiththismoduleflag?TypeScripthasahelpmenu,let'stakealook:
$tsc--help|grepmodule-mKIND,--moduleKINDSpecifymodulecodegeneration:'commonjs','amd','system','umd'or'es2015'--moduleResolutionSpecifiesmoduleresolutionstrategy:'node'(Node.js)or'classic'(TypeScriptpre-1.6).
(TypeScripthasmorehelpthanwhatwe'veshown;wefilteredbygrepforbrevity.)Therearetwohelpentriesthatreference"module",and--moduleistheoneTypeScriptwascomplainingabout.ThedescriptionexplainsthatTypeScriptsupportsanumberofdifferentmoduleschemes.Forthemomentcommonjsisdesirable.Thiswillproducemodulesthatarecompatiblewithnode.js'smodulesystem.
$tsc-mcommonjs./a.ts./b.ts
[email protected],tschasadefaultrulefor--moduleoption:target==='ES6'?'ES6':'commonjs'(moredetailscanbefoundhere),sowecansimplyrun:
WorkingWithtsc
41
https://www.typescriptlang.org/docs/handbook/compiler-options.html
-
$tsc./a.ts./b.ts
tscshouldproducenooutput.Inmanycommandlinetraditions,nooutputisactuallyamarkofsuccess.ListingthedirectorycontentswillconfirmthatourTypeScriptfilesdidinfactcompile.
$lsa.jsa.tsb.jsb.ts
Excellent-therearenowtwoJavaScriptmodulesreadyforconsumption.
Tellingthetsccommandwhattocompilebecomestediousandlaborintensiveevenonsmallprojects.FortunatelyTypeScripthasameansofsimplifyingthis.tsconfig.jsonfilesletprogrammerswritedownallthecompilersettingstheywant.Whentscisrun,itlooksfortsconfig.jsonfilesandusestheirrulestocompileJavaScript.
ForAngular2projectsthereareanumberofspecificsettingsthatneedtobeconfiguredinaproject'stsconfig.json
{"compilerOptions":{"module":"commonjs","target":"es5","emitDecoratorMetadata":true,"experimentalDecorators":true,"noImplicitAny":false,"removeComments":false,"sourceMap":true},"exclude":["node_modules","dist/"]}
Target
Thecompilationtarget.TypeScriptsupportstargetingdifferentplatformsdependingonyourneeds.Inourcase,we'retargetingmodernbrowserswhichsupportES5.
Module
WorkingWithtsc
42
-
Thetargetmoduleresolutioninterface.We'reintegratingTypeScriptthroughwebpackwhichsupportsdifferentinterfaces.We'vedecidedtousenode'smoduleresolutioninterface,commonjs.
Decorators
DecoratorsupportinTypeScripthasn'tbeenfinalizedyetbutsinceAngular2usesdecoratorsextensively,theseneedtobesettotrue.Decoratorshavenotbeenintroducedyet,andwillbecoveredlaterinthissection.
TypeScriptwithWebpack
Wewon'tberunningtscmanually,however.Instead,webpack'sts-loaderwilldothetranspilationduringthebuild:
//webpack.config.js//...rules:[{test:/\.ts$/,loader:'ts',exclude:/node_modules/},//...]
Thisloadercallstscforus,anditwilluseourtsconfig.json.
WorkingWithtsc
43
http://rbuckton.github.io/ReflectDecorators/typescript.html
-
TypingsAstutereadersmightbewonderingwhathappenswhenTypeScriptprogrammersneedtointerfacewithJavaScriptmodulesthathavenotypeinformation.TypeScriptrecognizesfileslabelled*.d.tsasdefinitionfiles.ThesefilesaremeanttouseTypeScripttodescribeinterfacespresentedbyJavaScriptlibraries.
TherearecommunitiesofpeoplededicatedtocreatingtypingsforJavaScriptprojects.Thereisalsoautilitycalledtypings(npminstall--save-devtypings)thatcanbeusedtomanagethirdpartytypingsfromavarietyofsources.(DeprecatedinTypeScript2.0)
InTypeScript2.0,userscangettypefilesdirectlyfrom@typesthroughnpm(forexample,npminstall--save@types/lodashwillinstalllodashtypefile).
Typings
44
-
LintingManyeditorssupporttheconceptof"linting"-agrammarcheckforcomputerprograms.Lintingcanbedoneinaprogrammer'seditorand/orthroughautomation.
ForTypeScriptthereisapackagecalledtslint,(npminstall--save-devtslint)whichcanbepluggedintomanyeditors.tslintcanalsobeconfiguredwithatslint.jsonfile.
Webpackcanruntslintbeforeitattemptstoruntsc.Thisisdonebyinstallingtslint-loader(npminstall--save-devtslint-loader)whichplugsintowebpacklikeso:
//...module:{preLoaders:[{test:/\.ts$/,loader:'tslint'}],loaders:[{test:/\.ts$/,loader:'ts',exclude:/node_modules/},//...]//...}
Linting
45
-
TypeScriptFeaturesNowthatproducingJavaScriptfromTypeScriptcodehasbeende-mystified,someofitsfeaturescanbedescribedandexperimentedwith.
TypesInterfacesShapesDecorators
TypesManypeopledonotrealizeit,butJavaScriptdoesinfacthavetypes,they'rejust"ducktyped",whichroughlymeansthattheprogrammerdoesnothavetothinkaboutthem.JavaScript'stypesalsoexistinTypeScript:
boolean(true/false)numberintegers,floats,InfinityandNaNstringcharactersandstringsofcharacters[]Arraysofothertypes,likenumber[]orboolean[]{}Objectliteralundefinednotset
TypeScriptalsoadds
enumenumerationslike{Red,Blue,Green}anyuseanytypevoidnothing
Primitivetypeexample:
TypeScriptFeatures
46
-
letisDone:boolean=false;letheight:number=6;letname:string="bob";letlist:number[]=[1,2,3];letlist:Array=[1,2,3];enumColor{Red,Green,Blue};letc:Color=Color.Green;letnotSure:any=4;notSure="maybeastringinstead";notSure=false;//okay,definitelyaboolean
functionshowMessage(data:string):void{alert(data);}showMessage('hello');
ThisillustratestheprimitivetypesinTypeScript,andendsbyillustratingashowMessagefunction.Inthisfunctiontheparametershavespecifictypesthatarecheckedwhentscisrun.
InmanyJavaScriptfunctionsit'squitecommonforfunctionstotakeoptionalparameters.TypeScriptprovidessupportforthis,likeso:
functionlogMessage(message:string,isDebug?:boolean){if(isDebug){console.log('Debug:'+message);}else{console.log(message);}}logMessage('hi');//'hi'logMessage('test',true);//'Debug:test'
Usinga?letstscknowthatisDebugisanoptionalparameter.tscwillnotcomplainifisDebugisomitted.
TypeScriptFeatures
47
-
TypeScriptClassesTypeScriptalsotreatsclassesastheirowntype:
classFoo{foo:number;}classBar{bar:string;}
classBaz{constructor(foo:Foo,bar:Bar){}}
letbaz=newBaz(newFoo(),newBar());//validbaz=newBaz(newBar(),newFoo());//tscerrors
Likefunctionparameters,classessometimeshaveoptionalmembers.Thesame?:syntaxcanbeusedonaclassdefinition:
classPerson{name:string;nickName?:string;}
Intheaboveexample,aninstanceofPersonisguaranteedtohaveaname,andmightoptionallyhaveanickName
TypeScriptClasses
48
-
InterfacesAninterfaceisaTypeScriptartifact,itisnotpartofECMAScript.Aninterfaceisawaytodefineacontractonafunctionwithrespecttotheargumentsandtheirtype.Alongwithfunctions,aninterfacecanalsobeusedwithaClassaswelltodefinecustomtypes.
Aninterfaceisanabstracttype,itdoesnotcontainanycodeasaclassdoes.Itonlydefinesthe'signature'orshapeofanAPI.Duringtranspilation,aninterfacewillnotgenerateanycode,itisonlyusedbyTypescriptfortypecheckingduringdevelopment.
HereisanexampleofaninterfacedescribingafunctionAPI:
interfaceCallback{(error:Error,data:any):void;}
functioncallServer(callback:Callback){callback(null,'hi');}
callServer((error,data)=>console.log(data));//'hi'callServer('hi');//tscerror
SometimesJavaScriptfunctionscanacceptmultipletypesaswellasvaryingarguments,thatis,theycanhavedifferentcallsignatures.Interfacescanbeusedtospecifythis.
interfacePrintOutput{(message:string):void;//commoncase(message:string[]):void;//lesscommoncase}
letprintOut:PrintOutput=(message)=>{if(Array.isArray(message)){console.log(message.join(','));}else{console.log(message);}}
printOut('hello');//'hello'printOut(['hi','bye']);//'hi,bye'
Hereisanexampleofaninterfacedescribinganobjectliteral:
Interfaces
49
-
interfaceAction{type:string;}
leta:Action={type:'literal'}
Interfaces
50
-
ShapesUnderneathTypeScriptisJavaScript,andunderneathJavaScriptistypicallyaJIT(Just-In-Timecompiler).GivenJavaScript'sunderlyingsemantics,typesaretypicallyreasonedaboutby"shapes".TheseunderlyingshapesworklikeTypeScript'sinterfaces,andareinfacthowTypeScriptcomparescustomtypeslikeclassesandinterfaces.
Consideranexpansionofthepreviousexample:
interfaceAction{type:string;}
leta:Action={type:'literal'}
classNotAnAction{type:string;constructor(){this.type='Constructorfunction(class)';}}
a=newNotAnAction();//validTypeScript!
DespitethefactthatActionandNotAnActionhavedifferentidentifiers,tscletsusassignaninstanceofNotAnActiontoawhichhasatypeofAction.ThisisbecauseTypeScriptonlyreallycaresthatobjectshavethesameshape.Inotherwordsiftwoobjectshavethesameattributes,withthesametypings,thosetwoobjectsareconsideredtobeofthesametype.
Shapes
51
-
TypeInferenceOnecommonmisconceptionaboutTypeScript'stypesisthatcodeneedstoexplicitlydescribetypesateverypossibleopportunity.Fortunatelythisisnotthecase.TypeScripthasarichtypeinferencesystemthatwill"fillintheblanks"fortheprogrammer.Considerthefollowing:
type-inference-finds-error.ts
letnumbers=[2,3,5,7,11];numbers=['thiswillgenerateatypeerror'];
tsc./type-inference-finds-error.tstype-inference-finds-error.ts(2,1):errorTS2322:Type'string[]'isnotassignabletotype'number[]'.Type'string'isnotassignabletotype'number'.
Thecodecontainsnoextratypeinformation.Infact,it'svalidES6.Ifvarhadbeenused,itwouldbevalidES5.YetTypeScriptisstillabletodeterminetypeinformation.
Typeinferencecanalsoworkthroughcontext,whichishandywithcallbacks.Considerthefollowing:
type-inference-finds-error-2.ts
interfaceFakeEvent{type:string;}
interfaceFakeEventHandler{(e:FakeEvent):void;}
classFakeWindow{onMouseDown:FakeEventHandler}constfakeWindow=newFakeWindow();
fakeWindow.onMouseDown=(a:number)=>{//thiswillfail};
TypeInference
52
-
tsc./type-inference-finds-error-2.tstype-inference-finds-error-2.ts(14,1):errorTS2322:Type'(a:number)=>void'isnotassignabletotype'FakeEventHandler'.Typesofparameters'a'and'e'areincompatible.Type'number'isnotassignabletotype'FakeEvent'.Property'type'ismissingintype'Number'.
Inthisexamplethecontextisnotobvioussincetheinterfaceshavebeendefinedexplicitly.Inabrowserenvironmentwitharealwindowobject,thiswouldbeahandyfeature,especiallythetypecompletionoftheEventobject.
TypeInference
53
-
TypeKeywordThetypekeyworddefinesanaliastoatype.
typestr=string;letcheese:str='gorgonzola';letcake:str=10;//Type'number'isnotassignabletotype'string'
Atfirstglance,thisdoesnotappeartobeveryuseful(eventheerrormentionstheoriginaltype),butastypeannotationsbecomemorecomplex,thebenefitsofthetypekeywordbecomeapparent.
UnionTypes
Uniontypesallowtypeannotationstospecifythatapropertyshouldbeoneofasetoftypes(either/or).
functionadmitAge(age:number|string):string{return`Iam${age},alright?!`;}
admitAge(30);//'Iam30,alright?!'admitAge('Forty');//'IamForty,alright?!'
Thetypekeywordsimplifiesannotatingandreusinguniontypes.
typeAge=number|string;
functionadmitAge(age:Age):string{return`Iam${age},alright?!`;}
letmyAge:Age=50;letyourAge:Age='OneHundred';admitAge(yourAge);//'IamOneHundred,alright?!'
Auniontypeofstringliteraltypesisaveryusefulpattern,creatingwhatisbasicallyanenumwithstringvalues.
TypeKeyword
54
-
typePartyZone="pizzahut"|"waterpark"|"bowlingalley"|"abandonedwarehouse";
functiongoToParty(place:PartyZone):string{return`letsgotothe${place}`;}
goToParty("pizzahut");goToParty("chucke.cheese");//Argumentoftype`"chucke.cheese"'isnotassignabletoparameteroftype'PartyZone'
IntersectionTypes
Intersectiontypesarethecombinationoftwoormoretypes.Usefulforobjectsandparamsthatneedtoimplementmorethanoneinterface.
interfaceKicker{kick(speed:number):number;}
interfacePuncher{punch(power:number):number;}//assignintersectiontypedefinitiontoaliasKickPunchertypeKickPuncher=Kicker&Puncher;
functionattack(warrior:KickPuncher){warrior.kick(102);warrior.punch(412);warrior.judoChop();//Property'judoChop'doesnotexistontype'KickPuncher'}
FunctionTypeDefinitions
Functiontypeannotationscangetmuchmorespecificthantypescriptsbuilt-inFunctiontype.Functiontypedefinitionsallowyoutoattachafunctionsignaturetoit'sowntype.
typeMaybeError=Error|null;typeCallback=(err:MaybeError,response:Object)=>void;
functionsendRequest(cb:Callback):void{if(cb){cb(null,{});}}
ThesyntaxissimilartoES6fat-arrowfunctions.([params])=>[returntype].
TypeKeyword
55
-
Toillustratethehowmuchthetypekeywordimprovedthereadabilityoftheprevioussnippet,hereisthefunctiontypedefinedinline.
functionsendRequest(cb:(err:Error|null,response:Object)=>void):void{if(cb){cb(null,{});}}
TypeKeyword
56
-
DecoratorsDecoratorsareproposedforafutureversionofJavaScript,buttheAngular2teamreallywantedtousethem,andtheyhavebeenincludedinTypeScript.
Decoratorsarefunctionsthatareinvokedwithaprefixed@symbol,andimmediatelyfollowedbyaclass,parameter,methodorproperty.Thedecoratorfunctionissuppliedinformationabouttheclass,parameterormethod,andthedecoratorfunctionreturnssomethinginitsplace,ormanipulatesitstargetinsomeway.Typicallythe"something"adecoratorreturnsisthesamethingthatwaspassedin,butithasbeenaugmentedinsomeway.
DecoratorsarequitenewinTypeScript,andmostusecasesdemonstratetheuseofexistingdecorators.However,decoratorsarejustfunctions,andareeasiertoreasonaboutafterwalkingthroughafewexamples.
Decoratorsarefunctions,andtherearefourthings(class,parameter,methodandproperty)thatcanbedecorated;consequentlytherearefourdifferentfunctionsignaturesfordecorators:
class:declaretypeClassDecorator=(target:TFunction)=>TFunction|void;
property:declaretypePropertyDecorator=(target:Object,propertyKey:string|symbol)=>void;
method:declaretypeMethodDecorator=(target:Object,propertyKey:string|symbol,descriptor:TypedPropertyDescriptor)=>TypedPropertyDescriptor|void;
parameter:declaretypeParameterDecorator=(target:Object,propertyKey:string|symbol,parameterIndex:number)=>void;
ReaderswhohaveplayedwithAngular2willnoticethatthesesignaturesdonotlooklikethesignaturesusedbyAngular2specificdecoratorslike@Component().
Noticethe()[email protected]@ComponentiscalledonceJavaScriptencounters@Component().Inturn,thismeansthattheremustbeaComponentfunctionsomewherethatreturnsafunctionmatchingoneofthedecoratorsignaturesoutlinedabove.Thisisanexampleofthedecoratorfactorypattern.
Ifdecoratorsstilllookconfusing,perhapssomeexampleswillclearthingsup.
Decorators
57
-
PropertyDecoratorsPropertydecoratorsworkwithpropertiesofclasses.
functionOverride(label:string){returnfunction(target:any,key:string){Object.defineProperty(target,key,{configurable:false,get:()=>label});}}
classTest{@Override('test')//invokesOverride,whichreturnsthedecoratorname:string='pat';}
lett=newTest();console.log(t.name);//'test'
Theaboveexamplemustbecompiledwithboththe--experimentalDecoratorsand--emitDecoratorMetadataflags.
Inthiscasethedecoratedpropertyisreplacedbythelabelpassedtothedecorator.It'simportanttonotethatpropertyvaluescannotbedirectlymanipulatedbythedecorator;insteadanaccessorisused.
Here'saclassicpropertyexamplethatusesaplaindecorator
functionReadOnly(target:any,key:string){Object.defineProperty(target,key,{writable:false});}
classTest{@ReadOnly//noticethereareno`()`name:string;}
constt=newTest();t.name='jan';console.log(t.name);//'undefined'
Inthiscasethenamepropertyisnotwritable,andremainsundefined.
PropertyDecorators
58
-
PropertyDecorators
59
-
ClassDecorators
functionlog(prefix?:string){return(target)=>{//saveareferencetotheoriginalconstructorvaroriginal=target;
//autilityfunctiontogenerateinstancesofaclassfunctionconstruct(constructor,args){varc:any=function(){returnconstructor.apply(this,args);}c.prototype=constructor.prototype;returnnewc();}
//thenewconstructorbehaviorvarf:any=function(...args){console.log(prefix+original.name);returnconstruct(original,args);}
//copyprototypesoinstanceofoperatorstillworksf.prototype=original.prototype;
//returnnewconstructor(willoverrideoriginal)returnf;};}
@log('hello')classWorld{}
constw=newWorld();//outputs"helloWorld"
Intheexamplelogisinvokedusing@,andpassedastringasaparameter,@log()returnsananonymousfunctionthatistheactualdecorator.
Thedecoratorfunctiontakesaclass,orconstructorfunction(ES5)asanargument.ThedecoratorfunctionthenreturnsanewclassconstructionfunctionthatisusedwheneverWorldisinstantiated.
Thisdecoratordoesnothingotherthanlogoutitsgivenparameter,anditstarget'sclassnametotheconsole.
ClassDecorators
60
-
ClassDecorators
61
-
ParameterDecorators
functionlogPosition(target:any,propertyKey:string,parameterIndex:number){console.log(parameterIndex);}
classCow{say(b:string,@logPositionc:boolean){console.log(b);}}
newCow().say('hello',false);//outputs1(newline)hello
Theabovedemonstratesdecoratingmethodparameters.ReadersfamiliarwithAngular2cannowimaginehowAngular2implementedtheir@Inject()system.
ParameterDecorators
62
-
TheJavaScriptToolchainInthissection,we'lldescribethetoolsthatyou'llbeusingfortherestofthecourse.
Figure:HandToolsbyM338islicensedunderPublicDomain(http://commons.wikimedia.org/wiki/File:Hand_tools.jpg)
TheJavaScriptToolchain
63
-
SourceControl:GitAsourcecontrol,sometimescalledaversioncontrolbringschangemanagementtosavingfilesatdifferentpointsinthedevelopmentprocess.AVersioncontrolsystem(VCS)thatwillwemakeuseofisGit.
Gitisadecentralizeddistributedversioningsystem,itallowsprogrammerstocollaborateonthesamecodebasewithoutsteppingoneachother'stoes.Ithasbecomethede-factosourcecontrolsystemforopensourcedevelopmentbecauseofitsdecentralizedmodelandcheapbranchingfeatures.
FormoreinformationonhowtouseGit,headovertoProGit
SourceControl:git
64
http://git-scm.com/https://www.gitbook.com/book/gitbookio/progit/details
-
TheCommandLineJavaScriptdevelopmenttoolsareverycommandlineoriented.IfyoucomefromaWindowsbackgroundyoumayfindthisunfamiliar.Howeverthecommandlineprovidesbettersupportforautomatingdevelopmenttasks,soit'sworthgettingcomfortablewithit.
Wewillprovideexamplesforallcommandlineactivitiesrequiredbythiscourse.
TheCommandLine
65
-
CommandLineJavaScript:NodeJSNode.jsisaJavaScriptruntimeenvironmentthatallowsJavaScriptcodetorunoutsideofabrowserusingGoogleV8JavaScriptengine.Node.jsisusedforwrittingfastexecutingcodeontheservertohandleeventsandnon-blockingI/Oefficently.
REPL(Read-Eval-Print-Loop)toquicklywriteandtestJavaScriptcode.TheV8JavaScriptinterpreter.ModulesfordoingOStaskslikefileI/O,HTTP,etc.
WhileNode.jswasinitiallyintendedforwritingservercodeinJavaScript,todayitiswidelyusedbyJavaScripttools,whichmakesitrelevanttofront-endprogrammerstoo.Alotofthetoolsyou'llbeusinginthiscourseleverageNode.js.
CommandLineJavaScript:NodeJS
66
http://nodejs.org
-
Back-EndCodeSharingandDistribution:npmnpmisthe"nodepackagemanager".ItinstallswithNodeJS,andgivesyouaccesstoawidevarietyof3rd-partyJavaScriptmodules.
Italsoperformsdependencymanagementforyourback-endapplication.Youspecifymoduledependenciesinafilecalledpackage.json;runningnpminstallwillresolve,downloadandinstallyourback-endapplication'sdependencies.
Back-EndCodeSharingandDistribution:npm
67
https://www.npmjs.com/
-
ModuleLoading,BundlingandBuildTasks:WebpackWebpackisaJavaScriptmodulebundler.Ittakesmoduleswiththeirdependenciesandgeneratesstaticassetsrepresentingthosemodules.WebpackknownonlyhowtobundleJavaScript.TobundleotherassetslikesCSS,HTML,imagesorjustaboutanythingitusesadditionalloaders.Webpackcanalsobeextendedviaplugins,forexampleminificationandmanglingcanbedoneusingtheUglifyJSpluginforwebpack.
ModuleLoading,BundlingandBuildTasks:Webpack
68
http://webpack.github.io/docs/what-is-webpack.html
-
WebBrowsersWeuseGoogle'sChromebrowserforthiscoursebecauseofitscutting-edgeJavaScriptengineandexcellentdebuggingtools.
Howeveryouarefreetouseotherbrowsers.Notwellknown,thereisaMozillaFirefoxDeveloperEditionavailablewithsupportforgreatdevelopmentanddebuggingtools.CodewrittenwithJavaScriptshouldworkonanymodernwebbrowser(Firefox,IE9+,Chrome,Safari,Opera).
Chrome
69
https://www.mozilla.org/en-US/firefox/developer/
-
BootstrappinganAngular2ApplicationBootstrappingisanessentialprocessinAngular-itiswheretheapplicationisloadedwhenAngularcomestolife.
BootstrappingAngular2applicationsiscertainlydifferentfromAngular1.x,butisstillastraightforwardprocedure.Let'stakealookathowthisisdone.
BootstrappinganAngular2Application
70
-
UnderstandingtheFileStructureTogetstartedlet'screateabare-bonesAngular2applicationwithasinglecomponent.Todothisweneedthefollowingfiles:
app/app.component.ts-thisiswherewedefineourrootcomponentapp/app.module.ts-theentryAngularModuletobebootstrappedindex.html-thisisthepagethecomponentwillberenderedinapp/main.ts-isthegluethatcombinesthecomponentandpagetogether
app/app.component.ts
import{Component}from'@angular/core'
@Component({selector:'app-root',template:'BootstrappinganAngular2Application'})exportclassAppComponent{}
index.html
Loading...
app/app.module.ts
import{BrowserModule}from'@angular/platform-browser';import{NgModule}'@angular/core';import{AppComponent}from'./app.component'
@NgModule({imports:[BrowserModule],declarations:[AppComponent],bootstrap:[AppComponent]})exportclassAppModule{}
app/main.ts
UnderstandingtheFileStructure
71
-
import{platformBrowserDynamic}from'@angular/platform-browser-dynamic';import{AppModule}from'./app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
Ifyou'remakinguseofAhead-of-Time(AoT)compilation,youwouldcodemain.tsasfollows.
import{platformBrowser}from'@angular/platform-browser';import{AppModuleNgFactory}from'../aot/app/app.module.ngfactory';
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
ViewExample
Thebootstrapprocessloadsmain.tswhichisthemainentrypointoftheapplication.TheAppModuleoperatesastherootmoduleofourapplication.ThemoduleisconfiguredtouseAppComponentasthecomponenttobootstrap,andwillberenderedonanyapp-rootHTMLelementencountered.
ThereisanappHTMLelementintheindex.htmlfile,andweuseapp/main.tstoimporttheAppModulecomponentandtheplatformBrowserDynamic().bootstrapModulefunctionandkickstarttheprocess.Asshownabove,youmayoptionallyuseAoTinwhichcaseyouwillbeworkingwithFactories,intheexample,AppModuleNgFactoryandbootstrapModuleFactory.
WhydoesAngular2bootstrapitselfinthisway?Wellthereisactuallyaverygoodreason.SinceAngular2isnotaweb-onlybasedframework,wecanwritecomponentsthatwillruninNativeScript,orCordova,oranyotherenvironmentthatcanhostAngular2applications.
Themagicistheninourbootstrappingprocess-wecanimportwhichplatformwewouldliketouse,dependingontheenvironmentwe'reoperatingunder.Inourexample,sincewewererunningourAngular2applicationinthebrowser,weusedthebootstrappingprocessfoundin@angular/platform-browser-dynamic.
It'salsoagoodideatoleavethebootstrappingprocessinitsownseparatemain.tsfile.Thismakesiteasiertotest(sincethecomponentsareisolatedfromthebootstrapcall),easiertoreuseandgivesbetterorganizationandstructuretoourapplication.
ThereismoretounderstandingAngularModulesand@NgModulewhichwillbecoveredlater,butfornowthisisenoughtogetstarted.
UnderstandingtheFileStructure
72
https://plnkr.co/edit/X0EBXA?p=preview
-
UnderstandingtheFileStructure
73
-
BootstrappingProvidersThebootstrapprocessalsostartsthedependencyinjectionsysteminAngular2.Wewon'tgooverAngular2'sdependencyinjectionsystemhere-thatiscoveredlater.Insteadlet'stakealookatanexampleofhowtobootstrapyourapplicationwithapplication-wideproviders.
Forthis,wewillregisteraservicecalledGreeterServicewiththeproviderspropertyofthemoduleweareusingtobootstraptheapplication.
app/app.module.ts
import{BrowserModule}from'@angular/platform-browser';import{NgModule}'@angular/core';import{AppComponent}from'./app.component'import{GreeterService}from'./greeter.service';
@NgModule({imports:[BrowserModule],providers:[GreeterService],declarations:[AppComponent],bootstrap:[AppComponent]})exportclassAppModule{}
ViewExample
BootstrappingProviders
74
https://plnkr.co/edit/bcpliM?p=preview
-
ComponentsinAngular2
Figure:components
ThecoreconceptofanyAngular2applicationisthecomponent.Ineffect,thewholeapplicationcanbemodeledasatreeofthesecomponents.
ThisishowtheAngular2teamdefinesacomponent:
Acomponentcontrolsapatchofscreenrealestatethatwecouldcallaview,anddeclaresreusableUIbuildingblocksforanapplication.
Basically,acomponentisanythingthatisvisibletotheenduserandwhichcanbereusedmanytimeswithinanapplication.
InAngular1.xwehadrouterviewsanddirectiveswhichworkedsortoflikecomponents.Theideaofdirectivecomponentsbecamequitepopular.TheywerecreatedbyusingdirectivewithacontrollerwhilerelyingonthecontrollerAsandbindToControllerproperties.Forexample:
ComponentsinAngular2
75
-
angular.module('ngcourse').directive('ngcHelloComponent',()=>({restrict:'E',scope:{name:'='},template:'Hello,{{ctrl.name}}.',controller:MyComponentCtrl,controllerAs:'ctrl',bindToController:true}));
Infact,thisconceptbecamesopopularthatinAngular1.5the.componentmethodwasintroducedassyntacticsugar.
angular.module('ngcourse').component('ngcHelloComponent',{bindings:{name:'='},template:'Hello,{{$ctrl.name}}.',controller:MyComponentCtrl});
ComponentsinAngular2
76
-
CreatingComponentsComponentsinAngular2builduponthelessonslearnedfromAngular1.5.Wedefineacomponent'sapplicationlogicinsideaclass.Tothisweattach@Component,aTypeScriptdecorator,whichallowsyoutomodifyaclassorfunctiondefinitionandaddsmetadatatopropertiesandfunctionarguments.
selectoristheelementpropertythatweusetotellAngulartocreateandinsertaninstanceofthiscomponent.templateisaformofHTMLthattellsAngularwhatneedstobetorenderedintheDOM.
TheComponentbelowwillinterpolatethevalueofnamevariableintothetemplatebetweenthedoublebraces{{name}},whatgetrenderedintheviewis
HelloWorld
.
import{Component}from'@angular/core';
@Component({selector:'rio-hello',template:'
Hello,{{name}}!
',})exportclassHelloComponent{name:string;
constructor(){this.name='World';}}
WeneedtoimporttheComponentdecaratorfrom@angular/corebeforewecanmakeuseofit.TousethiscomponentwesimplyaddtotheHTMLfileoranothertemplate,andAngularwillinsertaninstanceoftheHelloComponentviewbetweenthosetags.
ViewExample
CreatingComponents
77
http://plnkr.co/edit/bXrxWVkP2MWD8yNDYqVD?p=preview
-
ApplicationStructurewithComponentsAusefulwayofconceptualizingAngularapplicationdesignistolookatitasatreeofnestedcomponents,eachhavinganisolatedscope.
Forexampleconsiderthefollowing:
Attherootwehaverio-todo-appwhichconsistsofario-todo-listandario-todo-form.Withinthelistwehaveseveralrio-todo-items.Eachofthesecomponentsisvisibletotheuser,whocaninteractwiththesecomponentsandperformactions.
ApplicationStructurewithComponents
78
-
PassingDataintoaComponentTherearetwowaystopassdataintoacomponent,with'propertybinding'and'eventbinding'.InAngular2,dataandeventchangedetectionhappenstop-downfromparenttochildren.HoweverforAngular2eventswecanusetheDOMeventmentalmodelwhereeventsflowbottom-upfromchildtoparent.So,Angular2eventscanbetreatedlikeregularHTMLDOMbasedeventswhenitcomestocancellableeventpropagation.
The@Input()decaratordefinesasetofparametersthatcanbepasseddownfromthecomponent'sparent.Forexample,wecanmodifytheHelloComponentcomponentsothatnamecanbeprovidedbytheparent.
import{Component,Input}from'@angular/core';
@Component({selector:'rio-hello',template:'
Hello,{{name}}!
',})exportclassHelloComponent{@Input()name:string;}
Thepointofmakingcomponentsisnotonlyencapsulation,butalsoreusability.Inputsallowustoconfigureaparticularinstanceofacomponent.
Wecannowuseourcomponentlikeso:
ViewExample
UnlikeAngular1.x,thisisone-waybinding.
PassingDataintoaComponent
79
http://plnkr.co/edit/LEtEN9?p=preview
-
RespondingtoComponentEventsAneventhandlerisspecifiedinsidethetemplateusingroundbracketstodenoteeventbinding.Thiseventhandleristhencodedintheclasstoprocesstheevent.
import{Component}from'@angular/core';
@Component({selector:'rio-counter',template:`
Count:{{num}}
Increment`})exportclassCounterComponent{num=0;
increment(){this.num++;}}
ViewExample
Tosenddataoutofcomponentsviaoutputs,startbydefiningtheoutputsattribute.Itacceptsalistofoutputparametersthatacomponentexposestoitsparent.
app/counter.component.ts
import{Component,EventEmitter,Input,Output}from'@angular/core';
@Component({selector:'rio-counter',templateUrl:'app/counter.component.html'})exportclassCounterComponent{@Input()count=0;@Output()result=newEventEmitter();
increment(){this.count++;this.result.emit(this.count);}}
RespondingtoComponentEvents
80
http://plnkr.co/edit/l4FweMxodN8I26OeqhGH?p=preview
-
app/counter.component.html
Count:{{count}}
Increment
app/app.component.ts
import{Component,OnChange}from'@angular/core';
@Component({selector:'rio-app',templateUrl:'app/app.component.html'})exportclassAppComponentimplementsOnChange{num=0;parentCount=0;
ngOnChange(val:number){this.parentCount=val;}}
app/app.component.html
ParentNum:{{num}}
ParentCount:{{parentCount}}ViewExample
Togetherasetofinput+outputbindingsdefinethepublicAPIofyourcomponent.Inourtemplatesweusethe[squareBrackets]topassinputsandthe(parenthesis)tohandleoutputs.
RespondingtoComponentEvents
81
http://plnkr.co/edit/5RYLZ0?p=preview
-
UsingTwo-WayDataBindingTwo-waydatabindingcombinestheinputandoutputbindingintoasinglenotationusingthengModeldirective.
Whatthisisdoingbehindthescenesisequivalentto:
Tocreateyourowncomponentthatsupportstwo-waybinding,youmustdefinean@Outputpropertytomatchan@Input,butsuffixitwiththeChange.Thecodeexamplebelow,insideclassCounterComponentshowshowtomakepropertycountsupporttwo-waybinding.
app/counter.component.ts
import{Component,Input,Output,EventEmitter}from'@angular/core';
@Component({selector:'rio-counter',templateUrl:'app/counter.component.html'})exportclassCounterComponent{@Input()count=0;@Output()countChange=EventEmitter();
increment(){this.count++;this.countChange.emit(this.count);}}
app/counter.component.html
Count:{{count}}-Increment
UsingTwo-WayDataBinding
82
-
ViewExample
UsingTwo-WayDataBinding
83
http://plnkr.co/edit/nkww1Ov2AWZRMHFyjhjl?p=preview
-
AccessChildComponentsFromtheTemplateInourtemplates,wemayfindourselvesneedingtoaccessvaluesprovidedbythechildcomponentswhichweusetobuildourowncomponent.
Themoststraightforwardexamplesofthismaybeseendealingwithformsorinputs:
app/app.component.html
NameSubmitFormValue:{{formValue}}
app/app.component.ts
import{Component}from'@angular/core';
@Component({selector:'rio-app',templateUrl:'app/app.component.html'})exportclassAppComponent{formValue=JSON.stringify({});
onSubmit(form:NgForm){this.formValue=JSON.stringify(form.value);}}
ViewExample
Thisisn'tamagicfeaturewhichonlyformsorinputshave,butratherawayofreferencingtheinstanceofachildcomponentinyourtemplate.Withthatreference,youcanthenaccesspublicpropertiesandmethodsonthatcomponent.
app/app.component.html
AccessingChildComponentsfromTemplate
84
https://plnkr.co/edit/hfv5RC?p=preview
-
Mynameis{{profile.name}}
app/profile.component.ts
@Component({selector:'rio-profile',templateUrl:'app/profile.component.html'})exportclassProfileComponent{name='JohnDoe';}
ViewExample
Thereareothermeansofaccessingandinterfacingwithchildcomponents,butifyousimplyneedtoreferencepropertiesormethodsofachild,thiscanbeasimpleandstraightforwardmethodofdoingso.
AccessingChildComponentsfromTemplate
85
https://plnkr.co/edit/wEFOta?p=preview
-
ProjectionProjectionisaveryimportantconceptinAngular2.Itenablesdeveloperstobuildreusablecomponentsandmakeapplicationsmorescalableandflexible.Toillustratethat,supposewehaveaChildComponentlike:
@Component({selector:'rio-child',template:`ChildComponent{{childContent}}`})exportclassChildComponent{childContent="Defaultcontent";}
Whatshouldwedoifwewanttoreplace{{childContent}}toanyHTMLthatprovidedtoChildComponent?Onetemptingideaistodefinean@Inputcontainingthetext,butwhatifyouwantedtoprovidestyledHTML,orothercomponents?Tryingtohandlethiswithan@Inputcangetmessyquickly,andthisiswherecontentprojectioncomesin.Componentsbydefaultsupportprojection,andyoucanusethengContentdirectivetoplacetheprojectedcontentinyourtemplate.
So,changeChildComponenttouseprojection:
app/child/child.component.ts
import{Component}from'@angular/core';
@Component({selector:'rio-child',template:`ChildComponent`})exportclassChildComponent{}
Then,whenweuseChildComponentinthetemplate:
Projection
86
-
app/app.component.html
...
Myprojectedcontent.
...
ThisistellingAngular,thatforanymarkupthatappearsbetweentheopeningandclosingtagof,toplaceinsideof.
Whendoingthis,wecanhaveothercomponents,markup,etcprojectedhereandtheChildComponentdoesnotneedtoknowaboutorcarewhatisbeingprovided.
ViewExample
Butwhatifwehavemultipleandwanttospecifythepositionoftheprojectedcontenttocertainng-content?Forexample,forthepreviousChildComponent,ifwewanttoformattheprojectedcontentintoanextraheaderandfootersection:
app/child-select.component.html
ChildComponentwithSelect
Theninthetemplate,wecanusedirectives,say,tospecifythepositionofprojectedcontenttotheng-contentwithselect="header":
app/app.component.html
Projection
87
http://plnkr.co/edit/QAQ6BFuwuzEDVvqAmN9L?p=preview
-
...
SectionContentdivwith.class-selectFooterContentHeaderContent
...
Besidesusingdirectives,developerscanalsoselectang-contentthroughcssclass:
app/app.component.html
divwith.class-select
ViewExample
Projection
88
http://plnkr.co/edit/rH2vGgFluLXHCsgfkNjF?p=preview
-
StructuringApplicationswithComponentsAsthecomplexityandsizeofourapplicationgrows,wewanttodivideresponsibilitiesamongourcomponentsfurther.
Smart/Containercomponentsareapplication-specific,higher-level,containercomponents,withaccesstotheapplication'sdomainmodel.
Dumb/PresentationalcomponentsarecomponentsresponsibleforUIrenderingand/orbehaviorofspecificentitiespassedinviacomponentsAPI(i.ecomponentpropertiesandevents).Thosecomponentsaremorein-linewiththeupcomingWebComponentstandards.
StructuringApplicationswithComponents
89
-
UsingOtherComponentsComponentsdependonothercomponents,directivesandpipes.Forexample,TodoListComponentreliesonTodoItemComponent.Toletacomponentknowaboutthesedependencieswegroupthemintoamodule.
import{NgModule}from'@angular/core';
import{TodoListComponent}from'./components/todo-list.component';import{TodoItemComponent}from'./components/todo-item.component';import{TodoInputComponent}from'./components/todo-input.component';
@NgModule({imports:[...],declarations:[TodoListComponent,TodoItemComponent,TodoInputComponent],bootstrap:[...]})exportclassToDoAppModule{}
Thepropertydeclarationsexpectsanarrayofcomponents,directivesandpipesthatarepartofthemodule.
PleaseseetheModulessectionformoreinfoaboutNgModule.
UsingOtherComponents
90
-
DirectivesADirectivemodifiestheDOMtochangeapperance,behaviororlayoutofDOMelements.DirectivesareoneofthecorebuildingblocksAngular2usestobuildapplications.Infact,Angular2componentsareinlargepartdirectiveswithtemplates.
FromanAngular1perspective,Angular2componentshaveassumedalotoftherolesdirectivesusedto.Themajorityofissuesthatinvolvetemplatesanddependencyinjectionruleswillbedonethroughcomponents,andissuesthatinvolvemodifyinggenericbehaviourisdonethroughdirectives.
TherearethreemaintypesofdirectivesinAngular2:
Component-directivewithatemplate.Attributedirectives-directivesthatchangethebehaviorofacomponentorelementbutdon'taffectthetemplateStructuraldirectives-directivesthatchangethebehaviorofacomponentorelementbyaffectinghowthetemplateisrendered
Directives
91
-
AttributeDirectivesAttributedirectivesareawayofchangingtheappearanceorbehaviorofacomponentoranativeDOMelement.Ideally,adirectiveshouldworkinawaythatiscomponentagnosticandnotboundtoimplementationdetails.
Forexample,Angular2hasbuilt-inattributedirectivessuchasngClassandngStylethatworkonanycomponentorelement.
AttributeDirectives
92
-
NgStyleDirectiveAngular2providesabuilt-indirective,ngStyle,tomodifyacomponentorelement'sstyleattribute.Here'sanexample:
@Component({selector:'app-style-example',template:`
`})exportclassStyleExampleComponent{borderStyle='1pxsolidblack';}
ViewExample
Noticethatbindingadirectiveworkstheexactsamewayascomponentattributebindings.Here,we'rebindinganexpression,anobjectliteral,tothengStyledirectivesothedirectivenamemustbeenclosedinsquarebrackets.ngStyleacceptsanobjectwhosepropertiesandvaluesdefinethatelement'sstyle.Inthiscase,wecanseethatbothkebabcaseandlowercamelcasecanbeusedwhenspecifyingastyleproperty.AlsonoticethatboththehtmlstyleattributeandAngular2ngStyledirectivearecombinedwhenstylingtheelement.
Wecanremovethestylepropertiesoutofthetemplateintothecomponentasapropertyobject,whichthengetsassignedtoNgStyleusingpropertybinding.Thisallowsdynamicchangestothevaluesaswellasprovidestheflexibilitytoaddandremovestyleproperties.
NgStyleDirective
93
https://plnkr.co/edit/akK3Gw8W6EgUQ4PRQp4h?p=preview
-
@Component({selector:'app-style-example',template:`
`})exportclassStyleExampleComponent{borderStyle='1pxsolidblack';
alertStyles={'color':'red','font-weight':'bold','borderBottom':this.borderStyle};}
NgStyleDirective
94
-
NgClassDirectiveThengClassdirectivechangestheclassattributethatisboundtothecomponentorelementit'sattachedto.Thereareafewdifferentwaysofusingthedirective.
BindingastringWecanbindastringdirectlytotheattribute.Thisworksjustlikeaddinganhtmlclassattribute.
@Component({selector:'app-class-as-string',template:`
`,styles:[`.centered-text{text-align:center;}
.underlined{border-bottom:1pxsolid#ccc;}
.orange{color:orange;}`]})exportclassClassAsStringComponent{}
ViewExample
Inthiscase,we'rebindingastringdirectlysoweavoidwrappingthedirectiveinsquarebrackets.AlsonoticethatthengClassworkswiththeclassattributetocombinethefinalclasses.
Bindinganarray
NgClassDirective
95
https://plnkr.co/edit/uUtjY1Qlkx5dOB8gsqCm?p=preview
-
@Component({selector:'app-class-as-array',template:`
`,styles:[`.warning{color:red;font-weight:bold;}
.big{font-size:1.2rem;}`]})exportclassClassAsArrayComponent{}
ViewExample
Here,sincewearebindingtothengClassdirectivebyusinganexpression,weneedtowrapthedirectivenameinsquarebrackets.Passinginanarrayisusefulwhenyouwanttohaveafunctionputtogetherthelistofapplicableclassnames.
BindinganobjectLastly,anobjectcanbeboundtothedirective.Angular2applieseachpropertynameofthatobjecttothecomponentifthatpropertyistrue.
NgClassDirective
96
https://plnkr.co/edit/uUtjY1Qlkx5dOB8gsqCm?p=preview
-
@Component({selector:'app-class-as-object',template:`
ToggleFlat`,styles:[`.card{border:1pxsolid#eee;padding:1rem;margin:0.4rem;font-family:sans-serif;box-shadow:2px2px2px#888888;}
.dark{background-color:#444;border-color:#000;color:#fff;}
.flat{box-shadow:none;}`]})exportclassClassAsObjectComponent{flat:boolean=true;}
ViewExample
Herewecanseethatsincetheobject'scardandflatpropertiesaretrue,thoseclassesareappliedbutsincedarkisfalse,it'snotapplied.
NgClassDirective
97
https://plnkr.co/edit/uUtjY1Qlkx5dOB8gsqCm?p=preview
-
StructuralDirectivesStructuralDirectivesareawayofhandlinghowacomponentorelementrendersthroughtheuseofthetemplatetag.Thisallowsustorunsomecodethatdecideswhatthefinalrenderedoutputwillbe.Angular2hasafewbuilt-instructuraldirectivessuchasngIf,ngFor,andngSwitch.
Note:Forthosewhoareunfamiliarwiththetemplatetag,itisanHTMLelementwithafewspecialproperties.Contentnestedinatemplatetagisnotrenderedonpageloadandissomethingthatismeanttobeloadedthroughcodeatruntime.Formoreinformationonthetemplatetag,visittheMDNdocumentation.
Structuraldirectiveshavetheirownspecialsyntaxinthetemplatethatworksassyntacticsugar.
@Component({selector:'app-directive-example',template:`
Underastructuraldirective.
`})
Insteadofbeingenclosedbysquarebrackets,ourdummystructuraldirectiveisprefixedwithanasterisk.Noticethatthebindingisstillanexpressionbindingeventhoughtherearenosquarebrackets.That'sduetothefactthatit'ssyntacticsugarthatallowsusingthedirectiveinamoreintuitivewayandsimilartohowdirectiveswereusedinAngular1.Thecomponenttemplateaboveisequivalenttothefollowing:
@Component({selector:'app-directive-example',template:`
Underastructuraldirective.
`})
Here,weseewhatwasmentionedearlierwhenwesaidthatstructuraldirectivesusethetemplatetag.Angular2alsohasabuilt-intemplatedirectivethatdoesthesamething:
StructuralDirectives
98
https://developer.mozilla.org/en/docs/Web/HTML/Element/template
-
@Component({selector:'app-directive-example',template:`
Underastructuraldirective.
`})
StructuralDirectives
99
-
NgIfDirectiveThengIfdirectiveconditionallyaddsorremovescontentfromtheDOMbasedonwhetherornotanexpressionistrueorfalse.
Here'sourappcomponent,wherewebindthengIfdirectivetoanexamplecomponent.
@Component({selector:'app-root',template:`ToggleComponentHello`})exportclassAppComponent{exists=true;
toggleExists(){this.exists=!this.exists;}}
ViewExample
ClickingthebuttonwilltogglewhetherornotIfExampleComponentisapartoftheDOMandnotjustwhetheritisvisibleornot.Thismeansthateverytimethebuttonisclicked,IfExampleComponentwillbecreatedordestroyed.Thiscanbeanissuewithcomponentsthathaveexpensivecreate/destroyactions.Forexample,acomponentcouldhavealargechildsubtreeormakeseveralHTTPcallswhenconstructed.InthesecasesitmaybebettertoavoidusingngIfifpossible.
NgIfDirective
100
https://plnkr.co/edit/Kb0KW89265F0e9pYJ118?p=preview
-
NgForDirectiveTheNgFordirectiveisawayofrepeatingatemplatebyusingeachitemofaniterableasthattemplate'scontext.
@Component({selector:'app-root',template:`{{episode.title}}`})exportclassAppComponent{episodes=[{title:'WinterIsComing',director:'TimVanPatten'},{title:'TheKingsroad',director:'TimVanPatten'},{title:'LordSnow',director:'BrianKirk'},{title:'Cripples,Bastards,andBrokenThings',director:'BrianKirk'},{title:'TheWolfandtheLion',director:'BrianKirk'},{title:'AGoldenCrown',director:'DanielMinahan'},{title:'YouWinorYouDie',director:'DanielMinahan'},{title:'ThePointyEnd',director:'DanielMinahan'}];}
ViewExample
TheNgFordirectivehasadifferentsyntaxfromotherdirectiveswe'veseen.Ifyou'refamiliarwiththefor...ofstatement,you'llnoticethatthey'realmostidentical.NgForletsyouspecifyaniterableobjecttoiterateoverandthenametorefertoeachitembyinsidethescope.Inourexample,youcanseethatepisodeisavailableforinterpolationaswellaspropertybinding.Thedirectivedoessomeextraparsingsothatwhenthisisexpandedtotemplateform,itlooksabitdifferent:
@Component({selector:'app',template:`{{episode.title}}`})
NgForDirective
101
https://plnkr.co/edit/dXU4K13piTYotDX5Nhi6?p=previewhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
-
ViewExample
Noticethatthereisanoddlet-episodepropertyonthetemplateelement.TheNgFordirectiveprovidessomevariablesascontextwithinitsscope.let-episodeisacontextbindingandhereittakesonthevalueofeachitemoftheiterable.
LocalVariablesNgForalsoprovidesothervaluesthatcanbealiasedtolocalvariables:
index-positionofthecurrentitemintheiterablestartingat0first-trueifthecurrentitemisthefirstitemintheiterablelast-trueifthecurrentitemisthelastitemintheiterableeven-trueifthecurrentindexisanevennumberodd-trueifthecurrentindexisanoddnumber
@Component({selector:'app-root',template:`{{i+1}}.{{episode.title}}
Desugared
{{i+1}}.{{episode.title}}`})
ViewExample
trackBy
NgForDirective
102
https://plnkr.co/edit/dXU4K13piTYotDX5Nhi6?p=previewhttps://plnkr.co/edit/58A5p8cWpVIY7Ne4O7aO?p=preview
-
OftenNgForisusedtoiteratethroughalistofobjectswithauniqueIDfield.Inthiscase,wecanprovideatrackByfunctionwhichhelpsAngularkeeptrackofitemsinthelistsothatitcandetectwhichitemshavebeenaddedorremovedandimproveperformance.
Angular2willtryandtrackobjectsbyreferencetodeterminewhichitemsshouldbecreatedanddestroyed.However,ifyoureplacethelistwithanewsourceofobjects,perhapsasaresultofanAPIrequest-wecangetsomeextraperformancebytellingAngular2howwewanttokeeptrackofthings.
Forexample,iftheAddEpisodebuttonwastomakearequestandreturnanewlistofepisodes,wemightnotwanttodestroyandre-createeveryiteminthelist.IftheepisodeshaveauniqueID,wecouldaddatrackByfunction:
NgForDirective
103
-
@Component({selector:'app-root',template:`AddEpisode{{episode.title}}`})exportclassAppComponent{
otherEpisodes=[{title:'TwoSwords',director:'D.B.Weiss',id:8},{title:'TheLionandtheRose',director:'AlexGraves',id:9},{title:'BreakerofChains',director:'MichelleMacLaren',id:10},{title:'Oathkeeper',director:'MichelleMacLaren',id:11}]
episodes=[{title:'WinterIsComing',director:'TimVanPatten',id:0},{title:'TheKingsroad',director:'TimVanPatten',id:1},{title:'LordSnow',director:'BrianKirk',id:2},{title:'Cripples,Bastards,andBrokenThings',director:'BrianKirk',id:3},{title:'TheWolfandtheLion',director:'BrianKirk',id:4},{title:'AGoldenCrown',director:'DanielMinahan',id:5},{title:'YouWinorYouDie',director:'DanielMinahan',id:6}{title:'ThePointyEnd',director:'DanielMinahan',id:7}];
addOtherEpisode(){//WewanttocreateanewobjectreferenceforsakeofexampleletepisodesCopy=JSON.parse(JSON.stringify(this.episodes))this.episodes=[...episodesCopy,this.otherEpisodes.pop()];}trackById(index:number,episode:any):number{returnepisode.id;}}
ToseehowthiscanaffecttheForExamplecomponent,let'saddsomeloggingtoit.
NgForDirective
104
-
exportclassForExampleComponent{@Input()episode;
ngOnInit(){console.log('componentcreated',this.episode)}ngOnDestroy(){console.log('destroyingcomponent',this.episode)}}
ViewExample
Whenweviewtheexample,asweclickonAddEpisode,wecanseeconsoleoutputindicatingthatonlyonecomponentwascreated-forthenewlyaddeditemtothelist.
However,ifweweretoremovethetrackByfromthe*ngFor-everytimeweclickthebutton,wewouldseetheitemsinthecomponentgettingdestroyedandrecreated.
ViewExampleWithouttrackBy
NgForDirective
105
https://plnkr.co/edit/jQmozF?p=previewhttps://plnkr.co/edit/hC2cIK?p=preview
-
NgSwitchDirectivesngSwitchisactuallycomprisedoftwodirectives,anattributedirectiveandastructuraldirective.It'sverysimilartoaswitchstatementinJavaScriptandotherprogramminglanguages,butinthetemplate.
@Component({selector:'app-root',template:`Tab1Tab2Tab3
Tabcontent1Tabcontent2Selectatab`})exportclassAppComponent{tab:number=0;
setTab(num:number){this.tab=num;}
isSelected(num:number){returnthis.tab===num;}}
ViewExample
HereweseethengSwitchattributedirectivebeingattachedtoanelement.Thisexpressionboundtothedirectivedefineswhatwillcomparedagainstintheswitchstructuraldirectives.IfanexpressionboundtongSwitchCasematchestheonegiventongSwitch,thosecomponentsarecreatedandtheothersdestroyed.Ifnoneofthecasesmatch,thencomponentsthathavengSwitchDefaultboundtothemwillbecreatedandtheothersdestroyed.NotethatmultiplecomponentscanbematchedusingngSwitchCaseandinthosecasesallmatchingcomponentswillbecreated.Sincecomponentsarecreatedordestroyedbeawareofthecostsindoingso.
NgSwitchDirectives
106
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/switchhttps://plnkr.co/edit/QWxD0DIZi6QiISafwfgu?p=preview
-
NgSwitchDirectives
107
-
UsingMultipleStructuralDirectivesSometimeswe'llwanttocombinemultiplestructuraldirectivestogether,likeiteratingusingngForbutwantingtodoanngIftomakesurethatthevaluematchessomeormultipleconditions.Combiningstructuraldirectivescanleadtounexpectedresultshowever,soAngular2requiresthatatemplatecanonlybeboundtoonedirectiveatatime.Toapplymultipledirectiveswe'llhavetoexpandthesugaredsyntaxornesttemplatetags.
@Component({selector:'app-root',template:`{{item}}`})
ViewExample
TheprevioustabsexamplecanusengForandngSwitchifthetabtitleandcontentisabstractedawayintothecomponentclass.
UsingMultipleStructuralDirectives
108
https://plnkr.co/edit/V2nWlGOwIITPrUDksGNG?p=preview
-
import{Component}from'@angular/core';
@Component({selector:'app-root',template:`
{{tab.title}}
{{tab.content}}Selectatab`})exportclassAppComponent{tabNumber:number=-1;
tabs=[{title:'Tab1',content:'Tabcontent1'},{title:'Tab2',content:'Tabcontent2'},{title:'Tab3',content:'Tabcontent3'},];
setTab(num:number){this.tabNumber=num;}
isSelected(num:number){returnthis.tabNumber===i;}}
ViewExample
UsingMultipleStructuralDirectives
109
https://plnkr.co/edit/YOT4G4buUZduwvVi8cMA?p=preview
-
AdvancedComponents
Figure:GBNetworkPCICardbyHarkeislicensedunderP