Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
AngularJSWebApplicationDevelopmentBlueprints
TableofContents
AngularJSWebApplicationDevelopmentBlueprints
Credits
AbouttheAuthor
AbouttheReviewers
www.PacktPub.com
Supportfiles,eBooks,discountoffers,andmore
Whysubscribe?
FreeaccessforPacktaccountholders
Preface
AboutJavaScriptMVCframeworks
HowAngularJSwasborn
Theideabehindthisbook
Whatthisbookcovers
Whatyouneedforthisbook
Softwareversions
Copyingthecodefiles
Whothisbookisfor
Conventions
Readerfeedback
Customersupport
Downloadingtheexamplecode
Errata
Piracy
Questions
1.IntroductiontoAngularJSandtheSinglePageApplication
DelvingintoSinglePageApps
AnatomyofasimpleAngularJSapp
Modelsandviews
BuildinganAddressBookApp
UnderstandingthescopeinAngularJS
Stylingtheapp
Sortingthecontactsalphabetically
AddingcontactstotheAddressBook
Theng-showandng-hidedirectives
Summary
2.SettingUpYourRig
SettingupNode.js
CreatingasimpleNode.jswebserverwithExpressJS
SettingupGrunt
InstallingGrunt-cli
Creatingthepackage.jsonfile
CreatingyourGrunttasks
Grunttaskstomergeandconcatenatefiles
RunningshellcommandsviaGrunt
Yeoman–theworkflowtool
InstallingYeoman
Runningyourapp
UnittestingwithKarma
UsingProtractorforEnd-to-Endtests
InstallingSeleniumServer
Understandingtheexample_spec.jsfile
Understandingtheconf.jsfile
WritingyourownProtractortestcases
Summary
3.RapidPrototypingwithAngularJS
UnderstandingtheapplicationthatwewillPrototype
IntroducingGridLayoutsandBootstrap
Understandingthegridsystem
IntroducingAngularUI
UI-Utils
UI-Modules
UI-Bootstrap
NG-Grid
UI-Router
IDEPlugins
PrototypingtheHealthyLivingwebsite
Addingtheui.bootstrapdependency
Creatingthenavigationbar
Addingthecarousel
Tweakingtheherounit
Addingthethreecontentblocks
Creatinganewview
Understandingroutes
Buildingthearticlesview
AccordionsusingAngularBootstrap
Buildingtheimagegallery
GalleryviewusingBootstrapThumbnail
Addingthestarrating
BuildingdatagridsusingNG-Grid
AddingtheNG-Gridcomponent
GroupingdatainNG-Grid
Excel-styleeditinginNG-Grid
Creatingamodalwindowtoaddsubscribers
Real-timeformvalidations
Summary
4.UsingRESTWebServicesinYourAngularJSApp
UnderstandingtheresponsefromaRESTAPI
TestingaRESTfulwebservice
JumpstartingyourappdevelopmentwithAngularSeed
FilesandfoldersinAngularSeed
AddingBootstraplibraries
StartingyourNodewebserver
Mark-upourLayout
Creatingtheroutes
UnderstandingAngularJSservices
Writingyourfirstfactoryservice
DependencyInjection
Codingthepartial
CallingtheRESTwebserviceusing$http
Usingpromiseforasynchronouscalls
DisplayingdatafromtheJSONresponse
Unittestingourapplication
Mocking$httpduringUnittesting
CreatingaPintereststylelayout
Addingactionstothebuttons
Summary
5.FacebookFriends’BirthdayReminderApp
UnderstandingtheFacebookSDK
TheSocialGraph
TheGraphAPI
TheGraphAPIExplorer
CreatingyourFacebookapp
Settingupourproject
Runningyourapplication
DelvingintoAngularJSdirectives
Whatisadirective?
Importanceofnamingconventionsfordirectives
Theanatomyofadirective
Writingourfirstdirective
AddingaFacebooklogin
Addingthefb-rootdivelement
LoadingtheFacebookSDK
Understanding$watchand$digest
Whentouse$apply
Gettingtheuser’sfriendlist
Gettingyourfriends’profilepicturesandbirthdays
RequestingadditionalpermissionwithFB.login
Understandingisolatedscope
AddingsomeCSSstyles
Changingtheroutes
Addinginthelogoutlink
Writingautomatedtests
WritingUnittestswithKarma
WritingEnd-to-EndtestsusingProtractor
Summary
6.BuildinganExpenseManagerMobileApp
UnderstandingHTML5WebStorage
localStorage
sessionStorage
BuildingtheExpenseManagerApp
BuildingtheAddExpenseform
Whatis$rootScope?
Understandingthe.runblock
CreatingavalueservicetostoreCategoryList
ValidatingtheAddExpenseform
UsinglocalStoragetosavedata
BuildingabarchartdirectivebasedonD3
Summarizingtheexpensesbycategories
Creatingourbarchartdirective
Makingtheappresponsive
AddingtheCSSmediaquery
ScalingtheD3chartbasedonwindowsize
Addingtouchevents
EnablingswipegesturesusingngTouch
AddingpagetransitionsusingngAnimate
LoadingthengAnimatemodule
AddingCSS3transitions
Makingtheappfeellikeanativeapp
Addingtouchicons
Runningtheappinfullscreenmode
Addingadditionalfeatures
Summary
7.BuildingaCMSontheMEANStack
WhytheMEANstack?
GettingstartedwiththeMEANstack
SettingupMongoDB
SettingupExpressJSandMongooseJS
Buildingtheserver-sideapp
CreatingtheMongooseschemas
CreatingCRUDroutes
Addinganewentrytothecollection
Updatingacollection
Deletingacollectionitem
Displayingasinglerecord
Securingyouradminsection
Usingbcrypttoencryptpasswords
Addinganewadminuser
Creatingtherouteforauthenticatinglogin
Creatingthelogoutroute
WritingthesessionCheckmiddleware
IntegratingAngularJSwithanExpressJSproject
GeneratingSEO-friendlyURLsusingHTML5mode
BuildingtheadminsectionforCRUDoperations
Creatingtheroutesfortheadminsection
Buildingthefactoryservices
Buildingthecontrollersfortheadminsection
Settinguptheadminpagelayout
Buildingthelistingviewfortheadminsection
SettingupauthenticationinAngularJS
Creatingourloginpage
Buildingacustommoduleforglobalnotification
Buildingandinitializingthemessage.flashmodule
Buildingthemessage.flashfactoryservice
Settingup$broadcasts
Buildingthedirectiveforthemessage.flashmodule
Settingaflashmessage
CreatingourAdd-Editpagecontroller
CreatingourAdd-Editview
WritingacustomfiltertoautogeneratetheURLfield
AddingtheWYSIWYGeditor
SettingupanInterceptortodetectresponses
BuildingthefrontendofourCMS
Buildingournavigationbardirective
Buildingtheadmin-logindirective
Displayingthecontentofapage
Settingthedefaulthomepage
Summary
8.ScalableArchitectureforDeploymentsonAWS
UnderstandingthevariousservicesinAmazonAWS
DelvingintoAWSdeploymentarchitectures
TheEC2server-basedarchitecture
TheServer-lessArchitecture
DeployingourappinaServer-lessArchitectureonAWS
MappingadomaintoS3
MappingtheS3buckettoaCloudFrontdistribution
Gettingyourappreadyforproductiondeployment
Improvingthepage-loadtimeofyourapp
SettingExpiresheaders
Performance
Summary
9.BuildinganE-CommerceStore
BackendasaService
BuildingaBaaSplatformonAWS
SettingupanS3Bucketwithpublicreadaccess
SettinguptheCORSpolicyonyourS3bucket
CreatingourDynamoDBtables
CreatingtheIdentityandAccessManagement(IAM)role
Creatingoure-commerceapp
BuildingnestedviewsusingUI-Router
MappingstatestoURL,views,andcontrollers
Prototypingourapplication
Settingupourindex.htmlfile
Creatingthecontrollers
Creatingtheproductpartials
Addinganimationstotheviewtransitions
AddingintheCSStransitioneffects
Creatingourapplication-levelcontroller
AddingaFacebooklogin
IntegratingAWSJSSDKwithourapplication
CreatingtheAWSserviceprovider
BuildingourAddProductspage
SavingdatainDynamoDBtables
Creatingtheviewfortheaddproductform
Buildingthecontrollerfortheaddproductsview
UploadingimagestoS3
Fetchingtheproductslistsforacategory
Usingresolvestopreloaddata
Creatingourproductdetailspage
Addingproductstocart
Thecheckoutpage
Savingtheorders
Summary
A.AngularJSResources
Officialresources
RecommendedAngularJSmodules
Boilerplates
Learningresources
GoodfriendswithAngularJS(third-partytoolsandservices)
Coreteammembersandknowledgeablepeopletofollow
Index
AngularJSWebApplicationDevelopmentBlueprints
AngularJSWebApplicationDevelopmentBlueprintsCopyright©2014PacktPublishing
Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.
Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthor,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.
PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.
Firstpublished:August2014
Productionreference:1180814
PublishedbyPacktPublishingLtd.
LiveryPlace
35LiveryStreet
BirminghamB32PB,UK.
ISBN978-1-78328-561-7
www.packtpub.com
CoverimagebyFaizFattohi()
http://www.packtpub.commailto:[email protected]
CreditsAuthor
VinciRufus
Reviewers
JeffCunningham
AshutoshDas
AJKerrigan
CiroNunes
YacineRezgui
CommissioningEditor
AkramHussain
AcquisitionEditor
RichardHarvey
ContentDevelopmentEditor
VaibhavPawar
TechnicalEditors
ShashankDesai
MenzaMathew
CopyEditors
KarunaNarayanan
AlfidaPaiva
LaxmiSubramanian
ProjectCoordinators
BinnyK.Babu
KrantiBerde
Proofreaders
BridgetBraund
PaulHindle
LucyRowland
Indexers
HemanginiBari
MariammalChettiyar
RekhaNair
PriyaSubramani
Graphics
ValentinaD’silva
ProductionCoordinator
AparnaBhagat
CoverWork
AparnaBhagat
AbouttheAuthorVinciRufushasbeenworkingwithfrontendtechnologiesforcloseto14yearsnow.HestartedhiscareerbuildinggameswithFlashActionScriptandlatermovedontoJavaScriptandHTML5.Duringhissparetime,heenjoysconductingworkshopsandtrainingpeople.
Foraliving,hementors,guides,andhelpsgrowthetechnologyteamatRazorfishNeev,primarilyintheareaofcommerce,usability,andemergingtechnologies.
AsincerethankstotheawesometeamatRazorfishNeev.I’velearnedsomuchworkingwithyouall.
Mydeepestregardstothetechnicalreviewers,JeffCunningham,AshutoshDas,AJKerrigan,CiroNunes,andYacineRezgui,andalsotothecontentdevelopmenteditor,VaibhavPawar,whoseinsightsandfeedbackgreatlyhelpedinaddingthefinishingtouchesforthisbook.
Abigthankyoutomyfamily;mydad,Rufus,wholearnedcomputersonlysothathecouldteachme;mymom,Anne,whohasalwaysencouragedmetotakeupchallengeseverytimeIthoughtitwasn’tpossible;myawesomekids,ShannonandJaden,whosacrificedalotoftheirplaytimesothatIcouldwritethisbook;mywife,Raina,forallthesupportthatwasinstrumentalinthisbookreachingitscompletion;andfinally,mysister,Blaisy,whowasalwaystheretogivefeedbackandcritiquemywork,andwithwhomIcouldbrainstormanddiscussideas.
AbouttheReviewersJeffCunninghamisamobileappdeveloperatComdatainNashville,TN.After15yearsofworkinginthefieldofJavawebdevelopment,henowenjoysthechallengesoffrontendandmobiledevelopment.Healsoreviewedthebook,AngularJSDirectives,PacktPublishing,andmaintainsthepopularreponamedAngularJS-LearningonGitHub(https://github.com/jmcunningham/AngularJS-Learning).
AshutoshDas,whohailsfromBangladesh,worksmainlyasabackenddeveloperandhisexperienceincludesworkingwithDjango,Node.js,Laravel,andsoon.HealsolikestoworkwithAngularJS.HespendshissparetimewritingforGitHub.Healsoworksasafreelancerandisapart-timejobholder.Heiscurrentlyintheprocessofreviewingthebook,AngularJSUIDevelopment,PacktPublishing.
AJKerriganisasystemsanalystwithasmallITdepartmentinNewJersey.Histechnicaldutiesandinterestsincludeserveranddatabaseadministration,command-linescripting,andwebdevelopment.
AngularJSWebApplicationDevelopmentBlueprints,PacktPublishing,representsAJ’sfirstexperienceasatechnicalreviewer.
Iwouldliketothankmywife,daughter,anddogfortheirlove,support,andendlesssupplyofhugs.Thankstomyfatheraswell,whoprovidedmewithmyfirstexposuretoprogramming(BASIConthefamilyTI-99/4acomputer).Hehasbeenaconsistentsourceofencouragementandguidance.
CiroNunesisa22-yearoldfrontendengineer,test-firstevangelist,andspecialistinlarge-scalearchitecturesforheavyclient-sideapplications.Atsuchayoungage,hehasbeenresponsibleforthedevelopmentofthebiggeste-commercewebsitesfromLatinAmerica.He’salsotheorganizeroftheAngularJSSPMeetupwhichhasmorethan400members.
Nowadays,he’sworkingonapplicationsforthefinancialmarketthatpushestheboundariesofAngularJS.
Iwanttothankmyfamilyandfriendsfortheirpatience,withmebeingsoabsentlately.IpromisethatI’mgoingtowalkmorewiththedogandspendmoretimewithyouwhomIlove.
YacineRezguiisaFrench-Tunisianwebdeveloper.Hestartedwebdevelopingattheageof12,andsincethen,hasmadehispassionhisjob.He’sspecializedinwebdevelopmentandstronglybelievesthatitisthebestcross-platformenvironment.He’scurrentlytheorganizeroftheLondonPhonegapMeetup.
HeworkedindifferentcompaniessuchasMédiamétrieeStat,TequilaRapido,andGovernorHubasafreelancer.
Iwouldliketothankmyfriends,JamesNocentini,JamesSharp,CédricFerretti,andXavierKressforsupportingmeonmywork,myfamilyforalltheirencouragement,andXuxuforhelpingmetofocus.
https://github.com/jmcunningham/AngularJS-Learning
www.PacktPub.com
Supportfiles,eBooks,discountoffers,andmoreYoumightwanttovisitwww.PacktPub.comforsupportfilesanddownloadsrelatedtoyourbook.
DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusatformoredetails.
Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.
http://PacktLib.PacktPub.com
DoyouneedinstantsolutionstoyourITquestions?PacktLibisPackt’sonlinedigitalbooklibrary.Here,youcanaccess,readandsearchacrossPackt’sentirelibraryofbooks.
http://www.PacktPub.comhttp://www.PacktPub.commailto:[email protected]://www.PacktPub.comhttp://PacktLib.PacktPub.com
Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,printandbookmarkcontentOndemandandaccessibleviawebbrowser
FreeaccessforPacktaccountholdersIfyouhaveanaccountwithPacktatwww.PacktPub.com,youcanusethistoaccessPacktLibtodayandviewnineentirelyfreebooks.Simplyuseyourlogincredentialsforimmediateaccess.
http://www.PacktPub.com
PrefaceThemostannoyingpartofusinganywebsiteorwebapplicationisthetimewewaitforpagestoload.Sure,everybodyisworkingonmakingtheWebfast,butthose2-3secondsthatittakesforaroundtriptotheserverdoesnotstopyoufromopeningmultipletabsandoftenforgettingwhichtabyouoriginallywereon.
TherapidpopularityofJavaScriptframeworksandtechnologiessuchasAJAXclearlyshowthedesperateneedtosavethose1or2,second-roundtripstotheserver,andprovidetheuserswithamoredesktop-likeuserexperience.
AboutJavaScriptMVCframeworksTheseJavaScriptframeworksaren’tsomenewrevolutionarytechnologyoranewdiscovery;theyareallstillusingthesameoldfaithfulJavaScript.TheseJavaScriptframeworksmerelyprovidealayerofabstraction(ifImay)oramoreModel-View-Controller-likearchitecture,sothatwecanbemoreproductivewhilebuildingappsanddon’treallyhavetoworryaboutmundanethings.
ThecreditfortherisingpopularityoftheseJavaScriptframeworkswouldgotothissurgeofJavaScript-basedhighlyinteractiveandrichInternetapplicationsthatnowadaysdosomuchmorethanjustdisplayingdatareceivedfromabackendserver.AllofthisispossiblethankstothemoderndaybrowserandtheirJavaScriptenginesthathavebecomefasterandpowerful.
TherehasnearlybeenanexplosionoftheseJavaScriptMVCframeworks,andeveryotherday,weseeanewframeworkbeinglaunched.WhilemostpeopleconsiderBackbone.jsorSproutCoretobeoneofthefirstJavaScriptframeworks,IwouldsayExtJSbySenchahasbeenamongthefirstJavaScriptframeworksandonethatisstillbeingextensivelyusedinthecorporateworldmainlytobuildfinanceapps.WhileBackbone.jsandSproutCorewerelaunchedin2010,Version2.0ofExtJSwaslaunchedtowardstheendof2007.
AngularJStoowaslaunchedsomewherein2010.Aroundthesametime,otherJavaScriptframeworksweresproutingup.However,itisprobablythefastestgrowingframeworkintermsofuseradoption,mainlyduetothe“wow”factorandalsothebackingfromthebigG.
Eachframeworkhasitsownprosandcons,andideallythechoiceoftheframeworkwoulddependonthenatureofyourproject.
Notehttp://www.todomvc.com/isaverynicesitetounderstandandcomparethefunctioningoftheseJavaScriptframeworks.
AngularJSiscurrentlythemostpopularJavaScriptMVCframework.Someofthereasonsforthiswouldbeasfollows:
It’samongthesimplesttolearnItfollowssomeofthebestsoftware-engineeringconcepts,andisidealtobuildlarge,scalableappsIthasarobusttestingframeworktorunUnittestsandEnd-to-Endtests,thusmakingiteasytowriteandrunautomatedtestcasesItalsoallowsforteamstoworkinparallelonasingleapplicationwithoutsteppingovereachother’sworkIthasthefastestgrowingcommunityofadaptors,andtheAngularJSGoogleGroupsandIRCchatsareagreatplacetointeractwithothers
http://www.todomvc.com/
HowAngularJSwasbornAngularJSstartedasaninternalGoogleprojectbyMiskoHevery,sometimein2009.Asthestorygoes,Misko’steamwasworkingonaprojectcalledGoogleFeedback;evenaftersixmonthsofdevelopmentandabout17,000linesofcode,theywerestillunhappywiththepaceofdevelopmentandtheinabilitytowriteautomatedtests.That’swhenMiskodecidedtorewritethat.Ittookhimabout3weeksandhemanagedtowritethewholethinginjustabout1,500linesofcode.
That’swhenAngularJSgotsomeseriousattentioninternallyatGoogle,andateamwasputtogethertohelpfurtherdevelopit.Around2010,GoogledecidedtodeclareitasopensourceundertheMITlicense.
TheideabehindthisbookTheideabehindwritingthisbookistoshowcasethedifferenttypesofapplicationsthatcanbebuiltonAngularJS.BesidesexplainingAngularJSandhowtowritemodularandtestablecode,thereisafairamountofemphasisonmakingthoseappslookbeautiful.So,bereadyforsomeCSSstuffanddesign-relateddiscussions.
I’vetriedtocoveravarietyofapplicationsrangingfromasimpleaddressbook,anHTML5mobileapp,ane-commercestore,aCMSframework,andalsoideasonhowtodeployappsonAmazonAWS.
WhatthisbookcoversThisbookisbrokendownintoninechapters.
Chapter1,IntroductiontoAngularJSandtheSinglePageApplication,talksabouttheconceptofaSinglePageAppandhowtheyaredifferentfromtheregularwebapps.We’llalsolearnaboutthebasicsofAngularJSbybuildingasimpleAddressBookApp.
Chapter2,SettingUpYourRig,talksabouthowhavingtherightsetoftoolscanbeahugeproductivitybooster.ItalsomakesyoufeellikeaprowhenbuildingyourAngularJSapp.ThischapterwilltalkaboutsomeofthetoolssuchasNode.js,ExpressJS,Grunt,Yeoman,andKarma.
Chapter3,RapidPrototypingwithAngularJS,talksabouttheeasewithwhichonecancreateclickableprototypestogetafeelofhowanapplicationwouldlookandfeelbeforeworkingonanybackendcode.
Chapter4,UsingRESTWebServicesinYourAngularJSApp,willshowyouhowtoconsumedatafromthird-partyRESTwebservicesusingfactoriesandthe$httpservice.
Chapter5,FacebookFriends’BirthdayReminderApp,willexplaindirectivesandhowwecancreateourFacebooklogindirective.Wewillalsosetupsomeautomatedteststoensureeverythingisworkingfine.
Chapter6,BuildinganExpenseManagerMobileApp,willwalkyouthroughtheprocessofbuildingaresponsiveandtouch-friendlymobileappusingngAnimateandHTML5featuressuchaslocalStorage.
Chapter7,BuildingaCMSontheMEANStack,talksabouthowtosetupanentirebackendandfrontendsystemandhowAngularJSinteractswithanodeserverandMongoDBdatabase.Wewillalsolookatsessionmanagementandinterceptors.
Chapter8,ScalableArchitectureforDeploymentsonAWS,willteachyouaboutAWSanditsvariousservices,andhowwecandeployourappinaServer-lessArchitecturethatcaninherentlyscale.
Chapter9,BuildinganE-CommerceStore,willshowyouhowtodirectlyreadandwritedatafromAWS’sDynamoDBdatabase,anduploadimagestoS3directlyfromourJavaScriptapp.
Appendix,AngularJSResources.Well,youknowwhattoexpecthere.
WhatyouneedforthisbookYouobviouslydon’tneedtoreadtheentirebookbeforeyoucanstartworkingonyourfirstAngularJSproject.I’mafirmbelieveroflearningthingsthepracticalway,andthat’swhyfromtheveryfirstchapter,youwillfindyourselffiringupyourIDE/Texteditor,andwritingcodeandtestingitonyourbrowser.
WhileyouwilllearnacoupleofnewfeaturesofAngularJSineachofthechapters,eachchapterisstillself-contained,andyoucancomfortablyjumptoanyofthechaptersthatinterestyouorthatyouneedtorefertoforyourproject.
However,ifyouarejuststartingoffwithAngularJS,thenIstronglyrecommendthatyoureadthroughthefirstthreechaptersbeforeyoustartjumping.
SoftwareversionsThecurrentstableversionofAngularJSwhilewritingthisbookis1.2,andunlessspecified,wewillbeusingthestableversionof1.2.17foralltheexamplesinthisbook.
YoucangetthelatestversionofAngularJSusinganyofthefollowingmethods:
Downloadthecompiledminifiedversionfromhttp://www.angularjs.org.ForkorclonethesourcecodefromtheGitHubURLhttps://github.com/angular/angular.js.TherecommendedoptionforbothdevelopmentandproductioncodeistocalltheAngularJSfiledirectlyfromtheGoogleCDN.ThelinktotheAngularJSsectionontheCDNishttps://developers.google.com/speed/libraries/devguide#angularjs.
http://www.angularjs.orghttps://github.com/angular/angular.jshttps://developers.google.com/speed/libraries/devguide#angularjs
CopyingthecodefilesThecodeexamplesmentionedinthisbookcanbeusedinyourprograms.However,ifyouchoosetoburnthemontoCDsforredistributionorareputtingupthecodeexamplesfordownloads,youarerequiredtogetexplicitpermissionfromPacktPublishing.
WhothisbookisforThisbookismainlyaimedatprofessionals,bothdesignersandprogrammers.Thankfully,AngularJSisevolvingtobeaframeworkwherebothdesignersandprogrammersworktogetherwithoutdiscriminatingeachotherasbackenddevelopersorfrontenddesigners.
ThebookobviouslyassumesthatyouknowyourbasicsinHTML,CSS,andJavaScript.Youunderstandtheimportanceandneedforwritingmodular,scalable,testable,andgood-lookingapplications.Youdon’tneedtohaveworkedwithAngularJSoranyotherJavaScriptframeworktounderstandthetopicscovered.ThebookassumesyoujustmetAngularJSonablinddate.
ThebookstartsoffwithgettingyoucomfortablewiththebasicconceptsthatyoucomeacrossveryoftenwhileworkingwithAngularJS.We’llwritesomesimplecodejusttoseehowAngularJSworks,understandingitbetter,andthenwe’llgraduatetowritingcleanerandmodularcode.
Also,Ihaveachapterdedicatedtosettingupyourdevelopment“rig”withasetoftoolsandpluginsthatwillhelpyouboostyourproductivitywhilebuildingAngularJSapps.
ConventionsInthisbook,youwillfindanumberofstylesoftextthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestyles,andanexplanationoftheirmeaning.
Codewordsintext,databasetablenames,foldernames,filenames,fileextensions,pathnames,dummyURLs,userinput,andTwitterhandlesareshownasfollows:“Now,angular-bootstrapwillbeavailableforuseacrossourapplication.”
Ablockofcodeissetasfollows:
Whenwewishtodrawyourattentiontoaparticularpartofacodeblock,therelevantlinesoritemsaresetinbold:
{{myName}}is{{2014-1968}}yearsold.
Anycommand-lineinputoroutputiswrittenasfollows:
yoangular:routesubscribers
Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,inmenusordialogboxesforexample,appearinthetextlikethis:“ClickontheDownloadbuttonandselectthefollowingoptionsfromthepop-upwindow:”
NoteWarningsorimportantnotesappearinaboxlikethis.
TipTipsandtricksappearlikethis.
ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook—whatyoulikedormayhavedisliked.Readerfeedbackisimportantforustodeveloptitlesthatyoureallygetthemostoutof.
Tosendusgeneralfeedback,simplysendane-mailto,andmentionthebooktitleviathesubjectofyourmessage.
Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideonwww.packtpub.com/authors.
mailto:[email protected]://www.packtpub.com/authors
CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.
DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesforallPacktbooksyouhavepurchasedfromyouraccountathttp://www.packtpub.com.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
http://www.packtpub.comhttp://www.packtpub.com/support
ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks—maybeamistakeinthetextorthecode—wewouldbegratefulifyouwouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheerratasubmissionformlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedonourwebsite,oraddedtoanylistofexistingerrata,undertheErratasectionofthattitle.Anyexistingerratacanbeviewedbyselectingyourtitlefromhttp://www.packtpub.com/support.
http://www.packtpub.com/submit-erratahttp://www.packtpub.com/support
PiracyPiracyofcopyrightmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.Ifyoucomeacrossanyillegalcopiesofourworks,inanyform,ontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.
Pleasecontactusatwithalinktothesuspectedpiratedmaterial.
Weappreciateyourhelpinprotectingourauthors,andourabilitytobringyouvaluablecontent.
mailto:[email protected]
QuestionsYoucancontactusatifyouarehavingaproblemwithanyaspectofthebook,andwewilldoourbesttoaddressit.
mailto:[email protected]
Chapter1.IntroductiontoAngularJSandtheSinglePageApplicationInthischapter,we’lllearnwhatSinglePageAppsareandhowtheydifferfromtheregularwebapplications.WewillalsolearnthefundamentalsofAngularJSandgoaboutbuildingasimpleAddressBookAppusingit.
Thelistoftopicstobecoveredinthechapterareasfollows:
WhatareSinglePageApps?AnatomyofanappModelsandviewsBuildinganAddressBookAppStylingtheappwithCSSAddingitemstotheAddressBook
DelvingintoSinglePageAppsBesidesotherthings,AngularJSisprimarilyusedtobuildSinglePageApps(SPAs),soletusfirstunderstanditscharacteristics.
SinglePageAppsareappsorwebsiteswhereintheentiresiteorappcontentloadswithinasinglepage.Thisessentiallymeansthatoncetheapporwebsiteisloadedinthebrowser,clickingonanylinkwouldnotreloadtheentirepagebutwouldsimplyupdatecertainsectionswithinthemainpageitself.Thisgivesusersaverydesktop-likefeelwhileusinganSPA.
AlthoughSPAshavebecomeverypopularnowadays,theconcepthasbeendiscussedasearlyas2003,andthetermSinglePageAppwascoinedin2005.
SomeofthetechnologiesthatplayapredominantroleinbuildingSPAsareHTML,CSS,JavaScript,AJAX,andwebservicesusuallyRESTful.Ofthese,JavaScriptplaysthemostcrucialroleinbuildinganSPA,soifyouhavebeenprocrastinatingonsharpeningyourJavaScriptskillsthiswouldbethebesttimetogetupandgetstarted.
OneofthefundamentaldifferencesinthewaySPAsworkagainstregularwebsitesisthewaythepagesarebuilt,whichtheusersees.Refertothefollowingdiagram:
Intraditionalwebapplicationsthatarebuiltontheserver-sidetechnologiessuchasJava,PHP,and.NET,wheneverapageisrequested,thewebserverwouldmakearequesttothedatabase,fetchtheresultofthequery,thenloadthetemplate,anddynamicallygeneratethefinalpage,whichissentdowntothebrowser.Asyoucanseehere,thewebserverisdoingalltheheavylifting,andasthetraffictotheserverincreases,thewebserverbecomesabottleneck.Thisiswhypopularhigh-trafficsitesneedalotofservers.
SinglePageApps,especiallythosebuiltonJavaScriptframeworkssuchasAngularJSworkinaslightlydifferentfashion.Refertothefollowingdiagram:
InanSPAarchitecture,theentiretemplatealongwiththeHTML,JavaScript,andCSSisdownloadedtotheuser’sbrowser,sowhenarequestismade,contentissentfromthewebserverandthepageisbuiltontheclientsideontheuser’sbrowser.Here,thebrowserisdoingtheheavylifting.Insuchanarchitecture,thewebserverismerelypassingrawdataandisnotinvolvedinbuildingthepages.Thepagesarebuiltoneachuser’sbrowserandhenceevenifthetraffictothesiteincreases,theserverdoesn’tgetoverloaded,asitwouldhaveinaregularwebapparchitecture.
AnotherthingthatmakesSPAswonderfulisthatthepresentationlayercanbecompletelydecoupledfromthebackendlayer.
AnatomyofasimpleAngularJSappPerformthefollowingsteps:
1. Tostart,let’sfirstdownloadaversionofAngularJSfromhttp:www.angularjs.org.2. ClickontheDownloadbuttonandselectthefollowingoptionsfromthepop-up
window:
Branch:SelectStableBuild:SelectMinified
3. DownloadtheJSfileandplaceitinyourproject’sfolder.
LetusstartbywritingasimpleAngularJSapp.Createanindex.htmlfilewiththefollowingcode:
AngularJSBasic
{{myName}}is{{2014-1968}}yearsold.
ThisisaregularHTMLpagewiththeHTML5doctypeandtheAngularJSJavaScriptfilebeingcalledin.Now,letuslookatspecificsyntaxesofAngularJSandwhattheymean.Thesyntaxesareasfollows:
ng-app:ThisdefinestheelementwithinwhichAngularJSwillbootstrapitself.Inmostcases,wewouldaddittotheortag.ItisalsopossibleyouwouldbebuildingaregularapplicationinJava,PHP,or.NETandonlyasectionofitwouldberunninganAngularJSapp,insuchcasesyouwouldaddng-apptothetagwrappingtheappcomponent.ng-init:Thisisusedtodefinetheinitializationtasks.Inthisexample,wearecreatingamodelcalledmyNamewiththevalueJohnDoe.
NoteUsingng-initisnotrecommendedforproductionapps.Aswewillseelaterinthischapter,theidealwaytoinitializethevariablewouldbeinthecontrollerinsteadofdirectlywritingitintheview.
{{}}:Thedoublecurlybracketsareusedtooutputthedatastoredinmodels.Inthiscase,{{myName}}outputsthevalueJohnDoe.Thesecurlybracketscanalsobeusedforexpressions,asintheexample{{2014-1968}}outputstheresult46.ThisisverysimilartohowothertemplatingenginessuchasMustacheorSmartywork.Directives:Theng-appandtheng-inittagsthatyouseeintheprecedingsample
http://www.angularjs.org
codearecalledDirectives.TheyareanintegralpartofanyAngularJSappanditisthroughthesedirectivesthatAngularJSisabletomodifytheDOMelementofanapplication.AngularJScomeswithawholesetofpredefineddirectivesmanyofwhichwewilluseaswegothroughthisbook.ThegoodthingaboutAngularJSisthatyoucanalsocreateyourowncustomdirectivesthatcanmeetyourspecificrequirements.
ModelsandviewsInAngularJS,amodelcouldbeaprimitive,ahashtable,oraJavaScriptobject.Thedatafromthemodelcanbedisplayedintheviewusingthe{{}}expression.
Modelscanbedefinedinmultipleways.Likewesawinthefirstexample,wecandefinethemodelwithintheng-initdirective.Itcanbecreatedinthetemplatewithintheexpressionasfollows:
click
Alternatively,itcouldalsobecreatedwithinacontrollerusingthescope,whichistheidealwaytodoit.Refertothefollowingcode:
ModelinScope
{{person.name}}livesin{{person.city}}functionPeopleController($scope){$scope.person={name:"JohnDoe",city:"NewYork"}}
Intheprecedingexample,wecreatedacontrollercalledPeopleControlleranddefinedthemodelperson,whichisstoringthedataasahashtable.The$scopeisanAngularJSobjectthatisabletoreferencetheJavaScriptobjectmodelasaproperty.
BuildinganAddressBookAppIntheearlierexamples,wesawthedifferentwaysofcreatingmodels.Whencreatingproductiongradeorlarge-scaleapplications,whichinvolvegraphicalinterfaces,itiscompulsorytofollowtheModelViewController(MVC)designpattern.
Buildingonthepreviouscodeexample,we’llgoaheadandbuildasimpleAddressBookApp.
Let’sstartbycreatingourmodelsinacontrollercalledPeopleController.We’llnowwriteallourJavaScriptsinafilecalledscripts.js.Yourscripts.jsfileshouldlooklikethis:
functionPeopleController($scope){$scope.people=[{name:"JohnDoe",phone:"3452345678",city:"NewYork"},{name:"SarahParker",phone:"1236548769",city:"Chicago"},{name:"LittleJohn",phone:"4567853432",city:"LosAngeles"},{name:"AdamDoe",phone:"9025673152",city:"LasVegas"}];}
HerewearedefiningthecontrollercalledPeopleControllerandcreatingourmodelcalledpeople.Themodelcontainsthreeattributes:name,phone,andcity.
Now,letusgetourmarkupinplace.Letuscallthefileindex.htmlusingthefollowingcode:
AddressBookAddressBook{{person.name}}-{{person.phone}}{{person.city}}
TipItisalwaysagoodpracticetoloadyourJSfilesattheendofthepagejustabovethebodytagandnotinthehead.Youcanreadmoreaboutwhythismattershereathttps://developer.yahoo.com/performance/rules.html.
https://developer.yahoo.com/performance/rules.html
Asyoucanseehere,wearedefiningtheHTML5doctypeinthefirstline,andthenweinitializetheAngularJSapplicationbyusingtheng-appdirective.You’llalsonoticethatweareusingtheng-controllerdirectiveandassigningPeopleControllertoit.Bydoingso,wearedefiningthesectionoftheDOMthatisnowwithinthescopeofthiscontroller.
You’llalsonoticeanewdirectivecalledng-repeat;thisisthebuilt-indirectiveusedtodisplayalistofitemsfromacollection.Theng-repeatdirectivewouldsimplyduplicatetheDOMelementandbindthedefinedpropertiesofthedataobject.
Asyoucansee,ng-repeatmakesitsoeasyandcleantodisplayrecordsetsascomparedtodoingthisinjQueryorplainvanillaJavaScript.
Now,runyourindex.htmlinthebrowserandyoushouldbeseeingthenameswiththeirphonenumbersandcitiesbeingdisplayed.Thedatafromourmodelisshowingup,whichisgood.LetusalsoinspectthecodetohavealookatthechangesAngularJSismakingtoourmarkup.
Allmodernbrowsersallowyoutoinspectthesource.Andinmostcasesyoucansimplyright-clickonthepageandselectInspectElement.IncaseyouarenotcomfortablewithInspect,youcanalsodoViewSource.Refertothefollowingscreenshot:
TipBytheway,hereI’musingFirebug,anawesomeadd-onforMozillaFirefox.
Asyoulookthroughthecode,you’llnoticethatAngularJSismakingafairbitofchangetothemarkup.
Thefirstthingyou’llnoticeisthatAngularJSaddsaclasscalledng-scopetoeveryDOMelementwherethescopeisinitialized(wewillgettowhatascopeis,injustabit).ItduplicatestheentireDOMpresentwithintheng-repeatdirective.Itisalsoaddingaclasscalledng-bindingtoeveryelementwherethedataisbound.
AngularJSwilladddifferentCSSclassesdependingonthedirectivebeingused.Thesecancomeinhandywhenyouwanttostyle,forexample,thevalidationmessageswhileworkingwithforms.We’llseemoreaboutthisinthechaptersahead.
UnderstandingthescopeinAngularJSLetusnowlookatthisthingcalledthescope.Asyoumighthavenoticed,wedefinedourpeoplecontrollerwitha$scopeparameter.Wealsohadtodefineourpeoplemodelasapartofthisscope.Whileinspectingtheelements,wealsonoticedmultipleng-scopeclassesbeingdefined.So,whatexactlyisthisscopeandisitreallythatimportant?
AsperAngularJS’sdocuments,thescopeobjectreferstotheapplicationmodelandprovidesanexecutioncontextfortheexpressionsintheviews.
Theexpression{{person.name}}isabletodisplaythecontentonlybecausethenameisapropertythatcanbeaccessedbythescope.
AnotherimportantthingtonoteisthateveryAngularJSappwillhavearootscopecreatedattheng-appdirective.Manyotherdirectivescouldalsocreatetheirownscope.ScopesarearrangedinahierarchicalfashionfollowingtheDOMstructureofthepage.ChildScopesprototypicallyinheritfromtheirparentscope.
Theexceptiontothisisincaseswhereadirectiveusesascopeoption,itcreatesanisolatedscope.MoreinformationaboutthedirectivesandisolatedscopeisavailableinChapter5,FacebookFriends’BirthdayReminderApp.
We’llgetabetterunderstandingofitasweseeotherexamples.
StylingtheappNow,letusstyletheapplicationtomakeitlookalittlebetter.We’llgobacktoourindex.htmlandaddafewCSSclassesasfollows:
AddressBook
AddressBook
padding:10px;
}.contact-item{border-bottom:thinsolid#ccc;padding:10px;}
AsyoucanseefromtheCSSstyles,wefirststylethebodytogiveitalightgraybackgroundcolorusingthe#ccc(#cccistheshortcodefor#cccccc)hexcode.
TheH1headingtagisstyledtoaligncenter,withadarkgraytextcolorandatextshadow.Thestylingfor.nameand.cityisstraightforward.Now,letuslookatthestylesfor.wrapperusingthefollowingcode:
.wrapper{width:650px;margin:0auto;box-shadow:5px5px5px#555;background:#fff;border-radius:15px;padding:10px;
}
Here,wearesettingwidthofthedivto650px.Themarginwith0autoisusedtoplacethedivtothecenterofthescreenirrespectiveofthescreenresolution.
TipDownloadingtheexamplecode
YoucandownloadtheexamplecodefilesforallPacktbooksyouhavepurchasedfromyouraccountathttp://www.packtpub.com.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
Nowtomakeitlookalittlebetter,we’llgiveitabox-shadowandborderradius.Thefollowingdiagramexplainswhattheoptionsoftheborderradiusmean:
Forthe.contact-itemlist,wegiveaborder-bottomandsomepaddingsothatthingsstayalittlespacedout.
http://www.packtpub.comhttp://www.packtpub.com/support
WithallthisCSSinplace,yourappshouldbelookinglikethis:
SortingthecontactsalphabeticallyThislooksnice,butitwouldbeagoodideatohavethenamessortedalphabetically.Forthis,wewilluseAngularJS’sbuilt-infiltercalledorderBy.
InAngularJS,filtersareusedtoformatthedata.OnecanuseAngularJS’spredefinedfiltersorcreateyourown.We’lllearnmoreaboutfilterslaterinthisbook.
Allweneedtodoismodifythefollowingsectionoftheindex.htmlasfollows:
{{person.name}}-{{person.phone}}{{person.city}}
RefreshyourIndex.htmlinthebrowserandyoushouldnoticethenamesarenowsortedalphabetically.
AddingcontactstotheAddressBookNowthatwehaveourAddressBookdisplayingourcontactsnicely,let’snowcreateaformtoaddcontacts.
LetusaddthemarkupfortheAddaContactformintheindex.htmlfilewithinthebodytagasfollows:
AddaContactName:Phone:City:Save
Theprecedingcodeisratherstraightforward.Wecreateanewdivandreusethewrapperclasstostyleit.
Weareaddingthethreetextboxesforthename,phone,andcityattributes.WebindthesethreetextboxestoamodelobjectcallednewPersonasfollows:
ng-model='newPerson.name'ng-model='newPerson.phone'ng-model='newPerson.city’
WearealsoaddingabuttoncalledSaveandusingtheng-clickdirectivethatwillcalltheSave()functionwhenthebuttonisclicked.
Now,letuslookattheJavaScriptcodethatwewillbewritinginourscripts.jsfile:
$scope.Save=function(){$scope.people.push({name:$scope.newPerson.name,phone:$scope.newPerson.phone,city:$scope.newPerson.city});}
TipSincetheSave()functionisaccessingthescopewithinthePeopleControllerfunction,itisimperativethattheSave()functioniswrittenwithinthePeopleControllerfunctioninthescripts.jsfile.
Inthe$scope.Savefunction,wesimplycapturethevaluesfromtheinputboxesandpushthisintoourmainpeoplemodel.
Letusnowrefreshourindex.htmlandtryitout.FilluptheformandsaveitandyouwillimmediatelyseeitgetaddedtotheAddressBook.ThishappensthankstooneofthemanycoolfeaturesofAngularJScalledtwo-waydatabinding.
Theng-showandng-hidedirectivesWhiletheappisgoodasitis,maybeit’sagoodideatohaveabuttoncalledAddContactanddisplaytheAddContactformonlywhenthatbuttonisclicked.
LetusmakeuseofAngularJS’sng-showandng-hidedirectivestocontrolthevisibilityofourAddContactform.
Thewaytheyworkisverystraightforward.Iftheattributeng-show='true',thenthedivisvisibleandviceversa.Apointtonoteisthatng-showandng-hidemerelycontrolthevisibilityoftheDOMelement.
Let’saddourbuttoncalledAddContactandsetuptheng-showandng-hidedirectivessuchthatwhenyouclickonAddContact,theformshowsupandatthesametimethisbuttondisappears.AndwhentheSavebuttonisclicked,theformishiddenandtheAddContactbuttonshowsupagain.
Let’smodifyourindex.htmlasfollows:
AddContactAddaContactName:Phone:City:Save
Wesetthebuttontong-hide='formVisibility'becausewhenthevalueofformVisibilitybecomestrue,itwillhidethebutton.Similarly,ng-show=formVisibilitywillmaketheAddContactformdisplaywhenthevalueofformVisibilityistrue.
Now,let’saddthepieceofJavaScripttosettheformVisibilityvalues.Addthefollowingcodetoyourscripts.jsfileasfollows:
$scope.ShowForm=function(){$scope.formVisibility=true;}
TipMakesurethisnewfunctioniswrittenwithinthemainPeopleControllerfunction.
Wewillalsoaddonelineinourexisting$scope.SavefunctiontosetthevalueofformVisibilitytofalse.
Pleaseupdatethe$scope.Save()functionashighlightedinthefollowingcode:
$scope.Save=function(){
$scope.people.push({name:$scope.newPerson.name,
phone:$scope.newPerson.phone,city:$scope.newPerson.city});$scope.formVisibility=false;
}
Reloadyourindex.htmlandseethebuttonsinaction.
Ohandjustbecausewedon’tlikethewaythosedefaultbuttonslook,letsaddalittlebitofstyletoit.
AddthefollowingCSSclassestoyourstyles.cssfile:
button{background:#080;color:#fff;padding:5px15px;border-radius:5px;border:thinsolid#060;"margin:5pxauto;"}button:hover{background:#0A0;}
Whatwearesimplydoinghereissettingadarkgreencolorbackgroundforthebutton,givingthetextawhitecolor,andgivingitsomepaddingfivepixelsfromthetop-andbottom-sideand15pixelsfromtheleft-handsideandright-handsideandaddingsomeborderradius.
Thebutton:hoverisalightgreenbackgroundcolorjusttoshowthehighlightwhentheuserhoversthecursoroverthebutton.
Reloadyourindex.htmlpageandwehaveourveryfirstworkingandreasonablygood-lookingAddressBookApplication.
SummaryThisconcludesourfirstchapter.Toquicklysummarize,wewentaboutbuildingourAddressBookAppandindoingsolearnedaboutthevariousAngularJSdirectivessuchasng-appandng-repeat.Wesawhowtwo-waydatabindingsandexpressionsworkandtheimportanceofscope.Wealsosawhowwecanhideandshowcertainelementsusingtheng-showandng-hidedirectives.Lastbutnotleast,weusedsomesimpleandeasyCSS3featurestostyleourapp.
Inthenextchapter,wewillseethevarioustoolsthatfrontenddevelopersshouldideallyhaveintheirtoolboxandhowtogoaboutusingthem.
Chapter2.SettingUpYourRigI’msureyouwouldhaveheardthesaying,“Atoolmanisknownbythetoolshekeeps.”OKfine,Ijustmadethatup,butthat’sactuallytrue,especiallywhenitcomestoprogramming.SureyoucanbuildcompleteandfullyfunctionalAngularJSappsjustusingasimpletexteditorandabrowser,butifyouwanttoworklikeaninja,thenmakesurethatyoustartusingsomeofthesetoolsasapartofyourdevelopmentworkflow.
DonotethatthesetoolsarenotmandatorytobuildAngularJSapps.Theiruseisrecommendedmainlytohelpimprovetheproductivity.
Inthischapter,wewillseehowtosetupandusethefollowingproductivitytools:
Node.jsGruntYeomanKarmaProtractor
SincemostofusarerunningaMac,Windows,Ubuntu,oranotherflavoroftheLinuxoperatingsystem,we’llbecoveringthedeploymentstepscommonforallofthem.
SettingupNode.jsDependingonyourtechnologystack,IstronglyrecommendyouhaveeitherRubyorNode.jsinstalled.
IncaseofAngularJS,mostoftheproductivitytoolsorpluginsareavailableasNodePackageManager(npm),and,hence,wewillbesettingupNode.jsalongwithnpm.Node.jsisanopensourceJavaScript-basedplatformthatusesanevent-basedInput/outputmodel,makingitlightweightandfast.
Letusheadovertowww.nodejs.organdinstallNode.js.Choosetherightversionasperyouroperatingsystem.
ThecurrentversionofNode.jsatthetimeofwritingthisbookisv0.10.xwhichcomeswithnpmbuiltin,makingitabreezetosetupNode.jsandnpm.
TipNode.jsdoesn’tcomewithaGraphicalUserInterface(GUI),sotouseNode.js,youwillneedtoopenupyourterminalandstartfiringsomecommands.NowwouldalsobeagoodtimetobrushuponyourDOSandUnix/Linuxcommands.
AfterinstallingNode.js,thefirstthingyou’dwanttocheckistoseeifNode.jshasbeeninstalledcorrectly.
So,letusopenuptheterminalandwritethefollowingcommand:
node–-version
ThisshouldoutputtheversionnumberofNode.jsthat’sinstalledonyoursystem.Thenextwouldbetoseewhatversionofnpmwehaveinstalled.Thecommandforthatwouldbeasfollows:
npm–-version
Thiswilltellyoutheversionnumberforyournpm.
http://www.nodejs.org
CreatingasimpleNode.jswebserverwithExpressJSForbasic,simpleAngularJSapps,youdon’treallyneedawebserver.YoucansimplyopentheHTMLfilesfromyourfilesystemandtheywouldworkjustfine.However,asyoustartbuildingcomplexapplicationswhereyouarepassingdatainJSON,webservices,orusingaContentDeliveryNetwork(CDN),youwouldfindtheneedtouseawebserver.
ThegoodthingaboutAngularJSappsisthattheycouldworkwithinanywebserver,soifyoualreadyhaveIIS,Apache,Nginx,oranyotherwebserverrunningonyourdevelopmentenvironment,youcansimplyrunyourAngularJSprojectfromwithinthewebrootfolder.
Incaseyoudon’thaveawebserverandarelookingforalightweightwebserver,thenletussetoneupusingNode.jsandExpressJS.
OnecouldwritetheentirewebserverinpureNode.js;however,ExpressJSprovidesanicelayerofabstractionontopofNode.jssothatyoucanjustworkwiththeExpressJSAPIsanddon’thavetoworryaboutthelow-levelcalls.
So,let’sfirstinstalltheExpressJSmoduleforNode.js.
Openupyourterminalandfirethefollowingcommand:
npminstall-gexpress-generator
ThiswillgloballyinstallExpressJS.Omitthe–gtoinstallExpressJSlocallyinthecurrentfolder.
WheninstallingExpressJSgloballyonLinuxorMac,youwillneedtorunitviasudoasfollows:
sudonpminstall–gexpress-generator
Thiswillletnpmhavethenecessarypermissionstowritetotheprotectedlocalfolderundertheuser.ThenextstepistocreateanExpressJSapp;letuscallitmy-server.Typethefollowingcommandintheterminalandhitenter:
expressmy-server
You’llseesomethinglikethis:
create:my-servercreate:my-server/package.jsoncreate:my-server/app.jscreate:my-server/publiccreate:my-server/public/javascriptscreate:my-server/public/imagescreate:my-server/public/stylesheetscreate:my-server/public/stylesheets/style.csscreate:my-server/routescreate:my-server/routes/index.js
create:my-server/routes/user.jscreate:my-server/viewscreate:my-server/views/layout.jadecreate:my-server/views/index.jade
installdependencies:$cdmy-server&&npminstall
runtheapp:$DEBUG=my-server./bin/www
Thiswillcreateafoldercalledmy-serverandputinabunchoffilesinsidethefolder.
NoteThepackage.jsonfileiscreated,whichcontainstheskeletonofyourapp.Openitandensurethenamesaysmy-server;also,notethedependencieslisted.
Now,toinstallExpressJSalongwiththedependencies,firstchangeintothemy-serverdirectoryandrunthefollowingcommandintheterminal:
cdmy-servernpminstall
Now,intheterminal,typeinthefollowingcommand:
npmstart
Openyourbrowserandtypehttp://localhost:3000intheaddressbar.You’llgetaniceExpressJSwelcomemessage.NowtotestourAddressBookAppcreatedinChapter1,IntroductiontoAngularJSandtheSinglePageApplication,wewillcopyourindex.html,scripts.js,andstyles.cssintothepublicfolderlocatedwithinmy-server.
NoteI’mnotcopyingtheangular.jsfilebecausewe’llusetheCDNversionoftheAngularJSlibrary.
Openuptheindex.htmlfileandreplacethefollowingcode:
WiththeCDNversionofAngularJSasfollows:
Aquestionmightarise,astowhatiftheCDNisunreachable.Insuchcases,wecanaddafallbacktousealocalversionoftheAngularJSlibrary.
WedothisbyaddingthefollowingscriptaftertheCDNlinkiscalled:
window.angular||document.write('');
Savethefileinthebrowserandenterlocalhost:3000/index.html.YourAddressBook
isnowrunningfromaserverandtakingadvantageofGoogle’sCDNtoservetheAngularJSfile.
TipReferencingthefilesusingonly//isalsocalledtheprotocolindependentabsolutepath.Thismeansthatthefilesarerequestedusingthesameprotocolthatisbeingusedtocalltheparentpage.Forexample,ifthepageyouareloadingisviahttps://,thentheCDNlinkwillalsobecalledviaHTTPS.
Thisalsomeansthatwhenusing//insteadofhttp://duringdevelopment,youwillneedtorunyourappfromwithinaserverinsteadofafilesystem.
SettingupGruntGruntisaJavaScript-basedtaskrunner.Itisprimarilyusedforautomatingtaskssuchasrunningunittests,concatenating,merging,andminifyingJSandCSSfiles.Youcanalsorunshellcommands.Thismakesitsupereasytoperformservercleanupsanddeploycode.Essentially,GruntistoJavaScriptwhatRakewouldbetoRubyorAnt/MavenwouldbetoJava.
InstallingGrunt-cliInstallingGrunt-cliisslightlydifferentfrominstallingotherNode.jsmodules.WefirstneedtoinstalltheGrunt’sCommandLineInterface(CLI)byfiringthefollowingcommandintheterminal:
npminstall-ggrunt-cli
MacorLinuxuserscanalsodirectlyrunthefollowingcommand:
sudonpminstall–ggrunt-cli
Makesureyouhaveadministrativeprivileges.UsesudoifyouareonaMacorLinuxsystem.IfyouareonWindows,right-clickandopenthecommandpromptwithadministrativerights.AnimportantthingtonoteisthatinstallingGrunt-clidoesn’tautomaticallyinstallGruntanditsdependencies.
Grunt-climerelyinvokestheversionofGruntinstalledalongwiththeGruntfile.Whilethismayseemalittlecomplicatedatstart,thereasonitworksthiswayissothatwecanrundifferentversionsofGruntfromthesamemachine.ThiscomesinhandywhenyourprojecthasdependenciesonaspecificversionofGrunt.
Creatingthepackage.jsonfileToinstallGruntfirst,let’screateafoldercalledmy-projectandcreateafilecalledpackage.jsonwiththefollowingcontent:
{"name":"My-Project","version":"0.1.0","devDependencies":{"grunt":"~0.4.5","grunt-contrib-jshint":"~0.10.0","grunt-contrib-concat":"~0.4.0","grunt-contrib-uglify":"~0.5.0","grunt-shell":"~0.7.0"
}}
Savethefile.Thepackage.jsoniswhereyoudefinethevariousparametersofyourapp;forexample,thenameofyourapp,theversionnumber,andthelistofdependenciesneededfortheapp.
HerewearecallingourappMy-ProjectwithVersion0.1.0,andlistingoutthefollowingdependenciesthatneedtobeinstalledasapartofthisapp:
grunt(v0.4.5):ThisisthemainGruntapplicationgrunt-contrib-jshint(v0.10.0):Thisisusedforcodeanalysisgrunt-contrib-concat(v0.4.0):Thisisusedtomergetwoormorefilesintoonegrunt-contrib-uglify(v0.5.0):ThisisusedtominifytheJSfilegrunt-shell(v0.7.0):ThisistheGruntshellusedforrunningshellcommands
Visithttp://gruntjs.com/pluginstogetalistofallthepluginsavailableforGruntandalsotheirexactnamesandversionnumbers.
NoteYoumayalsochoosetocreateadefaultpackage.jsonfilebyrunningthefollowingcommandandansweringthequestions:
npminit
Openthepackage.jsonfileandaddthedependenciesasmentionedearlier.
Nowthatwehavethepackage.jsonfile,loadtheterminalandnavigateintothemy-projectfolder.ToinstallGruntandthemodulesspecifiedinthefile,typeinthefollowingcommand:
npminstall--save-dev
You’llseeaseriesoflinesgettingprintedintheconsole,letthatcontinueforawhileandwaituntilitreturnstothecommandprompt.EnsurethatthelastlineprintedbythepreviouscommandendswithOKcode0.
OnceGruntisinstalled,aquickversioncheckcommandwillensurethatGruntis
http://gruntjs.com/plugins
installed.Thecommandisasfollows:
grunt–-version
Thereisapossibilitythatyougotabunchoferrorsanditendedwithanotokcode0message.Therecouldbemultiplereasonswhythatwouldhavehappened,rangingfromerrorsinyourcodetoanetworkconnectionissueorsomethingchangingatGrunt’sendduetoanewversionupdate.
Ifgrunt--versionthrowsupanerror,itmeansGruntwasn’tinstalledproperly.ToreinstallGrunt,enterthefollowingcommandsintheterminal:
rm–rfnode_modulesnpmcachecleannpminstall
Windowsusersmaymanuallydeletethenode_modulesfolderfromWindowsExplorer,beforerunningthecachecleancommandinthecommandprompt.
TipRefertohttp://www.gruntjs.comtotroubleshoottheproblem.
http://www.gruntjs.com
CreatingyourGrunttasksTorunourGrunttasks,we’llneedaJavaScriptfile.So,let’scopyourscritps.jsfromthepreviouschapterandplaceitintothemy-projectsfolder.
ThenextstepistocreateaGruntfilethatwilllistoutthetasksthatweneedGrunttoperform.
Fornow,wewillaskittodofoursimpletasks,firstcheckifourJScodeiscleanusingJSHint,thenwewillmergethreeJSfilesintooneandthenminifytheJSfile,andfinallywewillrunsomeshellcommandstocleanup.
NoteUntilVersion0.3,theinitcommandwasapartoftheGrunttoolandonecouldcreateablankprojectusinggrunt-init.WithVersion0.4,initisnowavailableasaseparatetoolcalledgrunt-initandneedstobeinstalledusingthenpminstall–ggrunt-initcommandline.Alsonotethatthestructureofthegrunt.jsfilefromVersion0.4onwardsisfairlydifferentfromtheearlierversionsyou’veused.
Fornow,wewillresorttocreatingtheGruntfilemanually.Refertothefollowingscreenshot:
Inthesamelocationaswhereyouhaveyourpackage.json,createafilecalledgruntfile.jsasshownearlierandtypeinthefollowingcode:
module.exports=function(grunt){//Projectconfiguration.grunt.initConfig({jshint:{all:['scripts.js']}});
grunt.loadNpmTasks('grunt-contrib-jshint');
//Defaulttask.grunt.registerTask('default',['jshint']);};
Tostart,wewilladdonlyonetaskwhichisjshintandspecifyscripts.jsinthelistoffilesthatneedtobelinted.Inthenextline,wespecifygrunt-contrib-jshintasthenpmtaskthatneedstobeloaded.Inthelastline,wedefinethejshintasthetasktoberunwhenGruntisrunningindefaultmode.Savethefileandintheterminalrunthefollowingcommand:
grunt
Youwouldprobablygettoseethefollowingmessageintheterminal:
SoJSHintissayingthatwearemissingasemicolononlines18and24.Oh!DidImentionthatJSHintislikeyourverystrictmathteacherfromhighschool.
Let’sopenupscripts.jsandputinthosesemicolonsandrerunGrunt.Nowyoushouldgetamessageingreensaying1filelintfree.Donewithouterrors.
Let’saddsomemoretaskstoGrunt.We’llnowaskittoconcatenateandminifyacoupleofJSfiles.Sincewecurrentlyhavejustonefile,let’sgoandcreatetwodummyJSfilescalledscripts1.jsandscripts2.js.
Inscripts1.jswe’llsimplywriteanemptyfunctionasfollows:
//Thisisfromscript1functionScript1Function(){//------//}
Similarly,inscripts2.jswe’llwritethefollowing:
//Thisisfromscript2functionScript2Function(){//------//}
Savethesefilesinthesamefolderwhereyouhavescripts.js.
GrunttaskstomergeandconcatenatefilesNow,let’sopenourGruntfileandaddthecodeforboththetasks—tomergetheJSfile,andminifythemasfollows:
module.exports=function(grunt){//Projectconfiguration.grunt.initConfig({jshint:{all:['scripts.js']},concat:{dist:{src:['scripts.js','scripts1.js','scripts2.js'],dest:'merged.js'}},
uglify:{dist:{src:'merged.js',dest:'build/merged.min.js'}}});
grunt.loadNpmTasks('grunt-contrib-jshint');grunt.loadNpmTasks('grunt-contrib-concat');grunt.loadNpmTasks('grunt-contrib-uglify');
//Defaulttask.grunt.registerTask('default',['jshint','concat','uglify']);};
Asyoucanseefromtheprecedingcode,afterthejshinttask,weaddedtheconcattask.Underthesrcattribute,wedefinethefilesseparatedbyacommathatneedtobeconcatenated.Andinthedestattribute,wespecifythenameofthemergedJSfile.
TipItisveryimportantthatthefilesareenteredinthesamesequenceastheyneedtobemerged.Ifthesequenceofthefilesenteredisincorrect,themergedJSfilewillcauseerrorsinyourapp.
TheuglifytaskisusedtominifytheJSfileandthestructureisverysimilartotheconcattask.Weaddthemerged.jsfiletothesrcattributeandinthedestattribute,wewillplacethemerged.min.jsfileintoafoldercalledbuild.
Note
Gruntwillautocreatethebuildfolder.
Afterdefiningthetasks,wewillloadthenecessaryplugins,namelythegrunt-contrib-concatandthegrunt-contrib-uglify,andfinallywewillregistertheconcatanduglifytaskstothedefaulttask.
SavethefileandrunGrunt.Andifallgoeswell,youshouldseeGruntrunningthesetasksandinformingthestatusofeachofthetasks.
Ifyougetthefinalmessagesaying,Done,withoutanyerrors,itmeansthingswentwell,andthiswasyourluckyday!
Ifyounowopenyourmy-projectfolderinthefilemanager,youshouldseeanewfilecalledmerged.js.Openitinthetexteditorandyou’llnoticethatallthethreefileshavebeenmergedintothis.Also,gointothebuild/merged.min.jsfileandverifywhetherthefileisminified.
RunningshellcommandsviaGruntAnotherreallyhelpfulplugininGruntisgrunt-shell.Thisallowsustoeffectivelyrunclean-upactivitiessuchasdeleting.tmpfilesandmovingfilesfromonefoldertoanother.
Let’sseehowtoaddtheshelltaskstoourGruntfile.AddthefollowinghighlightedpieceofcodetoyourGruntfile:
module.exports=function(grunt){//Projectconfiguration.grunt.initConfig({jshint:{all:['scripts.js']},concat:{dist:{src:['scripts.js','scripts1.js','scripts2.js'],dest:'merged.js'}},
uglify:{dist:{src:'merged.js',dest:'build/merged.min.js'}},
shell:{multiple:{command:['rm-rfmerged.js','mkdirdeploy','mvbuild/merged.min.jsdeploy/merged.min.js'].join('&&')}}});
grunt.loadNpmTasks('grunt-contrib-jshint');grunt.loadNpmTasks('grunt-contrib-concat');grunt.loadNpmTasks('grunt-contrib-uglify');grunt.loadNpmTasks('grunt-shell');//Defaulttask.grunt.registerTask('default',['jshint','concat','uglify','shell']);};
Asyoucanseefromthecodeweadded,wearefirstdeletingthemerged.jsfile,thencreatinganewfoldercalleddeployandmovingourmerged.min.jsfileintoit.WindowsuserswouldneedtousetheappropriateDOScommandsfordeletingandcopyingthe
files.
Notethat.join('&&')isusedwhenyouwantGrunttorunmultipleshellcommands.Thenextstepsaretoloadthenpmtasksandaddshelltothedefaulttasklist.ToseeGruntperformallthesetasks,runtheGruntcommandintheterminal.
Onceit’sdone,openupthefilesystemandverifywhetherGrunthasdonewhatyouhadaskedittodo.Justlikeweusedtheprecedingfourplugins,therearenumerousotherpluginsthatyoucanusewithGrunttoautomateyourtasks.
ApointtonoteiswhilethedefaultGruntcommandwillrunallthetasksmentionedinthegrunt.registerTaskstatement,ifyouwouldneedtorunaspecifictaskinsteadofallofthem,thenyoucansimplytypethefollowinginthecommandline:
gruntjshint
Alternatively,youcantypethefollowingcommand:
gruntconcat
Alternatively,youcantypethefollowingcommand:
gruntugligy
Attimesifyou’dliketorunjusttwoofthethreetasks,thenyoucanregisterthemseparatelyasanotherbundledtaskintheGruntfile.Openupthegruntfile.jsfile,andjustafterthelinewhereyouhaveregisteredthedefaulttask,addthefollowingcode:
grunt.registerTask('concat-min',['concat','uglify']);
Thiswillregisteranewtaskcalledconcat-minandwillrunonlytheconcatanduglifytasks.
Intheterminalrunthefollowingcommand:
gruntconcat-min
VerifywhetherGruntonlyconcatenatedandminifiedthefileanddidn’trunJSHintoryourshellcommands.
TipYoucanrungrunt--helptoseealistofallthetasksavailableinyourGruntfile.
Yeoman–theworkflowtoolYeomanpreferstobeknownasaworkflowratherthanjustatool.Itisactuallyacollectionofthreetoolsthathelpyoumanageyourworkflowefficiently.ThetoolsthatcomeasapartofYeomanareasfollows:
Yo:Thisisascaffoldingtoolandusingthenumerousgeneratorsavailable,onecanquicklycreatetheskeletonofyourproject.YohasageneratortobuildAngularJSappsandwewillbeusingthatlaterinthischapter.Grunt:Thisisusedtorunthetasksthatwillhelpyoupreview,test,andbuildtheapp.Bower:Thisisanidealtoolfordependencymanagement.Yeomanusesittoautomaticallysearchanddownloadthenecessaryscripts.
Let’sgoaboutinstallingYeomanandplayingaroundwithitabit.
InstallingYeomanToinstallYeoman,makesureyouarerunningitwithadministrativeprivileges.Enterthefollowingcommandintheterminal:
sudonpminstall–gyo
Next,let’sinstalltheAngularJSgeneratorusingthefollowingcommand:
sudonpminstall-ggenerator-angular
Now,let’screateourprojectdirectoryandcreatetheskeletonforourproject.WewillcallourappYoho;so,firstlet’screateafoldercalledyoho.Enterthefollowingcommandintheterminal:
mkdiryohocdyohoyoangular
It’snowgoingtostartaskingaseriesofquestions,answerYforallexceptthequestion,“WouldyouliketouseSass(withCompass)?”.AnswerNforthisone.
NoteThereasonwesaynohereisbecausefornowwewillusevanillaCSS.UsingSaasandCompassishoweverstronglyrecommendedwhilebuildinglargeapplications.
Onceyo-angularhasfinisheddoingwhateverithadtodo,gointoyouryohofolderandyou’llnoticeawholebunchoffilesandfolders,asshowninthefollowingscreenshot:
YeomanhascreatedtheskeletonofyourAngularJSappalongwitheverythingyouwillneedforthisproject.
Beforewegointothedetailsofthedifferentfiles,onethingtonoteisthatyournode_modulesfolderisempty.ThismeansYeomanhasonlycreatedthepackage.jsonfilewithalldevdependencieslistedout,buthasn’tdownloadedthemyet.
Wewillneedtorunthefollowingcommand:
npminstall
Thiswilldownloadandinstallallthedependencieslistedoutinthepackage.jsonfile.Onceit’sfinishedinstalling,verifythatthenode_modulesfoldernowhasfolderssuchasgrunt-contrib-cleanandgrunt-contrib-concatwithinit.
Ok,now,let’stryandmakesenseofallthefilesthatYeomanhascreated.Refertothefollowingtable:
Filename Description
app/404.html Thisisthe404errorpagethatwillshowup,whentheusertypesinawrongURLortheAngularappcouldn’tfindthepagementionedintheURL.
app/favicon.ico
Thisistheiconthatwillshowupinthebrowsertabofyourapp.Makesureyoureplacethisdefaultonewithaniconthatrepresentsyourapp.Feelfreetouseanyofthosenumerousonlinefavicongeneratorstocreateyourfavicon.Rememberthatthisfaviconhelpsuserstoquicklyidentifyyourappwithinthemultipletabsofanopenbrowser.
app/index.html
Thiswillbethehomepageforyourapp.Youcanopenitinatexteditortoseewhatitcontains.Asyouwouldhavenoticed,otherthanthatonelineofcodewiththeng-viewsdirective,therestofthefileismostlybrowserchecksandinclusionofthevariousJavaScriptfiles.NotethatthereisnoactualAngularJScodeotherthanng-viewsandthat’showitneedstobekepttoo.
robots.txtThisisthefilewhereyousetrulesforthesearchenginerobotsorcrawlers,tellingthemwhatpagestheycanindexandwhichsectionsoftheappshouldnotbeindexed.
scripts/app.js
Thisistheroute’sfilewhereyou’lldefinethetemplateviewandthecontrollerthatshouldloadforagivenURL.ControllersandviewsarelooselycoupledinAngularJS;thismeansyoucanhaveasinglecontrollertalktodifferentviews,orswapthetemplatesforacontrollerbysimplyeditingtheroutesinthisapp.jsfile.
scripts/controllers/main.jsscripts/controllers/about.js
Thisiswhereyou’llbewritingthecontrollersforthisapp.Asapartofthescaffolding,YeomanwouldhavealreadycreatedadefaultMainCtrlandAboutCtrlcontrollerswithamodelcreatedineach.Feelfreetomodifyitand/orwritetherestofyourcontrollersinthesamefile.
styles/main.cssAllyourCSScodewouldgointothisfile.Thestylesfolderwouldalsocontainthebootstrap.cssfile.ThiscontainsalltheBootstrapclasses.Makesureyoudon’tmodifyanyofthecodehereoraddanyadditionalCSSinthebootstrapfile.
views/about.htmlviews/main.html
Theviewsfolderwouldcontainallthetemplateviewsorpartialsastheyarealsocalledtoloadwithintheng-viewstagoftheindex.htmlfile.Theroutesdefinedinthescripts/apps.jsfilewouldcontrolwhatviewwillbedisplayedforthegivenURL.
Bower_components:ThiscontainsfoldersforthevariousvendorlibrariessuchasAngularJS,AngularAnimate,jQuery,andBootstrapanditisusedfordependencymanagementoftheselibraries.
bower.json Thebower.jsonfilekeepsatrackofthedependenciesanddevdependenciesofthevariousmodulesandpluginsforthisapp.
YouknowwhattheGruntfileisforright?Openitinatexteditorandbeoverwhelmedbythe300pluslinesofcodeinthefile.You’llseeabunchof
Gruntfile.js predefinedtasksandyou’llalsonoticethatbesidesthedefaultbundledtask,youalsohavetaskscalledtestandbuild.Thesecanbeusedtopreviewyourappandfinallybuilditreadyfordeployment.
test/karma.conf.js
Thekarma.conf.jsfileistheconfigurationfileforrunningKarmaunittests.Openingthisfilewillshowthetestingframeworkweareusing,listfilesthatwewanttoincludewithinthescopeoftheseunittests,whatporttouse,thebrowsertouse,andsoon.
node_modules
Asself-explanatoryasitcanbe,thisfoldercontainsthevariousNode.jsmodulesthatweredefinedinthepackage.jsonfile.Notethatthesemodulesdonotgetinstalledwhenyouruntheyo-angularcommand.Thesewoulddownloadandinstallonlyafteryourunthenpm-installcommandafterthecreationofthepackage.jsonfile.
package.jsonThisfilelistsoutalltheNode.jsmodulesthatneedtobeinstalled.Youmayeditthisfilewithcautiontoaddmoreorremovedependenciesthatyouthinkarenotneededforyourapp.
test/spec/controllers/main.js
Thisisthefilewhereyou’dwritetheunittestsforyourcontrollers.Themain.jsfilewouldalreadyhaveasimpleunittestinit.
ThedefaultconfigurationofYeomanusesJasmine;youcanchangetheconfigurationstouseMochaorQunitframeworks.
Let’sinstallourNode.jsmodulesbyrunningthefollowingcommandintheterminal:
npminstall
RunningyourappEarlierinthischapter,wesawhowtosetupaserverusingNode.jsandExpressJS.Yeomancomeswithitsownserverandrunningitisassimpleasrunningthefollowingcommandinyourterminal:
gruntserve
TipThegruntservercommandisdeprecatedalthoughitmightstillworkforsome.
Thiswillopenupanewbrowserwindowandwillshowyouthedefaultwelcomescreen,asshowninthefollowingscreenshot:
Ifyourecollectlookingatthemain.jsfile(underscripts/controllers)andthe
main.htmlfile(underviews),you’llnoticethepagethatisbeingrendered.Let’splayaroundabit.
Openthescripts/controllers/main.jsfileandyou’llfindacontrollercalledMainCtrlandamodelcalledawesomeThings.Let’saddsomemoreitemstothisarrayasfollows:
'usestrict';
angular.module('yohoApp').controller('MainCtrl',function($scope){$scope.awesomeThings=['HTML5Boilerplate','AngularJS','Karma','E2E','Protractor'
];});
Let’sdisplayourawesomeThingsarrayintheview.Pleaseaddthefollowingcodetothemain.htmlfileasfollows:
{{things}}
Savethefileandswitchtothebrowser.VOILA!Thepageupdatedonitsown,youdidn’thavetoreloadthepageinthebrowser.
Thebrowserupdatesthemomentyousaveyourfile,nomorehittingtherefreshbutton.Isn’tthatabigreliefandaproductivityboost!
ThisworksthankstoaniftymodulecalledLiveReload.You’llfindthisbeinginstalledasapartofdevDependenciesinthepackage.jsonfile.You’llalsonoticeGrunttasksforitcreatedinyourgruntfile.jsfile.
Sonowyoucanhavetheserverrunningandplaceyourbrowserwindowandyourtexteditorarrangedside-by-side,andwatchyourappupdateasyouwriteyourcodeandsavethefile.
UnittestingwithKarmaWritingautomatedunittestsforyourAngularJSappisoneofthebestpractices,theAngularJSteamhasbeenstronglyadvocatingthisrightfromthestart.Everysamplecodeonthewww.Angularjs.orgsitehasautomatedtestcasesalongwithit.
Keepinginlinewiththesamephilosophy,YeomantoobakesinsomesampleunittestsusingKarma.WhileYeomanwouldautomaticallyinstallKarmaanditsdependencies,letus,nevertheless,makesurethefollowingmodulesarepresentinthenode_modulesfolder:
karmakarma-chrome-launcherkarma-jasmine
Incaseyoudon’tfindtheminyournode_modulesfolder,installthemusingthenpminstallcommand.Next,makesureyourkarma.conf.jsfilelookslikethefollowing:
module.exports=function(config){config.set({basePath:'',frameworks:['jasmine'],files:['bower_components/angular/angular.js','bower_components/angular-mocks/angular-mocks.js','bower_components/angular-animate/angular-animate.js','bower_components/angular-resource/angular-resource.js','bower_components/angular-cookies/angular-cookies.js','bower_components/angular-route/angular-route.js','bower_components/angular-sanitize/angular-sanitize.js','bower_components/angular-touch/angular-touch.js','app/app.js','app/scripts/*.js','app/scripts/**/*.js','test/spec/**/*.js'],exclude:[],preprocessors:{},reporters:['progress'],port:9876,colors:true,logLevel:config.LOG_INFO,autoWatch:true,browsers:['Chrome'],singleRun:false});};
Torunyourunittests,simplyrunthefollowingcommandintheterminal:
grunttest
http://www.Angularjs.org
ThiswillfireupanewChromebrowserwindowandintheterminalstartrunningthroughyourtests.Refertothefollowingscreenshot:
Oh!WegotanerrorinMainCtrl.ItwouldsaysomethinglikeExpected5tobe3andpointyoutoanerrorinthefilelocatedattest/spec/controllers/main.js.
Let’sopenupthisfileandseewhat’sgoingoninthere.Thetestcasethat’sfailingisasfollows:
it('shouldattachalistofawesomeThingstothescope',function(){expect(scope.awesomeThings.length).toBe(3);});
Ifyourecollect,earlierwehadmodifiedourawesomeThingscontrollerandaddedsomeadditionalelementstothearray,theprecedingtestcaseisexpectingthelengthofthatarraytobe3.Let’snowmodifythatstatementtothefollowingcode:
expect(scope.awesomeThings.length).toBeGreaterThan(3);
Let’ssavethisfileandrerunthefollowingcommand:
grunttest
ThetestcasesshouldrunfinewithamessagesayingExecuted2of2SUCCESS…….Done,withouterrors.WewillbewritingmoreunittestswithKarmaintheforthcomingchapters.
UsingProtractorforEnd-to-EndtestsAswesawearlierwithKarma,wecanwriteunitteststhatwillmakesurethatourcodeinthecontrollersisworkingwell;however,itwouldfallshortifyouwantedtorunautomatedUserAcceptanceTests(UAT)orrunteststhatsimulateuser-driveninteractionswiththebrowser.Forrunningsuchtests,we’llneedtouseanothernewtoolcalledProtractor.
ProtractorreplacestheearlierAngularJSscenariosasthedefaultEnd-to-EndtestingframeworkfortestingAngularJSapps.
ProtractorrunsonWebDriver.js,whichinturnmakesuseoftheSeleniumServer.Seleniumisoneofthemostpopularbrowser-automationtools.Inthissection,wewillseehowtosetupastandaloneinstanceofSeleniumServer,installProtractor,andrunadefaultsetofEnd-to-Endtestswithit.
Let’sfirstinstallProtractorbyrunningthefollowingcommandintheterminal:
sudonpminstall–gprotractor
ThiswillinstallProtractorglobally.
InstallingSeleniumServerProtractorcomeswithahandyscriptcalledwebdriver-managerthatcanbeusedtodownloadandruntheSeleniumServer.
Intheterminal,typeinthefollowingcommandtodownloadSeleniumServer:
webdriver-managerupdate
Tostarttheserver,typeinthefollowingcommand:
webdriver-managerstart
ThisshouldstartyourSeleniumServer.Nowopenyourbrowserandtypeinthehttp://localhost:4444/wd/hub/static/resource/hub.htmladdressintheaddressbar.ThiswillshowyouthecurrentstatusoftheSeleniumServer.
Theprotractorfolderwithinthenode_modulescomeswithacoupleofdefaultteststhatcanhelpyoujumpstart,writingyourEnd-to-Endtests.Thesetestsarelocatedintheusr/local/lib/node_modules/protractor/examplefolder.
Dependingonwhatyouarecomfortablewith,youcanchoosebetweenJasmineandMochaforwritingyourtestcases.Fromtheexamplefolderunderprotractor,copytheconf.jsandtheexample_spec.jsfilesandpastethemintoanewtest/protractor-testsfolder.
Understandingtheexample_spec.jsfileTheexample_spec.jsfileisthespecsfilewherethetestcasesarewritten.Let’sopenthisfileinaneditorandtryandmakesenseofwhatitisgoingtodo.
Wefirstdescribeourtestsuiteasfollows:
describe('angularjshomepage',function(){})
Next,let’slookatthetestcase.Thefirsttestcaselookssomethinglikethefollowing:
it('shouldgreetthenameduser',function(){browser.get('http://www.angularjs.org');
element(by.model('yourName')).sendKeys('Julie');
vargreeting=element(by.binding('yourName'));
expect(greeting.getText()).toEqual('HelloJulie!');});
Thefirstlinedescribesthetestcase.Inthenextline,wenavigatetothedefinedURL;inthiscaseweloadthewww.angularjs.orghomepage.
Oncethehomepageisloaded,inthenextstepthecodeistryingtolocateaninputfieldboundtoamodelcalledyourNameandtypeinthetextJulie.ItthenlooksfortheexpressioncalledHello{{yourName}}andverifiesthatthetextreadsHelloJulie.
Let’slookatthesecondtestsuite,whichhastwotestcasesasfollows:
describe('todoList',function(){vartodoList;
WedefinethesuitenameandinitializetodoList.NowsinceboththetestcasesneedtogotothesameURLandwillbebasedontodoList,weusebeforeEachtosettheURLandloadthecontentintoourtodoListarrayasfollows:
beforeEach(function(){browser.get('http://www.angularjs.org');
todoList=element.all(by.repeater('todointodos'));});
ThefirsttestcasecheckstoseeifwehavetwoitemsintodoListandthattheseconditemiscalledbuildanangularapp.Refertothefollowingcode:
it('shouldlisttodos',function(){expect(todoList.count()).toEqual(2);expect(todoList.get(1).getText()).toEqual('buildanangularapp');});
ThesecondtestcasewillsimulateaddinganitemtotodolistbylocatingthetodoTextmodel,andaddinginandverifyingthetextbeingaddedasfollows:
it('shouldaddatodo',function(){varaddTodo=element(by.model('todoText'));
http://www.angularjs.org
varaddButton=element(by.css('[value="add"]'));
addTodo.sendKeys('writeaprotractortest');addButton.click();
expect(todoList.count()).toEqual(3);expect(todoList.get(2).getText()).toEqual('writeaprotractortest');});
})
Understandingtheconf.jsfileTheconf.jsfileistheconfigurationfile.Openitinaneditorandyou’llseetheconfigurationsettingssuchasthedefaultaddressfortheSeleniumServer,thebaseURL,thebrowsertobeusedfortesting,andthelocationofyourtestcases.Now,sincewehavetheexample_spec.jsfileinthesamepathasourconf.jsfile,let’scorrectthepathofthespecstoreadasfollows:
specs:[example_spec.js'],
Torunourtestsuite,opentheterminalandnavigatetotheyohofolderandtypeinthefollowingcommand:
protractortest/protractor-tests/conf.js
Thiswilllaunchabrowserinstanceandseethestepsbeingperformedbythescript.Thebrowserwillautomaticallycloseoncethescriptisexecutedandtheterminalwindowshoulddisplaythefollowingmessage:
Finishedinxxx.xxxxseconds
2tests,2assertions,0failures
NoteSometimesyoumightstartgettingerrorslikeError:ECONNREFUSEDconnectECONNREFUSED.InsuchacaserestartyourSeleniumStandaloneServerandwebserver.
WritingyourownProtractortestcasesNowthatweknowhowtestcasesarewritteninProtractorandhowtorunthem,let’squicklywriteacoupleofourowntestcasesagainstthedefaultscaffoldapplicationthatYeomancreatedforus.
Let’screateanewfilecalledmytests.jsinthetestfolderunderyoho/protractor-tests.Nowwecanstartwritingoutourtestcasesasfollows:
describe('ourhomepage',function(){})
Thefirsttestcasewewillwriteistheonewherewe’llchecktoseeifthepageheadingwithintheh1tagssays‘AlloAllo!'.Thetestcaseforthatwouldlooksomethinglikethefollowing:
it('shouldsayAllo',function(){browser.get('http://localhost:9000/#/');varheading=element(by.tagName('h1'))expect(heading.getText()).toEqual("'Allo,'Allo!")});
Thebrowser.getfunctiondefinestheURLofthepageyou’dwantProtractortonavigateto.Weusetheby.tagNameselectortolocatetheh1tagandgetthetextwithinitandverifythatitmatches"'Allo,'Allo!".
Let’swriteoursecondtestcase.Here,wewanttoensurethatthewidthofourpageiswithintherecommendedlimitsandisn’tgoingbeyondthescreensizeofmostcommonusers.Refertothefollowingcode:
it('shouldnotbegreaterthan940px',function(){browser.get('http://localhost:9000/#/')element(by.className('container')).getSize().then(function(size){expect(size.width).toBeLessThan(950)})})
Here,weareusingtheby.classNameselectortoidentifythecontainerdivandusingthegetSizepropertywechecktomakesurethatthewidthisnotgreaterthan950px.
Noticethatthe.then()functionisapartofapromise,whichensuresthatthecodewaitsfortheresulttobereturned.We’llseepromisesindetailinChapter4,UsingRESTWebServicesinYourAngularJSApp.Fornow,savethefile.
Nowthatwehaveourtestcase’sspecsfileready,weneedtocallitwithintheprotractorconfigurationfile.Let’sopentheconf.jsfileandchangethefilenameinthespecsarraytopointtoourmytest.jsfileasfollows:
specs:['mytests.js'],
Wearenowsettotestourscripts.First,let’sstartourserverbyrunningthefollowingcommand:
cdyohogruntserve
Thisshouldstartourserver.Now,let’srunourprotractortestscriptbyrunningthefollowingcommandfromwithintheyohofolder:
protractortest/protractor-tests/conf.js
MakesureyouhaveyourSeleniumStandaloneServerrunning;ifnot,startitusingthefollowingcommand:
webdriver-managerstart
Ifallgoeswell,youcouldseetheChromebrowserbeinglaunched,andseethescriptnavigatetothelocalhost:9000/#/URLandthebrowserwindowclosingdownaftersometime.
Switchtoyourterminaltoseethestatussayingthefollowingingreenthatmeansourtestcasesworked:
Finishedinx.xxxseconds
2tests,2assertions,0failures
NoteIncaseyou’dliketorunyourtestcaseswithouthavingtolaunchthebrowserwindoweachtimeorifyou’dwanttorunitheadlessonaserver,thenhavealookatPhantomJS(http://phantomjs.org/),whichisanexcellentheadlessbrowserthatrunsontheWebKitengine.
http://phantomjs.org/
SummaryThiscompletesourchapteronsettingupyourrig.Weworkedthroughquiteafewtools,namelyNode.js,Grunt,Yeoman,Karma,andProtractor.WhileIstronglyrecommendmakinguseofallofthemwhenyoubuildyourAngularJSprojects,youmayfeelfreetochoosetheonesthatsuityourprojectthebest.
AnotherthingtonoteisthatmostofthesetoolssuchasNode.js,ExpressJS,andGruntcanbeusedforanynon-AngularJSprojects.Sogettingfamiliarwiththesetoolsissurelybeneficialforallfrontenddevelopers.
Inthenextchapter,wearegoingtoseehowtoquicklybuildaclickableprototypeusingAngular-UI.
Chapter3.RapidPrototypingwithAngularJSInthepreviouschapter,wesawhowtosetupthevarioustoolsthatwillaidinbuildingourAngularJSapp.Inthischapter,wewillseehowAngularJSlendsitselfasanexcellenttooltocreateprototypes.
RapidPrototypingisanexcellentwayofvalidatingthegoalsofthewebapplicationyouareplanningtobuild.Itgivesusefulandimportantfeedbackfromusersandstakeholdersonvariousaspectsoftheapplication,suchasuserclickflows,usabilityissues,andusefulnessoftherequirementspecificationsthatwereinitiallyoutlined.
Inthepast,prototypeswerebuiltusingeitherwireframingtools,ordeveloperswouldcreateaseriesofHTMLpageslinkedwitheachotherthatwouldmimicthefunctioningofthewebapplication.Whiletheformernevergavetherightfeelofhowtheappwouldlookandbehave,thelatterwouldtakeamuchlongertimetobuild,especiallyifitwasalargeapplication.
Now,thankstoAngularJS,buildingsuchprototypeshasbecomealoteasier,andonecanbuildnearlyfunctionalprototypewithinashorttimeframeandwithsignificantlylesscode.
Inthischapter,wewilldothefollowing:
RunthroughthevariouscomponentsoftheapplicationthatwearegoingtoprototypeUnderstandGridLayoutsandseehowBootstrapworksAddUIcomponentssuchascarousels,accordions,andmodalwindowsusingAngularUILearnthemodularwaytobuildpagesusingpartialsCreatedummydatamodelstosimulatedynamicdataUseroutestolinkthecontrollerstotheviews
UnderstandingtheapplicationthatwewillPrototypeWewillcreateaclickableprototypeofapseudowebappnamedHealthyLiving.Itwillconsistoffourpages.Theyareasfollows:
Homepage:Thiswillconsistofacarousel,herounit,andthreemaincontentblocks.Articles:Thisdisplayalistofarticlesinanaccordionview.Gallery:Thisisanimagegallerypagewithpictures,atitle,ashortdescription,andastarrating.Subscribers:ThispagewilldisplaythelistofsubscribersinaninteractivedatagridwithfeaturestogroupbyacolumnandExcel-styleinlineediting.Thesubscriptionpagewillalsohaveabuttonthatwillallowustoaddanewuserviaamodalwindow.
IntroducingGridLayoutsandBootstrapBuildingHTMLpageshadalwaysbeenawebdesigner’sjob,andprogrammerswouldrunmilesawayifaskedtobuildanHTMLpage.
AnotherproblemwithdesigningHTMLpagesisthateverydesignerhastheirownsecretrecipetocreateanHTMLpage,usingtheirownstructuretolayouttheDOMelementsandtheirfavoriteCSSclassnames.ThiscausesquiteananguishwhendeveloperstakeoverHTMLtoputinthedynamiccode,orwhentwodesignersareworkingonthesameproject.
TheGridLayoutsevolvedasameanstohelpgeteverybodyonthesamepageintermsofnamingconventionsandtheDOMstructure,andmoreimportantly,toreducethetimetakentobuildHTMLpageswhileensuringafairamountofbrowsercompatibilityatthesametime.
Whilegridsystemssuchasthe960GridSystemandBlueprintwereamongtheearlygridsystemsavailable,nowadays,Bootstrap,Foundation,andSemanticUIhavebecomeverypopulartoolstobuildfrontendpages.
Atthetimeofwritingthisbook,theversionofBootstrapthatiscompatiblewithAngularUIis3.1.x,andwewillbeusingthistobuildourprototype.
UnderstandingthegridsystemOflate,gridsystemshavebeenextensivelyusedinweb-developmentworkflows.GridsystemsaimtostreamlinetheHTMLmarkupprocessbyprovidingastandardsetofdimensionsanddisplaystylesforthecommonlyusedUIelements.Thefollowingscreenshotshowsagridsystem:
Bootstraphasadefault12-columngridsystemthatisavailableasaresponsive,fluid,andfixedlayout.ItcomeswithacompletesetofpredefinedclassesthatmeetsnearlyallyourUIstylingneeds.
Someofthemostcommonlyusedclassesarementionedinthefollowingtable:
Class Description
.col-md-* Thisisforcolumnwidthsthatareappliedtoacontentblockformediumscreendevicessuchasdesktopswithresolutionsgreaterthanorequalto992pxwide.
.col-xs-* Thisisforsmalldeviceswithawidthof768pxorless.
.col-sm-* Thisisfortabletdeviceswithasizeof768pxormore.
.col-lg-* Thisisforlargedeviceswithsizesgreaterthanorequalto1200px.
.col-md-offset-* Theoffsetclassisusedtoleavecolumnspacingfromtheleft.
.row
.row-fluidThe.rowclassisusedtoseparatethedatarowwise.The.row-fluidclassisusedincaseofafluidlayout.
.container
.container-fluid
The.containerclasswillsettheelementwidthto940pxandwillcenterithorizontallywithrespecttothepage.The.container-fluidclassisusedincaseofafluidlayout.
.lead Thisisusedtomakeaparagraphstandout.Itismostcommonlyusedwithinaherounitortodisplaythepagesummaryunderthepageheading.
.text-left
.text-center
.text-rightTheseareusedtoalignthetexttotheleft,centerandrightrespectively.
Theandtagsareusedtoquotesomebody,andtheandtagsareusedtowrapthenameofthesource.
.pull-left
.pull-rightTheseareusedtofloatanelementandpushiteithertotheleftorrightofitsboundingcontainer.
.btnprimary
.btn-success
.btn-info
.btn-warning
.btn-danger
.btn-inverse
Theseareusedtostylethebuttonsoranchorelements;theseclassesapplydifferentcolorstothebuttonrangingfrombluetoblack.
Atthemostminimum,BootstrapcomeswithaCSSandJavaScriptfilealongwithanimage(/img)foldercontainingtheglyphicons.TheCSSfilecontainsallthestylesforthegridsystemandthepredefinedclassesforthevariousUIcomponents.JavaScriptcontainsthelibrariestobuildUIwidgetssuchasaccordions,tabs,modalwindows,progressbars,datepickers,andsoon.
IntroducingAngularUIAngularUIisabunchofminiprojectsthathelpsyoubemoreproductivewithyourAngularappdevelopment.Atthetimeofwritingthisbook,AngularUIconsistedofprojectsdiscussedinthefollowingsections.
UI-UtilsUI-Utilsisautilitypackagethatallowsyoutoaddawidevarietyofutilitiesintoyourapplication.Theutilitiesareexplainedasfollows:
IEShiv:ThisisusedtoallowsupportforcustomtagsinIE8andbelow.jQueryPassthrough:TheuiJqdirectiveallowsustousejQuerypluginsdirectlyinsteadofhavingtocreatenewdirectivestousethem.EventBinder:ThisallowsyoutobindcallbackstoeventsthatarenotnativelysupportedinAngularJS.Keypress:Thisallowsyoutobindeventstoakeypress.Mask:Thisallowsyoutomaskdatabasedoncertainconditionsset.Validate:ThisallowsyoutocreatecustomvalidatorsandexpressionsReset:Thisallowsyoutodisplayaniconorlink;ifyouclickonit,themodelwillbecomeempty.Scrollfix:Thisaddsaui-scrollfixclasstotheelement.Show/Hide/Toggle:Thisallowsyoutouseasingledirectiveofui-toggleinsteadofusingng-showandng-hide.RouteMatching:Thisisaniftylittledirectivethatcanbeusedtomatchtherouteofthecurrentpage.Highlight:Thisisusedtohighlightastringofcharacterswithinascopemodel.Inflector:ThiswillhelpyouconvertastringintoalternativeformatssuchasreplacespaceswithunderscoresorconvertthestringintoacamelCasesyntax.Unique:Thiscanbeusedtoremoveallduplicateitemsfromwithinanarray.Format:Thisfiltercanbeusedtodoanykindofstringreplacement.
UI-ModulesTheUI-ModulesprojectallowsyoutoeasilyaddCalendarControls,GoogleMaps,andabunchofeditorssuchasTinyMCEandCodeMirrorAce.
UI-BootstrapUI-BootstrapisthenativeimplementationofTwitterBootstrapwithinAngular.Aswe’llseefurtherinthischapter,addingUIcontrols,suchascarousels,accordions,andtabs,isabreezeusingUI-Bootstrap.ItisworthnotingthatUI-BootstrapusestheoriginalCSSandglyphiconsofBootstrapastheyare.It’sonlytheJavaScriptfilethathasbeenrewrittentousenativeAngulardirectives.
NG-GridNG-GridallowsyoutoadddatagridsinyourAngularapp.NG-GridcomeswithquiteafewcustomizationoptionsthatallowyoutoplacegridswithsortablecolumnstofeaturessuchasExcel-styleediting,inplace.
UI-RouterUI-RouterisanewwayofroutingthatallowsyoutocreateNestedRouting.
IDEPluginsIDEPluginsareabunchofpluginsorextensionsthatprovideAngularJSsupportinvarioustexteditors.
Aswemoveaheadinthechapter,wewillmakeextensiveuseoftheUI-BootstrapandNG-Gridprojects.
PrototypingtheHealthyLivingwebsiteForthisexercise,wearegoingtocreateafour-pageclickableprototypeofapseudowebsitecalledHealthyLiving.Thehomepagewillconsistofafullyfunctionalcarousel,herounit,andthreecontentsectionswithcalltoactions.Thefollowingscreenshotisthatofthehomepage:
Let’sgetstartedwiththecreationofourapplication.We’llstartbyperformingthefollowingsteps:
1. Createafoldernamedhl,shortfor“HealthyLiving”.2. AssumingthatyouhavealreadyinstalledYeoman,openuptheterminal.Let’screate
thescaffoldingforourappusingthefollowinglinesofcode:
mkdirhlcdhlyoangular
NoteGenerator-AngularmustbeinstalledbeforeyoucanrunyourAngularapp.Incaseyouhaven’tinstalleditduringChapter2,SettingUpYourRig,pleaseinstallitusingthefollowingcommand:
sudonpminstall–ggenerator-angular
3. Intheprompt,pressYforthequestion,WouldyouliketoincludeTwitterBootstrap?.
4. Forthequestion,WouldyouliketouseSass(withCompass)?,pressN.5. Forthethirdquestion,pressEntertoacceptthedefaultsettings.
NoteUsingaCSSpreprocessorsuchasSASSorLESSisalwaysagoodpracticeasitallowsyoutousevariablesandmixinsinCSS,ensuringthatyourCSSremainsmodularandfollowsDRY(Don’tRepeatYourself)principals.However,coveringthemisbeyondthescopeofthisbook.
Youshouldbeseeingnpmpullingabunchoffilesandcreatingthescaffoldofyourapp.Waitpatientlyuntilitisalldoneandyouarereturnedbacktothecommandprompt.
Youshouldnowbeabletoseethestructureofyourapplicationwiththedefaulthomepage.
AswearegoingtobeusingUI-Bootstrap,let’sinstallitusingBower.
6. Firethefollowingcommandintheterminal:
bowerinstallangular-bootstrap
Thiswillcreatetheangular-bootstrapfolderwithintheapp/bower_componentsfolder.
TobeabletouseAngularBootstrapinourapplication,weneedtoincludetheJSfile.
7. Let’sopenuptheapp/index.htmlfileandaddthefollowinghighlightedline.
Ifyoulookintothebower_components/angular-bootstrapfolder,you’llnoticetherearethefollowingtwotypesoffilesalongwiththeirminifiedversions:
ui-bootstrap.js:Thiscontainsallthedirectives,butitdoesn’tcontainanytemplates.Itmakessensetousethisfileifyoudonotwanttousethedefaulttemplatesbutwanttocustomizeyourtemplatesfromscratch.
ui-bootstrap-tpls.js:Thiscontainsallthedirectivesalongwiththedefaulttwitterbootstraptemplatecode.Ifyouarenotlookingtomakeanycustomization,thenitsbesttoincludethisfileinyourproject.
Addingtheui.bootstrapdependencyThenextstepistoaddtheAngularBootstrapdependencytotheAngularapp.
Wedothisbymodifyingthefollowinglineintheapp/scripts/app.jsfile:
angular.module('hlApp',['ui.bootstrap'])
Now,angular-bootstrapwillbeavailableforuseacrossourapplication.
CreatingthenavigationbarTocreatethenavigationbar,let’sopenuptheapp/index.htmlfileandaddthepartofthecode,whichisshownasfollows:
HealthyLiving
ArticlesGallerySubscribers
Asyoucanseefromtheprecedingcode,wedefinedtheheadertagandappliedtheCSSclasses,navbarandnavbar-fixed-top,toit.ThesearepredefinedbootstrapCSSclassesthatareusedtostylethenavigationbar.
ThenavbarclassisadefaultcontainerthatsetstheoverflowtovisibleforallelementswithinthenavbarDOM.
Thenavbar-fixed-topclasswillmakethenavigationbarsticktothetopofthepage,anditwillstayfixedevenasthepagescrolls.Youcanalsousenavbar-fixed-bottomtomakeyournavigationbarsticktothebottomofthepage.
Now,we’lladdthetagwithaclassnamedcontainer.Thecontainerclasswillsetthewidthofthiselementto940pxandalsocentertheelementhorizontallyonthepage.
WewilladdourHealthyLivingwebsitewithinananchortagandgiveitaclassnamednavbar-brand,asthisiswhatourbrandnameissupposedtobe.
NavigationlinksfortheArticles,Gallery,an