itech.pkitech.pk/uploads/attachments/1495119359.pdf · 1.1 1.2 1.3 2.1 2.1.1 2.1.1.1 2.1.1.2...
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
WhyAngular?
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
BootstrappinganAngularApplication
UnderstandingtheFileStructure
BootstrappingProviders
ComponentsinAngular
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
10.1.5
11.1
11.1.1
11.1.2
11.1.3
11.1.4
11.1.5
11.1.6
Observables
UsingObservables
ErrorHandling
DisposingSubscriptionsandReleasingResources
ObservablesvsPromises
UsingObservablesFromOtherSources
ObservablesArrayOperations
ColdvsHotObservables
Summary
AngularDependencyInjection
WhatisDI?
DIFramework
Angular'sDI
@Inject()and@Injectable
InjectionBeyondClasses
AvoidingInjectionCollisions:OpaqueToken
TheInjectorTree
Http
MakingRequests
CatchingRejections
CatchandRelease
CancelaRequest
Retry
SearchwithflatMap
EnhancingSearchwithswitchMap
RequestsasPromises
ChangeDetection
ChangeDetectionStrategiesinAngular1vsAngular2
HowChangeDetectionWorks
ChangeDetectorClasses
ChangeDetectionStrategy:OnPush
EnforcingImmutability
AdditionalResources
4
-
12.1
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
Zone.js
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
5
-
16.1.2.1
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.1.1
19.1.1.2
19.1.1.3
NestingFormData
UsingTemplateModelBinding
ValidatingTemplate-DrivenForms
Reactive/Model-DrivenForms
FormBuilderBasics
ValidatingFormBuilderForms
FormBuilderCustomValidation
VisualCuesforUsers
Modules
WhatisanAngularModule?
AddingComponents,PipesandServicestoaModule
CreatingaFeatureModule
DirectiveDuplications
LazyLoadingaModule
LazyLoadingandtheDependencyInjectionTree
SharedModulesandDependencyInjection
SharingtheSameDependencyInjectionTree
Routing
WhyRouting?
ConfiguringRoutes
RedirectingtheRoutertoAnotherRoute
DefiningLinksBetweenRoutes
DynamicallyAddingRouteComponents
UsingRouteParameters
DefiningChildRoutes
ControllingAccesstoorfromaRoute
PassingOptionalParameterstoaRoute
UsingAuxiliaryRoutes
StateManagement
Reduxand@ngrx
Adding@ngrxtoyourProject
DefiningyourMainApplicationState
ExampleApplication
6
-
19.1.1.4
19.1.1.5
19.1.1.6
19.1.1.7
19.1.1.8
19.1.1.9
19.1.1.10
19.1.1.11
19.1.1.12
19.1.1.13
19.1.1.14
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
ReadingyourApplicationStateusingSelectors
Actions
ModifyingyourApplicationStatebyDispatchingActions
ReducersandPureFunctions
ReducersasStateManagement
CreatingyourApplication'sRootReducer
ConfiguringyourApplication
ImplementingComponents
ComponentArchitecture
SideEffects
GettingMoreFromReduxand@ngrx
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
7
-
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
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
TestingRedux
TestingSimpleActions
TestingComplexActions
TestingReducers
Afterthoughts
MigratingAngular1.xProjectstoAngular2
MigrationPrep
UpgradingToAngular1.3+Style
UsingWebpack
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
8
-
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
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
CreatingaNewApp
ServingtheApp
CreatingComponents
CreatingRoutes
CreatingOtherThings
Testing
Linting
CLICommandOverview
AddingThirdPartyLibraries
IntegratinganExistingApp
AccessibilityinAngular
WhyMakemyApplicationAccessible?
KeyConcernsofAccessibleWebApplications
SemanticMarkup
KeyboardAccessibility
VisualAssistance
TestingforAccessibility
IsmyApplicationReadable?
IsmyApplicationPredictable?
IsmyApplicationNavigable?
TestingwithScreenReaders
AdditionalResources
InternationalizationinAngular
Whatistheprocesslikeandhowisinvolved?
Markingtextinourtemplates
ExtractingtranslationtextusingtheAngularCLI
Howtoimportthecompletedtranslationfiles
UsingtheAoTCompiler
UsingtheJiTCompiler
Glossary
FurtherReadingAndReference
9
-
10
-
Rangle'sAngularTrainingBook
Overthelastthreeandahalfyears,AngularhasbecometheleadingopensourceJavaScriptapplicationframeworkforhundredsofthousandsofprogrammersaroundtheworld.The"1.x"versionofAngularhasbeenwidelyusedandbecameextremelypopularforcomplexapplications.ThenewAngular2.xhasalsoannounceditsfinalreleaseversion.
AboutRangle’sAngularTrainingBookWedevelopedthisbooktobeusedascoursematerialforRangle'sAngulartraining,butmanypeoplehavefoundittobeusefulforlearningAngularontheirown.ThisbookwillcoverthemostimportantAngulartopics,fromgettingstartedwiththeAngulartoolchaintowritingAngularapplicationsinascalableandmaintainablemanner.
Ifyoufindthismaterialuseful,youshouldalsoconsiderregisteringforoneofRangle’strainingcourses,whichfacilitatehands-onlearningandareagreatfitforcompaniesthatneedtotransitiontheirtechnologytoAngular,orindividualslookingtoupgradetheirskills.
Rangle.ioalsohasanAngular1.xbookwhichisgearedtowardswritingAngular1.xapplicationsinanAngular2style.Wehopeyouenjoythisbook.WewelcomeyourfeedbackintheDiscussionArea.
Introduction
11
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
12
-
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
13
https://creativecommons.org/licenses/by-sa/4.0/legalcodehttps://creativecommons.org/licenses/by-sa/4.0/legalcode
-
WhyAngular?Therearemanyfront-endJavaScriptframeworkstochoosefromtoday,eachwithitsownsetoftrade-offs.ManypeoplewerehappywiththefunctionalitythatAngular1.xaffordedthem.Angular2improvedonthatfunctionalityandmadeitfaster,morescalableandmoremodern.OrganizationsthatfoundvalueinAngular1.xwillfindmorevalueinAngular2.
Angular'sAdvantagesThefirstreleaseofAngularprovidedprogrammerswiththetoolstodevelopandarchitectlargescaleJavaScriptapplications,butitsagehasrevealedanumberofflawsandsharpedges.Angular2wasbuiltonfiveyearsofcommunityfeedback.
Angular2IsEasier
ThenewAngularcodebaseismoremodern,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.
Byfocusingonmakingtheframeworkeasierforcomputerstoprocess,Angular2allowsforamuchricherdevelopmentecosystem.Programmersusingsophisticatedtexteditors(orIDEs)willnoticedramaticimprovementswithauto-completionandtypesuggestions.These
WhyAngular?
14
https://toddmotto.com/angular-component-method-back-ported-to-1.3/
-
improvementshelptoreducethecognitiveburdenoflearningAngular2.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,providinganotherwaytoleveragenativedevicefeatureswithAngular.
ProjectArchitectureandMaintenance
ThefirstiterationofAngularprovidedwebprogrammerswithahighlyflexibleframeworkfordevelopingapplications.Thiswasadramaticshiftformanywebprogrammers,andwhilethatframeworkwashelpful,itbecameevidentthatitwasoftentooflexible.Overtime,bestpracticesevolved,andacommunity-drivenstructurewasendorsed.
Angular1.xtriedtoworkaroundvariousbrowserlimitationsrelatedtoJavaScript.Thiswasdonebyintroducingamodulesystemthatmadeuseofdependencyinjection.Thissystemwasnovel,butunfortunatelyhadissueswithtooling,notablyminificationandstaticanalysis.
WhyAngular?
15
https://www.nativescript.org/
-
Angular2.xmakesuseoftheES2015modulesystem,andmodernpackagingtoolslikewebpackorSystemJS.Modulesarefarlesscoupledtothe"Angularway",andit'seasiertowritemoregenericJavaScriptandplugitintoAngular.Theremovalofminificationworkaroundsandtheadditionofrigidprescriptionsmakemaintainingexistingapplicationssimpler.Thenewmodulesystemalsomakesiteasiertodevelopeffectivetoolingthatcanreasonbetteraboutlargerprojects.
NewFeatures
SomeoftheotherinterestingfeaturesinAngular2are:
FormBuilderChangeDetectionTemplatingRoutingAnnotationsObservablesShadowDOM
DifferencesBetweenAngular1&2Notethat"TransitionalArchitecture"referstoastyleofAngular1applicationwritteninawaythatmimicsAngular2'scomponentstyle,butwithcontrollersanddirectivesinsteadofTypeScriptclasses.
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
WhyAngular?
16
-
WhyAngular?
17
-
EcmaScript6andTypeScriptFeatures
Figure:ES6andTypeScript
Thelanguageweusuallycall"JavaScript"isformallyknownas"EcmaScript".ThenewversionofJavaScript,knownas"ES6",offersanumberofnewfeaturesthatextendthepowerofthelanguage.
ES6isnotwidelysupportedintoday'sbrowsers,soitneedstobetranspiledtoES5.Youcanchoosebetweenseveraltranspilers,butwe'llbeusingTypeScript,whichiswhattheAngularteamusestowriteAngular.AngularmakesuseofanumberoffeaturesofES6andTypeScript.
EcmaScript6andTypeScriptFeatures
18
-
ES6JavaScriptwascreatedin1995,butthelanguageisstillthrivingtoday.Therearesubsets,supersets,currentversionsandthelatestversionES6thatbringsalotofnewfeatures.
Someofthehighlights:
ClassesArrowFunctionsTemplateStringsInheritanceConstantsandBlockScopedVariablesSpreadandRestoperatorsDestructuringModules
ES6
19
-
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
20
-
Classes
21
-
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.Thisisrarelywhatyouwant,anditcanbeconfusingwhenthisisnotwhatyouwereexpecting,becauseofwherethefunctionwascalledfrom.In"strict"mode,thiswouldbeundefined,whichisslightlylessconfusing.
Refresheron'this'
22
-
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'
23
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
24
-
classToppings{constructor(toppings){this.toppings=Array.isArray(toppings)?toppings:[];}outputList(){this.toppings.forEach(function(topping,i){console.log(topping,i+'/'+this.toppings.length);//`this`willbeundefined});}}
varmyToppings=newToppings(['cheese','lettuce']);
myToppings.outputList();
Let'strythiscodeonhttp://jsbin.com.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!});}}
varmyToppings=newToppings(['cheese','lettuce']);
myToppings.outputList();
Let'strythiscodeonhttp://jsbin.com.Herethisinsidethearrowfunctionreferstotheinstancevariable.
Warningarrowfunctionsdonothavetheirownargumentsvariable,whichcanbeconfusingtoveteranJavaScriptprogrammers.superandnew.targetarealsoscopedfromtheouterenclosure.
ArrowFunctions
25
http://jsbin.com/qakigoqulo/edit?js,consolehttp://jsbin.com/tulikutife/edit?js,console
-
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
26
-
InheritanceJavaScript'sinheritanceworksdifferentlyfrominheritanceinotherlanguages,whichcanbeveryconfusing.ES6classesprovideasyntacticsugarattemptingtoalleviatetheissueswithusingprototypicalinheritancepresentinES5.
Toillustratethis,let'simagewehaveazooapplicationwheretypesofbirdsarecreated.Inclassicalinheritance,wedefineabaseclassandthensubclassittocreateaderivedclass.
SubclassingTheexamplecodebelowshowshowtoderivePenguinfromBirdusingtheextendskeyword.AlsopayattentiontothesuperkeywordusedinthesubclassconstructorofPenguin,itisusedtopasstheargumenttothebaseclassBird'sconstructor.
TheBirdclassdefinesthemethodwalkwhichisinheritedbythePenguinclassandisavailableforusebyinstanceofPenguinobjects.LikewisethePenguinclassdefinesthemethodswimwhichisnotavilabletoBirdobjects.Inheritanceworkstop-downfrombaseclasstoitssubclass.
ObjectInitializationTheclassconstructoriscalledwhenanobjectiscreatedusingthenewoperator,itwillbecalledbeforetheobjectisfullycreated.Aconsturctorisusedtopassinargumentstoinitializethenewlycreatedobject.
Theorderofobjectcreationstartsfromitsbaseclassandthenmovesdowntoanysubclass(es).
Inheritance
27
-
//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
28
-
//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
29
-
DelegationIntheinheritancesectionwelookedatonewaytoextendaclassfunctionality,thereissecondwayusingdelegationtoextendfunctionality.Withdelegation,oneobjectwillcontainareferencetoadifferentobjectthatitwillhandoffarequesttoperformthefunctionality.
ThecodebelowshowshowtousedelegationwiththeBirdclassandPenguinclass.ThePenguinclasshasareferencetotheBirdclassanditdelegatesthecallmadetoit'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
30
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
31
-
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
32
-
Theexampleabovedemonstratesthatweareabletochangethenamepropertyofobjectperson,butweareunabletoresetthereferencepersonsinceithasbeenmarkedasconst.
ConstReferenceToAnObjectSomethingsimilartotheabovecodeisusingaconstreference,belowwe'veswitchtousingletfortheliteralobject.
letperson={name:'Tammy'};
constp=person;
p.name='Pushpa';//OK,namepropertychanged.
p=null;//"TypeError:Assignmenttoconstantvariable.
Takeaway,markinganobjectreferenceconstdoesnotmakepropertiesinsidetheobjectconst.
Ref:.
ConstantsandBlockScopedVariables
33
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
-
SpreadSyntax(SpreadElement)andRestparametersASpreadsyntaxallowsin-placeexpansionofanexpressionforthefollowingcases:
1. Array2. Functioncall3. Multiplevariabledestructuring
Restparametersworksintheoppositedirectionofthespreadsyntax,itcollectsanindefinitenumberofcommaseparatedexpressionsintoanarray.
SpreadSyntaxSpreadexample:
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}
RestparameterRestparameterssharetheellipsislikesyntaxofspreadsyntaxbutareusedforadifferentpurpose.Restparametersareusedtoaccessindefinitenumberofargumentspassedtoafunction.Forexample:
...spreadand...rest
34
-
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.
Restparametersareinfactarrayswhichprovidesaccesstomethodslikemap,filter,reduceandmore.Theotherimportantdifferenceisthatrestparametersonlyincludeargumentsnotspecificallynamedinafunctionlikeso:
functionprint(a,b,c,...more){console.log(more[0]);console.log(arguments[0]);}
print(1,2,3,4,5);//4//1
Note:CommonlyspreadsyntaxandrestparametersarereferencedasSpreadandRestoperatorsbuttheyaren'toperatorsaccordingtoECMAScriptspecifications.FewreferencesMDN-SpreadSyntax,MDN-RestParameters,ECMAScriptSpec-SpreadSyntax,ECMAScriptSpec-RestParameters
...spreadand...rest
35
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operatorhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parametershttp://www.ecma-international.org/ecma-262/6.0/#sec-array-initializerhttp://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions
-
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
36
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
37
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.Readmoreaboutarrowfunctionshere
ModuleSystemsUsingamoduleonthebackend(serverside)isrelativelystraightforward,yousimplymakeuseoftheimportkeyword.HoweverWebBrowsershavenoconceptofmodulesorimport,theyjustknowhowtoloadjavascriptcode.Weneedawaytobringinajavascriptmoduletostartusingitfromotherjavascriptcode.Thisiswhereamoduleloadercomesin.
Wewon'tgetintothevariousmodulesystemsoutthere,butit'sworthunderstandingtherearevariousmoduleloadersavailable.Thepopularchoicesoutthereare:
RequireJSSystemJSWebpack
LoadingaModuleFromaBrowserBelowwemakeuseofSystemJStoloadamodule.ThescriptfirstloadsthecodefortheSystemJSlibrary,thenthefunctioncallSystem.importisusetoimport(load)theappmodule.
Modules
38
https://angular-2-training-book.rangle.io/handout/features/arrow_functions.html
-
LoadingES6modulesisalittletrickier.InanES6-compliantbrowseryouusetheSystemkeywordtoloadmodulesasynchronously.Tomakeourcodeworkwithcurrentbrowsers,however,wewillusetheSystemJSlibraryasapolyfill:
varpromise=System.import('app').then(function(){console.log('Loaded!');}).then(null,function(error){console.error('Failedtoload:',error);});
Modules
39
-
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
40
-
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
41
-
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
42
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.
ForAngularprojectsthereareanumberofspecificsettingsthatneedtobeconfiguredinaproject'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
43
-
Thetargetmoduleresolutioninterface.We'reintegratingTypeScriptthroughwebpackwhichsupportsdifferentinterfaces.We'vedecidedtousenode'smoduleresolutioninterface,commonjs.
Decorators
DecoratorsupportinTypeScripthasn'tbeenfinalizedyetbutsinceAngularusesdecoratorsextensively,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
44
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
45
-
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
46
-
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
47
-
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
48
-
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
49
-
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
50
-
interfaceAction{type:string;}
leta:Action={type:'literal'}
Interfaces
51
-
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
52
-
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
53
-
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
54
-
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
55
-
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
56
-
Toillustratethehowmuchthetypekeywordimprovedthereadabilityoftheprevioussnippet,hereisthefunctiontypedefinedinline.
functionsendRequest(cb:(err:Error|null,response:Object)=>void):void{if(cb){cb(null,{});}}
TypeKeyword
57
-
DecoratorsDecoratorsareproposedforafutureversionofJavaScript,buttheAngularteamreallywantedtousethem,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;
ReaderswhohaveplayedwithAngularwillnoticethatthesesignaturesdonotlooklikethesignaturesusedbyAngularspecificdecoratorslike@Component().
Noticethe()[email protected]@ComponentiscalledonceJavaScriptencounters@Component().Inturn,thismeansthattheremustbeaComponentfunctionsomewherethatreturnsafunctionmatchingoneofthedecoratorsignaturesoutlinedabove.Thisisanexampleofthedecoratorfactorypattern.
Ifdecoratorsstilllookconfusing,perhapssomeexampleswillclearthingsup.
Decorators
58
-
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
59
-
PropertyDecorators
60
-
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
61
-
ClassDecorators
62
-
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.ReadersfamiliarwithAngularcannowimaginehowAngularimplementedtheir@Inject()system.
ParameterDecorators
63
-
TheJavaScriptToolchainInthissection,we'lldescribethetoolsthatyou'llbeusingfortherestofthecourse.
Figure:HandToolsbyM338islicensedunderPublicDomain(http://commons.wikimedia.org/wiki/File:Hand_tools.jpg)
TheJavaScriptToolchain
64
-
SourceControl:GitAsourcecontrol,sometimescalledaversioncontrolbringschangemanagementtosavingfilesatdifferentpointsinthedevelopmentprocess.AVersioncontrolsystem(VCS)thatwillwemakeuseofisGit.
Gitisadecentralizeddistributedversioningsystem,itallowsprogrammerstocollaborateonthesamecodebasewithoutsteppingoneachother'stoes.Ithasbecomethede-factosourcecontrolsystemforopensourcedevelopmentbecauseofitsdecentralizedmodelandcheapbranchingfeatures.
FormoreinformationonhowtouseGit,headovertoProGit
SourceControl:git
65
http://git-scm.com/https://www.gitbook.com/book/gitbookio/progit/details
-
TheCommandLineJavaScriptdevelopmenttoolsareverycommandlineoriented.IfyoucomefromaWindowsbackgroundyoumayfindthisunfamiliar.Howeverthecommandlineprovidesbettersupportforautomatingdevelopmenttasks,soit'sworthgettingcomfortablewithit.
Wewillprovideexamplesforallcommandlineactivitiesrequiredbythiscourse.
TheCommandLine
66
-
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
67
http://nodejs.org
-
Back-EndCodeSharingandDistribution:npmnpmisthe"nodepackagemanager".ItinstallswithNodeJS,andgivesyouaccesstoawidevarietyof3rd-partyJavaScriptmodules.
Italsoperformsdependencymanagementforyourback-endapplication.Youspecifymoduledependenciesinafilecalledpackage.json;runningnpminstallwillresolve,downloadandinstallyourback-endapplication'sdependencies.
Back-EndCodeSharingandDistribution:npm
68
https://www.npmjs.com/
-
ModuleLoading,BundlingandBuildTasks:WebpackWebpackisaJavaScriptmodulebundler.Ittakesmoduleswiththeirdependenciesandgeneratesstaticassetsrepresentingthosemodules.WebpackknownonlyhowtobundleJavaScript.TobundleotherassetslikesCSS,HTML,imagesorjustaboutanythingitusesadditionalloaders.Webpackcanalsobeextendedviaplugins,forexampleminificationandmanglingcanbedoneusingtheUglifyJSpluginforwebpack.
ModuleLoading,BundlingandBuildTasks:Webpack
69
http://webpack.github.io/docs/what-is-webpack.html
-
WebBrowsersWeuseGoogle'sChromebrowserforthiscoursebecauseofitscutting-edgeJavaScriptengineandexcellentdebuggingtools.
Howeveryouarefreetouseotherbrowsers.Notwellknown,thereisaMozillaFirefoxDeveloperEditionavailablewithsupportforgreatdevelopmentanddebuggingtools.CodewrittenwithJavaScriptshouldworkonanymodernwebbrowser(Firefox,IE9+,Chrome,Safari,Opera).
Chrome
70
https://www.mozilla.org/en-US/firefox/developer/
-
BootstrappinganAngularApplicationBootstrappingisanessentialprocessinAngular-itiswheretheapplicationisloadedwhenAngularcomestolife.
BootstrappingAngularapplicationsiscertainlydifferentfromAngular1.x,butisstillastraightforwardprocedure.Let'stakealookathowthisisdone.
BootstrappinganAngularApplication
71
-
UnderstandingtheFileStructureTogetstartedlet'screateabare-bonesAngularapplicationwithasinglecomponent.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:'BootstrappinganAngularApplication'})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
72
-
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.
WhydoesAngularbootstrapitselfinthisway?Wellthereisactuallyaverygoodreason.SinceAngularisnotaweb-onlybasedframework,wecanwritecomponentsthatwillruninNativeScript,orCordova,oranyotherenvironmentthatcanhostAngularapplications.
Themagicistheninourbootstrappingprocess-wecanimportwhichplatformwewouldliketouse,dependingontheenvironmentwe'reoperatingunder.Inourexample,sincewewererunningourAngularapplicationinthebrowser,weusedthebootstrappingprocessfoundin@angular/platform-browser-dynamic.
It'salsoagoodideatoleavethebootstrappingprocessinitsownseparatemain.tsfile.Thismakesiteasiertotest(sincethecomponentsareisolatedfromthebootstrapcall),easiertoreuseandgivesbetterorganizationandstructuretoourapplication.
ThereismoretounderstandingAngularModulesand@NgModulewhichwillbecoveredlater,butfornowthisisenoughtogetstarted.
UnderstandingtheFileStructure
73
https://plnkr.co/edit/X0EBXA?p=preview
-
UnderstandingtheFileStructure
74
-
BootstrappingProvidersThebootstrapprocessalsostartsthedependencyinjectionsysteminAngular.Wewon'tgooverAngular'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
75
https://embed.plnkr.co/W8CkQQ62pIjHFr7BqVjX/
-
ComponentsinAngular
Figure:components
ThecoreconceptofanyAngularapplicationisthecomponent.Ineffect,thewholeapplicationcanbemodeledasatreeofthesecomponents.
ThisishowtheAngularteamdefinesacomponent:
Acomponentcontrolsapatchofscreenrealestatethatwecouldcallaview,anddeclaresreusableUIbuildingblocksforanapplication.
Basically,acomponentisanythingthatisvisibletotheenduserandwhichcanbereusedmanytimeswithinanapplication.
InAngular1.xwehadrouterviewsanddirectiveswhichworkedsortoflikecomponents.Theideaofdirectivecomponentsbecamequitepopular.TheywerecreatedbyusingdirectivewithacontrollerwhilerelyingonthecontrollerAsandbindToControllerproperties.Forexample:
ComponentsinAngular
76
-
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});
ComponentsinAngular
77
-
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
78
http://plnkr.co/edit/bXrxWVkP2MWD8yNDYqVD?p=preview
-
ApplicationStructurewithComponentsAusefulwayofconceptualizingAngularapplicationdesignistolookatitasatreeofnestedcomponents,eachhavinganisolatedscope.
Forexampleconsiderthefollowing:
Attherootwehaverio-todo-appwhichconsistsofario-todo-listandario-todo-form.Withinthelistwehaveseveralrio-todo-items.Eachofthesecomponentsisvisibletotheuser,whocaninteractwiththesecomponentsandperformactions.
ApplicationStructurewithComponents
79
-
PassingDataintoaComponentTherearetwowaystopassdataintoacomponent,with'propertybinding'and'eventbinding'.InAngular,dataandeventchangedetectionhappenstop-downfromparenttochildren.HoweverforAngulareventswecanusetheDOMeventmentalmodelwhereeventsflowbottom-upfromchildtoparent.So,AngulareventscanbetreatedlikeregularHTMLDOMbasedeventswhenitcomestocancellableeventpropagation.
The@Input()decoratordefinesasetofparametersthatcanbepasseddownfromthecomponent'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
80
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
81
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
82
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
83
-
ViewExample
UsingTwo-WayDataBinding
84
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
85
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
86
https://plnkr.co/edit/wEFOta?p=preview
-
ProjectionProjectionisaveryimportantconceptinAngular.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
87
-
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
88
http://plnkr.co/edit/QAQ6BFuwuzEDVvqAmN9L?p=preview
-
...
SectionContentdivwith.class-selectFooterContentHeaderContent
...
Besidesusingdirectives,developerscanalsoselectang-contentthroughcssclass:
app/app.component.html
divwith.class-select
ViewExample
Projection
89
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
90
-
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
91
-
DirectivesADirectivemodifiestheDOMtochangeapperance,behaviororlayoutofDOMelements.DirectivesareoneofthecorebuildingblocksAngularusestobuildapplications.Infact,Angularcomponentsareinlargepartdirectiveswithtemplates.
FromanAngular1.xperspective,Angular2componentshaveassumedalotoftherolesdirectivesusedto.Themajorityofissuesthatinvolvetemplatesanddependencyinjectionruleswillbedonethroughcomponents,andissuesthatinvolvemodifyinggenericbehaviourisdonethroughdirectives.
TherearethreemaintypesofdirectivesinAngular:
Component-directivewithatemplate.Attributedirectives-directivesthatchangethebehaviorofacomponentorelementbutdon'taffectthetemplateStructuraldirectives-directivesthatchangethebehaviorofacomponentorelementbyaffectinghowthetemplateisrendered
Directives
92
-
AttributeDirectivesAttributedirectivesareawayofchangingtheappearanceorbehaviorofacomponentoranativeDOMelement.Ideally,adirectiveshouldworkinawaythatiscomponentagnosticandnotboundtoimplementationdetails.
Forexample,Angularhasbuilt-inattributedirectivessuchasngClassandngStylethatworkonanycomponentorelement.
AttributeDirectives
93
-
NgStyleDirectiveAngularprovidesabuilt-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.AlsonoticethatboththehtmlstyleattributeandAngularngStyledirectivearecombinedwhenstylingtheelement.
Wecanremovethestylepropertiesoutofthetemplateintothecomponentasapropertyobject,whichthengetsassignedtoNgStyleusingpropertybinding.Thisallowsdynamicchangestothevaluesaswellasprovidestheflexibilitytoaddandremovestyleproperties.
NgStyleDirective
94
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
95
-
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
96
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.Angularapplieseachpropertynameofthatobjecttothecomponentifthatpropertyistrue.
NgClassDirective
97
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
98
https://plnkr.co/edit/uUtjY1Qlkx5dOB8gsqCm?p=preview
-
StructuralDirectivesStructuralDirectivesareawayofhandlinghowacomponentorelementrendersthroughtheuseofthetemplatetag.Thisallowsustorunsomecodethatdecideswhatthefinalrenderedoutputwillbe.Angularhasafewbuilt-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.Angularalsohasabuilt-intemplatedirectivethatdoesthesamething:
StructuralDirectives
99
https://developer.mozilla.org/en/docs/Web/HTML/Element/template
-
@Component({selector:'app-directive-example',template:`
Underastructuraldirective.
`})
StructuralDirectives
100
-
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
101
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
102
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
103
https://plnkr.co/edit/dXU4K13piTYotDX5Nhi6?p=previewhttps://plnkr.co/edit/58A5p8cWpVIY7Ne4O7aO?p=preview
-
OftenNgForisusedtoiteratethroughalistofobjectswithauniqueIDfield.Inthiscase,wecanprovideatrackByfunctionwhichhelpsAngularkeeptrackofitemsinthelistsothatitcandetectwhichitemshavebeenaddedorremovedandimproveperformance.
Angularwilltryandtrackobjectsbyreferencetodeterminewhichitemsshouldbecreatedanddestroyed.However,ifyoureplacethelistwithanewsourceofobjects,perhapsasaresultofanAPIrequest-wecangetsomeextraperformancebytellingAngularhowwewanttokeeptrackofthings.
Forexample,iftheAddEpisodebuttonwastomakearequestandreturnanewlistofepisodes,wemightnotwanttodestroyandre-createeveryiteminthelist.IftheepisodeshaveauniqueID,wecouldaddatrackByfunction:
NgForDirective
104
-
@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
105
-
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
106
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
107
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/switchhttps://plnkr.co/edit/QWxD0DIZi6QiISafwfgu?p=preview
-
NgSwitchDirectives
108
-
UsingMultipleStructuralDirectivesSometimeswe'llwanttocombinemultiplestructuraldirectivestogether,likeiteratingusingngForbutwantingtodoanngIftomakesurethatthe