index-of.co.ukindex-of.co.uk/programming/stephen radford - sviluppare...gli argomenti del libro il...

259

Upload: others

Post on 12-Aug-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap
Page 2: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

SVILUPPAREAPPLICAZIONIWEBCONANGULARJSEBOOTSTRAP

StephenRadford

Page 3: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

©Apogeo-IF-IdeeeditorialiFeltrinellis.r.l.SocioUnicoGiangiacomoFeltrinelliEditores.r.l.

ISBNedizionecartacea:9788850333424

Copyright©PacktPublishing2014.FirstpublishedintheEnglishlanguageunderthetitleLearningWebDevelopmentwithBootstrapandAngularJS(9781783287550).

Ilpresentefilepuòessereusatoesclusivamenteperfinalitàdicaratterepersonale.TuttiicontenutisonoprotettidallaLeggesuldirittod’autore.

Nomiemarchicitatineltestosonogeneralmentedepositatioregistratidallerispettivecaseproduttrici.

L’edizionecartaceaèinvenditanellemigliorilibrerie.

~

Sitoweb:www.apogeonline.com

ScoprilenovitàdiApogeosuFacebook

SeguicisuTwitter@apogeonline

Rimaniaggiornatoiscrivendotiallanostranewsletter

Page 4: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Introduzione

Page 5: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Durantelamiacarrierahosviluppatoprogettididiversedimensioni,dapiccolisiticommercialiainterisocialnetwork.EranotuttiaccomunatidallanecessitàdidisporrediJavaScripteCSSbenstrutturati.

Questolibroaffrontaduefantasticiprogettiopensourcechederivanodaquestaesigenza:BootstrapeAngularJS.

Page 6: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

GliargomentidellibroIlCapitolo1,“Hello,{{name}}”,esaminaifondamentidiAngularJSeBootstrap

attraversolarealizzazionediunasempliceappHello,World.

IlCapitolo2,“SviluppareconAngularJSeBootstrap”,presental’appprincipalechesvilupperemonelcorsodellibro,ilsistemadellegrigliediBootstrapealcunicomponentidiAngularJS.

IlCapitolo3,“Ifiltri”,illustraalcunideifiltriintegratiinAngularJSelacreazionediunfiltro.

IlCapitolo4,“Routing”,sibasasulrouterintegratodiAngularJS,eillustral’utilizzodeipartialpercreareun’appmultiview.

IlCapitolo5,“Leviste”,esaminailsistemadellegrigliediBootstrapeapprofondisceipartial.

IlCapitolo6,“CRUD”,spiegacome,dopoaverimpostatoleviste,possiamoimplementare,creare,leggere,aggiornareecancellarelefunzioni.

IlCapitolo7,“AngularStrap”,descriveilmoduloditerzeparticheconsentediutilizzareiplug-indiBootstraptramiteAngularJS.

IlCapitolo8,“Connessionealserver”,esaminaduesistemiufficialipercollegarsiaunserver.

IlCapitolo9,“Itaskrunner”,spiegacomeminificaretuttiifileJSeLessutilizzandoGruntegulp.

IlCapitolo10,“PersonalizzareBootstrap”,mostracomepersonalizzarefacilmenteBootstrapdopoaverimpostatoGrunt.js.

IlCapitolo11,“Validazione”,affrontaglistrumentidivalidazionesubitoprontiall’uso;liimplementeremoegestiremoglierroridelserver.

IlCapitolo12,“Strumentidellacommunity”,presentaalcunistrumenticreatidallacommunitydiAngularJS.

L’AppendiceA,“Personeeprogetti”,presentaalcunepersoneimportantinell’ambientediAngularJSeBootstrap,oltreaprogettirilevanti.

L’AppendiceB,“Incasodidubbio”,offrerisposteaglieventualidubbideilettori.

L’AppendiceC,“Risposteaiquiz”,comprendetuttelerispostealledomandedeiquizpresentinellibro.

Page 7: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ChecosaoccorreperillibroAngularJSeBootstrapnonhannodipendenzeeperquestolibrodovretesolo

disporrediunbrowserediuneditorditesto.ViconsiglioChromeeAtom.

Page 8: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

AchisirivolgeillibroSeviinteressalosviluppowebmoderno,sicuramenteconoscereteBootstrape

AngularJS.QuestolibrosirivolgealettoriconunminimodiesperienzainJavaScriptchedesideranoimpegnarsinellosviluppodiwebapp.

TuttaviaèassolutamentenecessarialaconoscenzadiJavaScript.Senonconosceteladifferenzatraunastringaeunoggetto,correteairipari.Ovviamente,seavetegiàutilizzatoAngularJSoBootstrapevoletesapernedipiù,visentireteavostroagio.

Page 9: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ConvenzioniInquestolibrotroveretealcunistilidicaratterechedifferenzianodiversitipidi

informazioni.Diseguitoalcuniesempieunaspiegazionedellorosignificato.

Ilcodicechetrovereteneltesto,inomidelletabelledeldatabase,inomieleestensionideifile,ipercorsi,gliURL,l’inputdegliutentieglihandlediTwittervengonopresentatiinmonospaziato.

Unframmentodicodiceèformattatonelseguentemodo:

<!DOCTYPEhtml>

<htmllang="en">

<head>

<metacharset="utf-8">

<title></title>

</head>

<body>

</body>

</html>

Gliinputeoutputdarigadicomandosipresentanonelmodoseguente:

open-a'GoogleChrome'--args-allow-file-access-from-files

Termininuovi,paroleimportanti,cartelleodirectoryedelementidell’interfacciasonoriportatiincorsivo.

NOTA

Isuggerimenti,gliavvertimentielenoteimportantiappaionoinquestomodo.

Page 10: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ScaricaifiledegliesempiSulsitodell’editoreoriginaleinglese,PacktPublishing,potetescaricareifiledegli

esempipresentatideltesto.Perfarloènecessarioregistrarsigratuitamenteall’indirizzohttps://www.packtpub.com/register.Quindiandatesullaschedadellibroall’indirizzohttps://www.packtpub.com/web-development/learning-web-development-bootstrap-and-angularjs(percomoditàinformaabbraviatahttp://bit.ly/packt-ab)efateclicsuCodeFiles.Perproblemididownloadpotetecontattarelanostraredazioneall’[email protected].

Page 11: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

L’autore

Page 12: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

StephenRadfordèunosviluppatorewebatuttotondonativodiBristol,chevivenelcentrodiLeicester,inGranBretagna.Dopoaverfrequentatoall’universitàilcorsodiGraficaeComunicazioneVisiva,siètrasferitoinquestacittà,doveèstatoassuntodaunadellepiùimportantisocietàdimarketingonlinedelpaese.

Mentrelavoravaperalcuneagenzie,Stephenhasviluppatodiversiprogetticollaterali,tracuiFTPloy,unSaaSconcepitoperrendereaccessibileatuttiildeploymentcontinuo.Questoprogettosièclassificatotraifinalistinellacategoria“SideProjectoftheYear”dei.NetAwards.

Attualmente,insiemeconilsuosocio,gestisceCocoon,unasocietàdisviluppowebcherealizzaegestisceappcomeFTPloyeFormer.Cocoonlavoraancheastrettocontattoconungruppodistartupeaziendechetrasformanoideeinsitieapp.

Vorrei ringraziare quanti mi hanno sostenuto durante la stesura di questo libro. Prima di tutto, il miopartner,Declan.Miè statodigrande supportoenonpotreidesideraredi avere accantonessunapersonamiglioredilui.PaulMckayèstatoilprimoalqualehomostratoillibroemihaancheaiutatoconilmioprofilo biografico perché, stranamente, ho incontrato grandi difficoltà a scrivere sulla mia vita.Ovviamente, voglio ringraziare imiei genitori.Mio padre ha atteso pazientemente la copia cartacea dellibro;sperocheorasiainbellamostrainsoggiorno.

Page 13: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Irevisori

Page 14: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

TasosBekos,ingegnereinformatico,utilizzaletecnologiewebdapiùdidiecianni.Halavoratocomesviluppatorefreelanceeconsulenteperalcunedellepiùimportantisocietàinternazionalifinanziarieeditelecomunicazioni.AttualmentelavoracomesviluppatoreperZuluTrade,dovesiavvaledellepiùmodernetecnologiefront-end.ConosceafondoAngularJSedèunmembroattivodellacommunityopensource,nellaqualeoperacomeprincipalecollaboratorealprogettoAngularUIBootstrap.Quandononscrivecodice,trascorreiltempoagiocareconisuoiduefigli.

JackHsuèunosviluppatorewebspecializzatoneglistrumentienelletecnologiefront-end.Èilprincipalesviluppatorefront-endpressoNulogy,dovemettelasuaconoscenzadiJavaScripteAngularJSalserviziodeicolleghi.PrimadiNulogy,halavoratopernumeroseaziende,tracuiTheGlobe&Mail,OntarioInstituteofCancerResearcheWaveAccounting.Neltempoliberogiocaaivideogiochi,esploraidiversiquartieridiTorontooviaggiaperilmondo.Sulsuoblogpersonaleèpossibileleggerenumerosipostriguardantilaprogrammazione.

OleB.Michelsenlavoradapiùdi12anninellosviluppowebesièlaureatoininformaticapressolaDIKU,all’universitàdiCopenhagen.DirecentesièspecializzatonellosviluppoJavaScriptfront-end,concentrandosiinparticolaresuWebRTCesuframeworkperappsinglepage.

JurgenVandeMoereènatonel1978edècresciutoaEvergem,inBelgio,conigenitori,lasorellaeisuoianimalidomestici.A6annihainiziatoadaiutareilpadre,proprietariodiunnegoziodiinformatica,adassemblareicomputerpericlienti.Mentregliamicigiocavanoaivideogiochi,Jurgenpreferivascriverescripteprogrammiperrisolvereiproblemicheeranocostrettiadaffrontareiclientidelpadre.DopoessersilaureatoinlatinoematematicapressoilcollegeSint-LievensaGand,Jurgenhaproseguitolasuaformazionepressol’universitàdellastessacittà,dovehafrequentatoinformatica.All’universitàilsuonomeutenteUnixera“jvandemo,”ilnicknamecheusaancoraoggisuInternet.Nel1999hainiziatolacarrieraprofessionalepressoInfoworld.Dopoannididurolavorocomesviluppatoreenetworkengineer,nel2005enel2006haricopertoposizionimanageriali.Sentendosiunosviluppatore,eavvertendolamancanzadiscriverecodice,nel2007hadecisodiporrefineallacarrieradimanagerperdedicarsidinuovoallasuaverapassione:losviluppo.Daallorahastudiatoelavoratodacasa,inBelgio,dovevive

Page 15: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

attualmenteconlasuafidanzata,suofiglioeisuoicani.Inunmondoinrapidaevoluzionediapplicazionidata-intensiveereal-time,siconcentrasulletecnologielegateaJavaScriptebasatesuAngularJSeNode.js.Isuoinumerosicontributipubblicieprivatihannopermessodiavviaremoltepliciprogettidisuccessointuttoilmondo.Seviserveunaconsulenzaperilvostroprogetto,potetescrivergliall’[email protected](@jvandemo)oleggereilsuoblog(http://www.jvandemo.com).

Page 16: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo1

Page 17: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Hello,{{name}}

Ilmodomiglioreperimparareaprogrammareèscriverecodice,edèproprioquestociòchefaremo.PercomprenderequantoèfacileesseresubitooperativiconBootstrapeAngularJS,realizzeremoun’applicazionemoltosemplicecheciconsentiràdidigitareunnomeevisualizzarlosullapaginaintemporeale.Scopriretecosìl’efficaciadelbindingdeidatibidirezionaleeillinguaggiopertemplateintegratodiAngular.UtilizzeremoBootstrapperattribuireunostileeunastrutturaall’app.

Primadiinstallareiframework,creeremolastrutturadellecartelleeilfileindex.htmlchesaràlabasedell’app.

Page 18: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ImpostazionePerrealizzarel’appconAngulareBootstrap,procediamoall’impostazione,che

consistenelcreareunapaginaHTMLeincluderealcunifile.Innanzituttocreateunanuovadirectory,chapter1,eapritelanelvostroeditor.Createalsuointernounnuovofile,index.html,eimmettetequestocodiceboilerplate:

<!DOCTYPEhtml>

<htmllang=”en”>

<head>

<metacharset=”utf-8”>

<title></title>

</head>

<body>

</body>

</html>

SitrattadiunapaginaHTMLstandardconlaqualeopereremodopoaverintegratoAngulareBootstrap.

Createduecartelleall’internodellacartellachapter1:cssejs.Lastrutturacompletadellecartelledovrebbeesseresimileallaseguente.

Page 19: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

InstallazionediAngularJSeBootstrapInstallarequestiframeworkèsemplicecomeincluderefileCSSoJavaScriptnella

pagina.Lopotremmofareconuncontentdeliverynetwork(CDN)comeGoogleCodeoMaxCDN,maperorarecupereremoifilemanualmente.EsaminiamoipassichedovresteconoscerequandointegrereteAngularJSeBootstrapnelprogetto.

InstallazionediBootstrapAndateall’indirizzohttp://getbootstrap.comefateclicsulpulsanteDownload

Bootstrap.OtterreteunfileZIPconl’ultimaversionediBootstrapchecomprendeCSS,fontefileJavaScript.Leversioniprecedentiincludevanounadirectorydelleimmagini,chenellaVersione3diventaiconfonts.

Perquest’app,ciinteressaperorasoltantounfile:bootstrap.min.csspresentenelladirectorycss.Ilfogliodistileforniscetuttalastrutturaequeglielementigraziosi,tracuipulsantiemessaggidiavviso,percuiBootstrapèconosciuto.Copiatelonelladirectorycssdelprogettoeapriteilfileindex.htmlnell’editorditesto.

IntegrareBootstrapèfacilecomecollegareilfileCSScheabbiamoappenacopiato.Aggiungetequantosegueall’internodeltag<head>.Inseritequestotagnell’elemento<head>dellapagina:

<linkrel=”stylesheet”href=”css/bootstrap.min.css”>

InstallazionediAngularJSDopoaverintegratoBootstrapnellawebapp,procedeteainstallareAngular.

Visitateilsitohttps://angularjs.org/efateclicsulpulsanteDownload.Vedretealcuneopzioni;avoiservelaversionestabileminificata.

Copiateilfilecheavetescaricatonelladirectoryjsdelprogettoeapriteilfileindex.html.Angularpuòessereintegratonell’appcomequalsiasialtrofileJavaScript.

Èpreferibileincluderloneltag<head>dellapagina,altrimentialcunefunzioniacuiricorreretenellibrononsarannoattive.Anchesenonènecessario,dovretecompierealtripassiperintegrareancoradipiùAngularnelfileHTML.

Inseritequestotag<script>nell’<head>dellapagina.

<scriptsrc=”js/angular.min.js”></script>

Page 20: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Tuttofatto?Quasi.DobbiamodireadAngularcheintendiamoutilizzarlonell’app.Angularrichiedequestobootstrap,eilframeworksemplificamoltissimoquestaprocedura.Dovetesemplicementeincludereunaltroattributoneltag<html>diapertura:

<htmllang=”en”ng-app>

Eccofatto!OraAngularsachevogliamoutilizzarlo.

NOTA

Angularciconsenteanchedi farprecederequestiattributidadata- (peresempiodata-ng-app)nelcasovolessimoscrivereHTML5valido.

UtilizzareAngularJSAbbiamovistomoltateoriaallabasediAngular;ègiuntoilmomentodimetterla

inpratica.Dopoavercreatoun’appfunzionante,vedremocomeabbellirlaconBootstrap.

Riapriteilfileindex.html,maquestavoltaapriteloanchenelbrowsercosìdavedereciòsucuistatelavorando.Eccoachepuntosiamoarrivati:

<htmllang=”en”ng-app>

<head>

<metacharset=”utf-8”>

<linkrel=”stylesheet”href=”css/bootstrap.min.css”>

<title></title>

<scripttype=”text/javascript”src=”js/angular.min.js”></script>

</head>

<body>

</body>

</html>

AbbiamoimpostatoBootstrapeAngulareabbiamoinizializzatol’appconl’attributong-appneltagdiapertura<html>;orapassiamorapidamenteall’azione.

Realizzeremoun’appHello,Worldunpo’diversa.Invecedifarcomparirequestascritta,avremouncampoditestocheeffettueràilbindingdeidatieliripeteràautomaticamentenellavista;tuttoquestosenzascrivereunasolarigadiJavaScript.

Iniziamoadaggiungereiltag<h1>neltag<body>:

<h1>Hello,World</h1>

NelbrowservedretecheBootstraphaaggiornatolavisualizzazionepredefinita.AlpostodelfontTimesNewRomancomparel’Helveticaeimarginiditroppoattornoalbordosonostatieliminati.

Page 21: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Oradobbiamoincluderel’inputditestoespecificareancheilmodellocheintendiamoutilizzare.Ilmodellopuòesserediqualsiasitipo,mainquestocasosaràunastringachel’inputrestituirà:

<inputtype=”text”ng-model=”name”>

L’attributong-modeldichiarailbindingdelmodellosuquestoelemento,etuttociòchedigiteremonelcampoditestosaràassociatoaessodaAngular.Ovviamentenonverràvisualizzatocomepermagiasullapagina;dovremodirealframeworkdoveripeterlo.Pervisualizzareilmodellosullapagina,èsufficienteracchiudereilnometradoppieparentesigraffe:

{{name}}

InseriteloalpostodiWorldneltag<h1>eaggiornatelapaginanelbrowser.Sedigitateilvostronomenelcampoditesto,vedretechevienevisualizzatoautomaticamentenell’headerintemporeale.AngularlofaalpostovostrosenzadoverscrivereunasolarigadiJavaScript.

Page 22: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Unrisultatoottimo,masarebbeopportunoavereun’impostazionepredefinitacheevitidifarsembrarechenonfunzionaancoraprimacheunutentedigitiilsuonome.Fortunatamentetuttociòcheècompresotraleparentesigraffevieneanalizzatocomeun’espressioneAngularJS,ecosìèpossibileverificareseilmodellohaunvalore;incasocontrario,puòripetereWorld.InAngularquestaèun’espressione,edèsufficienteaggiungereildoppiopipecomeinJS:

{{name||‘World’}}

NOTA

Angulardescriveinquestomodoun’espressione:“FrammentidicodicesimiliaJavaScriptchedisolitosonopostiinbindingcome{{espressione}}.”

ÈopportunoricordarechesitrattadiJavaScript,edeccoperchédobbiamoinserirelevirgolettepersegnalarechesitrattadiunastringaenondelnomediunmodello.Seprovasteacancellarle,vedrestecheAngularnonvisualizzadinuovonulla.CiòaccadeperchéimodellinameeWorldnonsonodefiniti.

Questimodellipossonoesseredefinitidirettamenteall’internodell’HTMLutilizzando,comeabbiamovisto,unattributo,maèanchepossibileassegnareaessiunvaloredauncontroller.AquestoscopocreateunnuovofileJS,controller.js,eincludetelonell’app:

<scripttype=”text/javascript”src=”js/controller.js”></script>

InseritelodopoaverinclusoAngularnellapaginaperevitareerrori.

IcontrollersonosemplicementefunzionicheAngularpuòutilizzare;esaminiamoneuno:

Page 23: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

functionAppCtrl($scope){

}

Quiabbiamodichiaratoilcontroller(insostanzaunasemplicefunzionedelcostruttoreJavaScript)einessoabbiamoinseritoloscope.Loscopeèciòacuipossiamoaccedereall’internodellavista.Suun’unicapaginapossonoesisteremolteplicicontrolleremoltepliciscope.SitrattainsostanzadiunoggettoJavaScriptdeinostrimodelliedellenostrefunzioni,suiqualiAngularoperalasuamagia;peresempio,loscopedellanostraapplicazioneperilmomentoapparecosì:

{

name:“Stephen”

}

Loscopecambiaasecondadiciòchesidigitanelcampoditesto.Aessosipuòaccederesiadallavistasiadalcontroller.

Dopoavercreatoilcontroller,dobbiamodireadAngularcheintendiamoutilizzarlo.Perlanostraappciserveunsolocontroller;aggiungiamounsecondoattributoaltag<html>:

ng-controller=”AppCtrl”

QuestoattributodiceadAngularchevogliamoutilizzarelafunzioneAppCtrlcheabbiamoappenacreatocomecontrollerperlapagina.Potremmoovviamenteaggiungerloaqualsiasielementosullapaginacompreso,sevolessimo,ilbody.

Perverificarechetuttofunzioni,specificheremounvaloreinizialeperilmodello.Èfacilecomeimpostareunaproprietàsuqualsiasioggetto:

functionAppCtrl($scope){

$scope.name=“World”;

}

Seaggiornatel’appnelbrowser,vedretecheWorldèprecompilatocomevaloredelmodello.Questoèunottimoesempiodell’efficacebindingdeidatibidirezionalediAngular.CiconsentediutilizzaredatipredefinitidiunaAPIodiundatabaseepoimodificarlidirettamentenellavistaprimadiriottenerlinelcontroller.

NOTA

Angular descrive il binding dei dati come “la sincronizzazione dei dati tra i componenti delmodelloedellavista”.Così,semodifichiamo ilvalorediunmodellonellavistaonelcontrollerJavaScript,tuttosiaggiornadiconseguenza.

BootstrapDopoavercreatol’applicazioneHelloWorldeaververificatochetuttofunzioni

comeprevisto,èilmomentodiutilizzareBootstrapperaggiungerestileestruttura

Page 24: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

allanostraapp.Peroral’appèmalallineatasullasinistraetuttosembratroppofitto;rimediamoconunpo’discaffolding.Bootstrapoffreunottimosistemadigriglieresponsivemobilefirstchepossiamoutilizzareaggiungendoalcunidivealcuneclassi.

Prima,però,racchiudiamoilcontenutoinuncontenitoreperfarsubitounpo’diordine.

NOTA

Ilconcettodimobilefirstconsistenelprogettare/sviluppareinnanzituttoperglischermipiùpiccolieaggiungereelementialdesigninvecedieliminarli.

<divclass=”container”>

<h1>Hello,{{name||‘World’}}</h1>

<inputtype=”text”ng-model=”name”>

</div>

Seridimensionatelafinestradelbrowser,dovresteiniziareaosservarelacapacitàdiadattamentodelframeworkevederelafinestracomprimersi.

PuòessereunabuonaidearacchiuderloinquellochenellaterminologiadiBootstrapèunJumbotron(nelleversioniprecedentisichiamavaHeroUnit).Faràrisaltaremoltodipiùiltitolo.Possiamoottenerequestorisultatoracchiudendoitag<h1>e<input>inunnuovodivassociatoallaclassejumbotron:

<divclass=”container”>

<divclass=”jumbotron”>

<h1>Hello,{{name||‘World’}}</h1>

<inputtype=”text”ng-model=”name”>

</div>

</div>

Page 25: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Haunaspettodecisamentemigliore,mailcontenutoèancoratroppovicinoallapartesuperioredellafinestradelbrowser.Possiamointrodurreunulterioremiglioramentoconunheaderdipagina,ancheseilcampoditestomisembraancorafuoriposto.Sistemiamoinnanzituttol’headerdipagina:

<divclass=”container”>

<divclass=”page-header”>

<h2>Chapter1<small>Hello,World</small></h2>

</div>

<divclass=”jumbotron”>

<h1>Hello,{{name||‘World’}}</h1>

<inputtype=”text”ng-model=”name”>

</div>

</div>

Page 26: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Hoinseritoilnumeroeiltitolodelcapitolo.Iltag<small>all’internodeltag<h2>permettedidistinguereefficacementeilnumerodaltitolodelcapitolo.

Laclassepage-headeraggiungealtromargineepadding,oltreaunsottilebordoinferiore.L’ultimoelementochepotremmomigliorareèlacaselladitesto.Bootstrapoffrealcuniottimistiliditestoevalelapenautilizzarli.Perprimacosadobbiamoaggiungerelaclasseform-controlall’inputditesto.

Inquestomodolalarghezzaverràimpostataal100%ealcuniaspettistilisticimiglioreranno,comeibordiarrotondatieunbagliorenelmomentoincuil’elementoottieneilfocus:

<inputtype=”text”ng-model=”name”class=”form-control”>

Vamoltomeglio,masembraancoraunpo’piccolorispettoall’header.Bootstrapoffrealtredueclassicherimpicciolisconooingrandisconol’elemento,rispettivamenteinput-lgeinput-sm.Inquestocaso,scegliamolaclasseinput-lgelaaggiungiamoall’input:

<inputtype=”text”ng-model=”name”class=”form-controlinput-lg”>

Page 27: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Dobbiamoancorarisolverelaquestionedellaspaziaturaperchéètroppoaridossodeltag<h1>.Forseèunabuonaideaaggiungereun’etichetta,cosìl’utentecapiràchedevedigitarenellacasella.Bootstrapciconsentediprendereduepiccioniconunafavaperchéincludeunmarginenell’etichetta:

<labelfor=”name”>EnterYourName</label>

<inputtype=”text”ng-model=”name”class=”form-controlinput-lg”id=”name”>

Page 28: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. ComevieneinizializzatoAngularsullapagina?2. Checosasiusapervisualizzaresullapaginaunvaloredelmodello?3. Achecosacorrispondel’acronimoMVC?4. ComecreiamouncontrollerecomediciamoadAngularcheintendiamo

utilizzarlo?5. InBootstrap3qualèilnuovonomediHeroUnit?

Page 29: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoLanostraappèbellaefunzionapropriocomedovrebbe;riepiloghiamociòche

abbiamoimparatoinquestoprimocapitolo.

InnanzituttoabbiamovistocomeèfacileinstallareAngularJSeBootstrapincludendounsolofileJavaScripteununicofogliodistile.Abbiamoancheosservatocomevieneinizializzataun’applicazioneAngulareabbiamoiniziatoarealizzarelanostraprimaapp.

L’appHello,Worldcheabbiamocreato,seppurmoltosemplice,illustraalcunecaratteristichefondamentalidiAngular:

espressioni;scope;modelli;bindingdeidatibidirezionale.

TuttoquestoèstatopossibilesenzascrivereunasolarigadiJavaScript;infattiilcontrollercheabbiamocreatoservivasoloaillustrareilbindingbidirezionaleenonerauncomponenteobbligatoriodell’app.

ConBootstrap,abbiamoutilizzatoalcunideinumerosicomponentidisponibili,tracuileclassijumbotronepage-headerperattribuireall’appunpo’distileesostanza.Inoltreabbiamovistoinazioneilnuovodesignresponsivemobilefirstsenzadoveraffollareilmarkupconclassioelementinonnecessari.

NelCapitolo2esamineremopiùneldettaglioalcunecaratteristichefondamentalidiAngularJSeBootstrapepresenteremoilprogettocheimplementeremonelcorsodellibro.

Page 30: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo2

Page 31: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

SviluppareconAngularJSeBootstrap

DopoavercreatoufficialmentelaprimaapputilizzandoAngularJSeBootstrap,ègiuntoilmomentodifareunsaltodiqualità.

Inquestolibroviserviretedientrambiiframeworkpersviluppareun’appdigestionedeicontatticontantodiricercatestuale,creazione,modificaecancellazione.

Esamineremounabasedicodicechepuòesseremantenutaesfrutteremotuttoilpotenzialedientrambiiframework.Iniziamoasviluppare!

Page 32: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ImpostazioneCreiamorapidamenteunanuovadirectoryperl’appeimpostiamounastruttura

simileall’appHello,WorldcheabbiamosviluppatonelCapitolo1.

Peresempio,nellastrutturadicartellemostratanellaprossimafigura,abbiamoinseritoledirectorynelladirectoryassetsperteneretuttoinordine.CopiateAngulareBootstrap,comedescrittonelCapitolo1all’internodelledirectorypertinentiecreateilfileindex.htmlnellaradice,chediventeràlabasedell’appdigestionedeicontatti.IlseguentesnippetèunasemplicepaginaHTMLconintegratiBootstrapeAngular.AbbiamoancheinizializzatoAngularsullapaginaconl’attributong-appneltag<html>.

Eccocomedovrebbeapparireinquestafase:

<!DOCTYPEhtml>

<htmllang=”en”ng-app>

<head>

<metacharset=”utf-8”>

<title>ContactsManager</title>

<linkrel=”stylesheet”href=”assets/css/bootstrap.min.css”>

<scripttype=”text/javascript”

src=”assets/js/angular.min.js”></script>

</head>

<body>

</body>

</html>

Page 33: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ScaffoldingDopoaverimpostatoilfileelastrutturadellecartelledibase,possiamoiniziarea

effettuareloscaffoldingdell’appgrazieaBootstrap.Oltreaoffrireunaseriedicomponenti,comelanavigazioneeipulsanti,chepossiamoutilizzarenell’appdigestionedeicontatti,Bootstrapproponeancheunsistemadigriglieresponsivemoltopotentedicuisfrutteremoognipotenzialità.

BarradinavigazioneAvremobisognodiunabarradinavigazione(navbar)perpassaredaunavista

all’altra.Ovviamentesaràcollocataincimaalloschermo.

Osserviamolabarradinavigazionecompletaprimadiesaminarlapiùafondo:

<navclass=”navbarnavbar-default”role=”navigation”>

<divclass=”navbar-header”>

<buttontype=”button”class=”navbar-toggle”

data-toggle=”collapse”data-target=”#nav-toggle”>

<spanclass=”icon-bar”></span>

<spanclass=”icon-bar”></span>

<spanclass=”icon-bar”></span>

</button>

<aclass=”navbar-brand”href=”/”>ContactsManager</a>

</div>

<divclass=”collapsenavbar-collapse”id=”nav-toggle”>

<ulclass=”navnavbar-nav”>

<liclass=”active”><ahref=”/”>Browse</a></li>

<li><ahref=”/add”>AddContact</a></li>

</ul>

<formclass=”navbar-formnavbar-right”role=”search”>

<inputtype=”text”class=”form-control”

placeholder=”Search”>

</form>

</div>

</nav>

Questocodicepotrebbeintimorirvi,consideratocheèquellodiuncomponentedellapaginamoltosemplice,masel’analizzateneldettaglio,noteretecheognielementoènecessario.

Iltag<nav>contienetuttociòcheèpresentenellabarradinavigazione.Alsuointernositrovanoduesezioni:navbar-headerenavbar-collapse.Questielementisonoriservatiallanavigazionemobileecontrollanociòchevienemostratoonascostodalpulsanteinterruttore.

L’attributodata-targetperilpulsantecorrispondedirettamenteall’attributoiddell’elementonavbar-collapse;inquestomodoBootstrapsachecosadeveattivare.Laprossimaschermatariproducelabarradinavigazionesudispositivipiùgrandidiuntablet.

Page 34: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Includeremolabarradinavigazionedirettamenteall’internodeltag<body>.Inquestomodooccuperemotuttalalarghezzadellafinestradelbrowser.

Selaridimensionate,vedretecheBootstrapvisualizzal’headermobileconilpulsanteinterruttoreperschermididimensioniinferioriai768px,ossialedimensionidelloschermodiuniPadconorientamentoverticale.Tuttaviasefateclicsulpulsantepermuovervinellanavigazione,vedretechenonsuccedenulla.CiòaccadeperchénonabbiamoinclusoinBootstrapilfileJavaScript,presentenelfileZIPcheabbiamoscaricatoinprecedenza.

Copiatelonelladirectoryjsdell’appefateviriferimentonelfileindex.html.DovreteincludereanchejQuerynell’applicazione,poichéilJSdiBootstrapdipendedaquesto.

Potetetrovarel’ultimaversioneall’indirizzohttp://jquery.com/;ancoraunavoltaaggiungetelaalladirectoryeincludetelanellapaginaprimadibootstrap.js.VerificatecheifileJavaScriptcompaianonelseguenteordine:

<scriptsrc=”assets/js/jquery.min.js”></script>

<scriptsrc=”assets/js/bootstrap.min.js”></script>

<scriptsrc=”assets/js/angular.min.js”></script>

Seriaggiornatelapaginadovresteriuscireafarclicsulpulsanteinterruttorepervisualizzarelanavigazioneperdispositivimobili.

Page 35: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

LegrigliediBootstrap

Ilsistemaagrigliacon12colonnediBootstrapèmoltopotenteecipermettedieffettuareloscaffoldingdellanostraappresponsiveconpochissimielementi,approfittandodelCSSmodulare.Lagrigliaècompostadarigheecolonnecheèpossibileadattareutilizzandounaseriediclassi.Primadiiniziare,dobbiamoinserireuncontenitoreperlerighe,altrimentiilframeworknonsicomporteràcomeprevisto.Èsufficienteunsemplicetag<div>dacollocaresottolabarradinavigazione:

<divclass=”container”></div>

Inquestomodolagrigliasaràcentrataeaggiungeremolaproprietàmax-widthperdisporretuttoperbene.

Esistonoquattroprefissiperleclassi,chedefinisconoilcomportamentodellecolonne.Utilizzeremoperlopiùilprefissocol-sm-,checomprimelecolonneinmodocheappaianounasopral’altraquandoilcontenitorehaunalarghezzainferiorea750px.

Lealtreclassisiriferisconotutteadiversedimensionidelloschermodeidispositiviesicomportanoinmodosimile.Laseguentetabella,trattadahttp://getbootstrap.com/,mostraledifferenzetralequattroclassi.

Cellulari(<768px)

Tablet(≥768px)

Desktop(≥992px)

Desktop(≥1200px)

Comportamentodellagriglia

Sempreorizzontale

All’iniziocompressa,orizzontalesopraibreakpoint

Larghezzamassima Nessuna

Page 36: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

delcontenitore (automatico) 750px 970px 1170px

Prefissodelleclassi .col-xs- .col-sm- .col-md- .col-lg-

Larghezzamassimadellacolonna Automatica 60px 78px 95px

Offset N/D Sì

Ordinamentodellecolonne N/D Sì

Creiamorapidamenteunlayoutaduecolonneconun’areadelcontenutoprincipaleeunabarralaterale.Siccomelagrigliaècostituitada12colonne,dovremofarsìchel’areadelcontenutorientriinesse,altrimentiavremodellospaziovuoto.

Ottocolonneperl’areadelcontenutoequattroperlabarralateraledovrebberoessereunasoluzioneottimale,macomeimplementarle?

All’internodelcontenitorecreiamounnuovotag<div>conlaclasserow.Possiamoimpostarequanterighedesideriamo;ciascunapuòcontenerealmassimododicicolonne:

<divclass=”container”>

<divclass=”row”>

</div>

</div>

Siccomevogliamochelecolonnevenganovisualizzatesudispositivimobili,utilizzeremoilprefissocol-sm-.Lacreazionediunacolonnaèsemplice;èsufficientescegliereilprefissoopportunoeaggiungereilnumerodellecolonnechesidesideraimpostare.Osservateillayoutdibaseaduecolonne:

<divclass=”container”>

<divclass=”row”>

<divclass=”col-sm-8”>

Thisisourcontentarea

</div>

<divclass=”col-sm-4”>

Hereisoursidebar

</div>

</div>

</div>

Selovisualizzatesuunoschermodidimensionisuperioriaquellodiundispositivomobile,Bootstrapaggiungeràautomaticamente30pxdispaziotralecolonne(15pxsuciascunlato).Tuttavia,talvoltavorreteinserirealtrospaziotralecolonneedistanziarleunpo’.Bootstrappermettediottenerequestorisultatoaggiungendoun’altraclasseallacolonna.

Sceglietedinuovoilprefissoopportuno,maquestavoltaaggiungetelaparolachiaveoffset:

<divclass=”col-sm-4col-sm-offset-1”></div>

Page 37: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Inquestocasoilnumeropresenteallafinecontrollailnumerodellecolonnesucuisiimpostal’offset.Lanuovaclasseaggiungeunulterioremargineasinistra.

NOTA

Ricordate: lasommadellecolonne inunariga,compreso l’offset,nondeveesseresuperiorea12.

All’internodellecolonneèpossibilenidificarealtrerigheecolonnepercreareunlayoutpiùcomplesso:

<divclass=”container”>

<divclass=”row”>

<divclass=”col-sm-8”>

<divclass=”row”>

<divclass=”col-sm-6”>

<p>Loremipsumdolor…<p>

</div>

<divclass=”col-sm-6”>

<p>Classaptenttaciti…</p>

</div>

</div>

</div>

</div>

</div>

Cosìsicreerannoduecolonneall’internodelcontenitoreprincipalecheabbiamoimpostatoprima.Atitolodiesempio,abbiamoinseritoall’internodeltestofittizio.

Nelbrowservedretecheorasonopresentitrecolonne.Tuttavia,siccomelagrigliaènidificata,possiamocreareunanuovarigaeunasolacolonna,trecolonneoquellocherichiedeillayout.

Classihelper

Bootstrapincludealcuneclassihelperchepossiamoutilizzareperadattareillayout.Ingeneresonofunzionalierispondonoaununicoscopo.Osserviamoalcuniesempi.

Elementiflottanti

GlielementiflottantisonospessoessenzialipercreareunlayoutefficacesulWeb,eBootstrapoffredueclassiperrenderemobiliglielementiasinistraoadestra:

<divclass=”pull-left”>...</div>

<divclass=”pull-right”>...</div>

Perutilizzareefficacementeglielementiflottanti,dobbiamoracchiuderliinunaclasseclearfix.Inquestomodoliisoleremo,eilflussodeldocumentoverràvisualizzatocomeprevisto:

<divclass=”clearfix”>

<divclass=”pull-left”>...</div>

<divclass=”pull-right”>...</div>

</div>

Page 38: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Seleclassifloatsitrovanodirettamenteall’internodiunelementoconlaclasserow,glielementi“mobili”vengonoisolatiautomaticamentedaBootstrapenonènecessarioapplicaremanualmentelaclasseclearfix.

Centrareglielementi

Insiemeconglielementiflottanti,spessoènecessariocentrareglielementialivellodiblocco.Bootstrappermettedifarloconlaclassecenter-block:

<divclass=”center-block”>...</div>

Inquestomodosiimpostanoleproprietàdelmarginesinistroedestrosuautomatico,el’elementosaràcentrato.

Mostrareonascondere

PotrestevolermostrareonascondereglielementiconilCSS;Bootstrapoffredueclassiperottenerequestorisultato:

<divclass=”show”>...</div>

<divclass=”hidden”>...</div>

Èimportanteosservarechelaclasseimpostalaproprietàdisplaysublock;quindiapplicatelasoltantoaglielementialivellodibloccoenonaquelliinlineoinline-block.

Bootstrapincludeinoltrenumeroseclassiperpermettereaglielementidiveniremostrationascostisuschermididimensionispecifiche.LeclassiutilizzanolestessedimensionipredefinitedellagrigliadiBootstrap.

Peresempio,ilcodiceseguentenasconderàunelementosuunoschermocondimensionispecifiche:

<divclass=”hidden-md”></div>

Nasconderàl’elementosudispositiviconschermididimensionimedie,malolasceràancoravisibilesudispositivimobili,tabletegrandidesktop.Pernascondereunelementosupiùdispositivi,doveteutilizzarepiùclassi:

<divclass=”hidden-mdhidden-lg”></div>

Leclassivisiblehannouncomportamentooppostoemostranoglielementisuschermididimensionispecifiche.Tuttavia,adifferenzadelleclassihidden,bisognaimpostareilvaloredisplay,chepuòessereblock,inlineoinline-block:

<divclass=”visible-md-block”></div>

<divclass=”visible-md-inline”></div>

<divclass=”visible-md-inline-block”></div>

Page 39: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Ovviamenteèpossibileutilizzarelediverseclassiinassociazione.Seperesempiovoletechecompaiaunelementoalivellodibloccosuunoschermopiccolo,cheinseguitodevediventareinline-block,dovreteutilizzareilcodiceseguente:

<divclass=”visible-sm-blockvisible-md-inline-block”></div>

Senonricordatelediversedimensionidelleclassi,consultateilparagrafo“LegrigliediBootstrap”.

UtilizzareledirettiveSenzasaperloabbiamogiàutilizzatociòcheAngulardefiniscedirettive.Sitratta

insostanzadipotentifunzionichepossonoesserechiamatedaunattributoodalsuostessoelemento.Angularneincludemolte.Siacheintendiamoeseguireilciclodeidati,gestireiclicoinviareiform,Angularvelocizzeràtuttequesteoperazioni.

AbbiamoutilizzatounadirettivaperinizializzareAngularsullapaginatramiteng-app,etutteledirettivecheesamineremoinquestocapitolovengonousateallostessomodo:aggiungendounattributoaunelemento.

Primadiosservarelealtredirettiveintegrate,ènecessariocrearerapidamenteuncontroller.Createunnuovofileechiamatelocontroller.js.Salvatelonelladirectoryjsall’internodelprogettoeapritelonell’editor.

ComeabbiamovistonelCapitolo1,icontrollersonosemplicifunzionistandarddelcostruttoreJSnellequalièpossibileinserireiservizidiAngularcome$scope.Diquestefunzionivienecreataun’istanzaquandoAngularrileval’attributong-controller.Inquestomodopossiamoaveremoltepliciistanzedellostessocontrollerall’internodell’applicazioneeriutilizzarebuonapartedelcodice.Questadichiarazionedifunzioneètuttociòdicuiabbiamobisognoperilcontroller:

functionAppCtrl(){

}

Percomunicarealframeworkchequestoèilcontrollercheintendiamoutilizzare,dobbiamoincluderlonellapaginadopocheAngularvienecaricato,eaggiungereladirettivang-controlleraltagdiapertura<html>:

<htmlng-controller=”AppCtl”>

<scripttype=”text/javascript”

src=”assets/js/controller.js”></script>

ng-clickeng-mouseover

Page 40: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

UnadelleoperazionifondamentalicheèpossibileeseguireconJavaScriptconsistenelgestireuneventoclic.Aquestoscoposiutilizzal’attributoonclicksuunelementoricorrendoajQueryoaunlistenerdieventi.InAngularricorreremoaunadirettiva.

Comeesempio,creeremounpulsantecheapriràunafinestradiavviso:un’operazionesemplice.Iniziamoadaggiungereilpulsanteall’areadelcontenutocreatainprecedenza:

<divclass=”col-sm-8”>

<button>ClickMe</button>

</div>

Selovisualizzatenelbrowser,vedreteunpulsanteHTMLstandard:finquinessunasorpresa.Primadiassociareladirettivaaquestoelemento,dobbiamocreareunhandlernelcontroller.Sitrattadiunasemplicefunzioneall’internodelcontrollerassociatoalloscope.Èmoltoimportanteassociarelafunzionealloscope,altrimentisaràimpossibileaccedervidallavista:

functionAppCtl($scope){

$scope.clickHandler=function(){

window.alert(‘Clicked!’);

};

}

Comesappiamo,possiamoaveremoltepliciscopesuunapagina;questisonooggettiaiqualiinAngularpossonoaccederelavistaeilcontroller.Perfareinmodocheilcontrollerviabbiaaccesso,abbiamoinseritoilservizio$scopenelcontroller.QuestoserviziometteadisposizioneloscopecheAngularcreasull’elementoalqualeabbiamoaggiuntol’attributong-controller.

Angularsibasamoltosull’inserimentodelledipendenze,cheforsepotrestenonconoscere.Comeabbiamovisto,Angularèsuddivisoinmodulieservizi.Ciascunodiquestimodulieservizidipendel’unodall’altroel’inserimentodelledipendenzeconsentelatrasparenzareferenziale.Duranteiltestdell’unità,possiamoanchesimularedeglioggetticheverrannoinseritiperconfermareirisultatideitest.L’inserimentodelledipendenzecipermettedidireadAngulardaqualiservizidipendeilcontroller,eilframeworkliconvertiràpernoi.

Potetetrovareunaspiegazionedettagliatasull’inserimentodelledipendenzediAngularJSnelladocumentazioneufficialeall’indirizzohttps://docs.angularjs.org/guide/di.

Oral’handlerèimpostato;comeabbiamofattoinprecedenza,dobbiamoaggiungereladirettivaalpulsante,comeattributoaggiuntivo.Questavoltapasseremoilnomedellafunzionecheintendiamoeseguire,cheinquestocasoèclickHandler.Angularvaluteràtuttociòcheinseriremonelladirettivacomeespressione

Page 41: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

diAngularJS;pertantodobbiamofareattenzioneadaggiungeredueparentesicheindicanochestiamochiamandounafunzione:

<buttonng-click=”clickHandler()”>ClickMe</button>

Selovisualizzatenelbrowser,vedreteunafinestradiavvisoquandofareteclicsulpulsante.Nonènecessarioincluderelavariabile$scopequandosichiamalafunzionenellavista.Lefunzionielevariabiliallequalièpossibileaccederedallavistarimangonoall’internodelloscopecorrenteodiqualsiasiscopeprecedente.

Sedesideratevisualizzarelafinestradiavvisoall’hover(cioèalpassaggio)invecechealclic,èsufficientemodificareilnomedelladirettivainng-mouseover,poichéentrambefunzionanonellostessomodo.

ng-init

Ladirettivang-initvalutaun’espressionesulloscopecorrenteepuòessereutilizzatadasolaoinassociazioneconaltredirettive.Laprioritàdiesecuzioneèmassimarispettoadaltredirettive,perfareinmodochel’espressionevengavalutataintempo.

Eccounsempliceesempiodelladirettivang-initinazione:

<divng-init=”test=‘Hello,World’”></div>

{{test}}

InquestomodocompariràsulloschermoHello,Worldquandol’applicazionesaràcaricatanelbrowser.Sopraabbiamoimpostatoilvaloredelmodelloditesteutilizzatolasintassiconledoppieparentesigraffepervisualizzarlo.

Page 42: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ng-showeng-hide

Talvoltadovremocontrollarelavisualizzazioneprogrammatadiunelemento.Siang-showsiang-hidepossonoesserecontrollatedalvalorerestituitodaunafunzioneodaunmodello.

PossiamoavvalercidellafunzioneclickHandlercheabbiamocreatopermostrareinazioneladirettivang-clickalfinedirenderevisibileonasconderel’elemento.Aquestoscopocreeremounnuovomodelloealterneremoilvaloretraveroefalso.

Creiamol’elementochemostreremoenasconderemo.Immetteteilseguentecodicesottoilpulsante:

<divng-hide=”isHidden”>

Clickthebuttonabovetotoggle.

</div>

Ilvalorenell’attributong-hideèilnostromodello.Siccomeècompresonelloscope,possiamofacilmentemodificarlonelcontroller:

$scope.clickHandler=function(){

$scope.isHidden=!$scope.isHidden;

};

Quistiamoinvertendoilvaloredelmodello,cheasuavoltarendevisibileomenoil<div>.

Seloapritenelbrowser,vedretechel’elementoènascostoperimpostazionepredefinita.Esistonoalcunisistemipergestirequestoaspetto.Potremmoimpostareilvaloredi$scope.hiddensutruenelcontroller,oppureimpostareilvaloredihiddensutrueutilizzandoladirettivang-init.Altrimentièpossibilericorrerealladirettivang-showchehauncomportamentocontrariorispettoang-hideerenderàvisibileunelementoseilvalorediunmodelloèimpostatosutrue.

NOTA

Verificate cheAngular sia caricato nell’header, altrimenti ng-hide e ng-show non funzionerannocorrettamente.QuestoperchéAngularutilizzalesueclassipernascondereglielementiequestedevonoesserecaricatealrenderingdellapagina.

ng-ifAngularincludeancheunadirettivang-ifchesicomportainmodosimileang-showe

ng-hide.Tuttaviang-ifeliminal’elementodalDOM,mentreng-showeng-hiderendonovisibiliomenoglielementi.

Osserviamorapidamentecomeèpossibileutilizzareng-ifnelcodiceprecedente:

Page 43: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

<divng-if=”isHidden”>

Clickthebuttonabovetotoggle.

</div>

Sevolessimoinvertireilsignificatodell’istruzione,sarebbesufficienteaggiungereunpuntoesclamativoprimadell’espressione:

<divng-if=”!isHidden”>

Clickthebuttonabovetotoggle.

</div>

ng-repeat

Benpresto,durantelosviluppodiunawebapp,avretebisognodirappresentareunarraydiitem.Peresempio,nell’appdigestionedeicontatti,potrebbeessereunelencodicontatti,oqualsiasialtracosa.Angularconsentediraggiungerequestoscopoconladirettivang-repeat.

Vediamounesempiodialcunidatichepotresteincontrare.Sitrattadiunarraydioggetticonmoltepliciproprietàalsuointerno.Pervisualizzareidati,dovremoriuscireadaccedereaogniproprietà.ng-repeatserveaquestoscopo.

Eccoilcontrollerconunarraydioggettidelcontattoassegnatialmodellodeicontatti:

functionAppCtrl($scope){

$scope.contacts=[

{

name:‘JohnDoe’,

phone:‘01234567890’,

email:‘[email protected]

},

{

name:‘KaranBromwich’,

phone:‘09876543210’,

email:‘[email protected]

}

];

}

Inquestocasoabbiamosoloduecontatti,macomepoteteimmaginare,un’APIpotrebbeservirnecentinaiachenonsarebbepossibilegestiresenzang-repeat.

Aggiungeteunarraydicontattialcontrollereassegnateloa$scope.contacts.Apriteilfileindex.htmlpercreareuntag<ul>.Ripeteremounavocepresenteinquestoelencononordinato,quindiquestoèl’elementoalqualedobbiamoaggiungereladirettiva:

<ul>

<ling-repeat=”contactincontacts”></li>

</ul>

Page 44: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

SesapetecomefunzionanoicicliinPHPoRuby,visentireteavostroagio.Createunavariabileallaqualepoteraccedereall’internodell’elementocorrentecheentranelciclo.Lavariabiledopolaparolachiaveinfariferimentoalmodellocheabbiamocreatosu$scopenelcontroller.Cosìèpossibileaccedereaqualsiasiproprietàimpostatasull’oggetto,eogniiterazioneoitemripetutiacquisisconounnuovoscope.PossiamovisualizzarlisullapaginautilizzandolasintassidelledoppieparentesigraffediAngular,comeabbiamovistonelCapitolo1:

<ul>

<ling-repeat=”contactincontacts”>

{{contact.name}}

</li>

</ul>

Cosìverràvisualizzato,comeprevisto,ilnomeall’internodellavocedell’elencoesaràpossibileaccederefacilmenteaqualsiasiproprietàdell’oggettodelcontattofacendoriferimentoaessotramitelasintassiapuntostandard.

ng-class

Spessocapitadivolermodificareoaggiungereunaclasseaunelemento.Aquestoscopopossiamoricorrerealladirettivang-class,perdefinireunaclassedaaggiungereodaeliminareinbasealvalorediunmodello.

Esistonoduesistemiperutilizzareng-class.Nellasuaformapiùsemplice,AngularapplicheràilvaloredelmodellocomeclasseCSSall’elemento:

<divng-class=”exampleClass”></div>

Seilmodelloalqualefacciamoriferimentoèindefinitoofalso,Angularnonapplicheràlaclasse.Questosistemaèottimoperlesingoleclassi,masevolessimoaveremaggiorecontrollooapplicarepiùclassiaunsoloelemento?Provatequestocodice:

<divng-class=”{className:model,class2:model2}”></div>

Inquestocasol’espressioneèunpo’diversa.Disponiamodiuninsiemedinomidiclassieilmodelloconilqualeconfrontarlo.Seilmodellorestituiscetrue,laclasseverràaggiuntaall’elemento.

Osserviamoloinazione.Utilizzeremolecaselledicontrolloconl’attributong-modelcheabbiamogiàesaminatonelCapitolo1perapplicarealcuneclassiaunparagrafo:

<png-class=”{‘text-center’:center,‘text-danger’:error}”>

Loremipsumdolorsitamet

</p>

Page 45: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

HoaggiuntodueclassiBootstraptext-centeretext-danger.Questeesaminanounpaiodimodelli,chepossiamomodificarerapidamenteconalcunecaselledicontrollo:

<label><inputtype=”checkbox”ng-model=”center”>text-

center</label>

<label><inputtype=”checkbox”ng-model=”error”>text-

danger</label>

NOTA

Levirgolettesemplicicheracchiudonoinomidelleclassinell’espressionesononecessariesoloquandosiutilizzanoitrattini(-),altrimentiAngulargeneraunerrore.

Quandoquestecaselledicontrollosonospuntate,leclassiopportunevengonoapplicateall’elemento.

ng-style

Inmodosimileang-class,questadirettivaciconsentediassegnaredinamicamenteunostileaunelementoconAngular.Atitolodiesempiocreeremounaterzacaselladicontrollocheapplicheràaltristiliall’elementoparagrafo.

Ladirettivang-styleutilizzaunoggettoJavaScriptstandard,eleparolechiavesarannolaproprietàcheintendiamomodificare(peresempiocoloreesfondo).Questosipuòapplicaredaunmodelloounvalorerestituitodaunafunzione.

Esaminiamocomeassociarloaunafunzionecheverificheràunmodello.Poipossiamoaggiungerloallacaselladicontrollopercambiareglistili.

Apriteilfilecontroller.jsecreateunanuovafunzioneassociataalloscope.QuilachiameremostyleDemo:

$scope.styleDemo=function(){

if(!$scope.styler){

return;

}

return{

background:‘red’,

fontWeight:‘bold’

};

};

All’internodellafunzionedobbiamoverificareilvalorediunmodello;inquestoesempiosichiamastyler.Seèfalso,nonrestituirànulla,altrimentirestituiràunoggettoconleproprietàCSS.AbbiamoutilizzatofontWeightinvecedifont-weightnell’oggettorestituito.EntrambivannobeneeAngularapplicheràautomaticamentelasintassicamelcasenellacorrettaproprietàCSS.Ricordatechequandosiutilizzano

Page 46: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

itrattininelleparolechiavedeglioggettiJavaScript,questevannoracchiusetravirgolette.

Questomodellosaràassociatoaunacaselladicontrollo,comeabbiamofattoconng-class:

<label><inputtype=”checkbox”ng-model=”styler”>ng-style</label>

L’ultimacosachedobbiamofareèaggiungereladirettivang-styleall’elementodelparagrafo:

<p..ng-style=”styleDemo()”>

Loremipsumdolorsitamet

</p>

Angularèingradodirichiamarequestafunzioneognivoltachecambialoscope.Ciòsignificachenonappenailvaloredelmodellocambiadafalseatrue,verrannoapplicatiglistilieviceversa.

ng-cloak

L’ultimadirettivacheesamineremoèng-cloak.QuandoutilizzateitemplatediAngularinunapaginaHTML,vengonovisualizzatetemporaneamenteledoppieparentesigraffeprimacheAngularJSabbiafinitodicaricareecompilaretuttosullapagina.Perovviareaquestocomportamento,dobbiamonasconderetemporaneamenteiltemplateprimacheterminiilrendering.

Angularconsentedifarloconladirettivang-cloak,cheimpostaunulteriorestilesull’elementomentrevienecaricato,ovverodisplay:none!important;.

NOTA

Per evitare il flashing durante il caricamento del contenuto, è importante che Angular vengacaricatonellasezioneheaddellapaginaHTML.

Page 47: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. Checosaaggiungiamoincimaallapaginaperpoterpassaredaunavista

all’altra?2. QuantecolonnecomprendeilsistemaagrigliadiBootstrap?3. Checos’èunadirettivaecomevieneutilizzatalamaggiorpartediesse?4. Qualedirettivadobbiamoutilizzarepereseguireilciclodeidati?

Page 48: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoInquestocapitoloabbiamoaffrontatomoltiargomenti;primadiproseguireconil

prossimo,riepiloghiamoli.

Bootstrapciconsentedicrearerapidamenteunanavigazioneresponsive.DobbiamoincludereilfileJavaScriptpresentenellaversionediBootstrapcheabbiamoscaricatoperrenderedisponibileilpulsanteinterruttoreperlanavigazionemobile.

AbbiamoancheesaminatoilpotentesistemaagrigliaresponsiveinclusoinBootstrapecreatounsemplicelayoutaduecolonne.Durantequestaoperazioneabbiamoanalizzatoiquattrodiversiprefissidelleclassiperlecolonneenidificatolagriglia.Peradattareillayoutabbiamoscopertoalcuneclassihelperinclusenelframeworkcheciconsentonodirenderemobili,centrareenascondereglielementi.

AbbiamoesaminatoindettaglioledirettiveintegrateinAngular,lefunzionicheèpossibileutilizzaredallavista.Primadiosservarleinazione,abbiamocreatouncontroller,ossiaunafunzioneincuipossiamopassareiservizidiAngularsfruttandol’inserimentodelledipendenze.

Ledirettivecheabbiamodescrittosarannofondamentalimanmanochesvilupperemol’appdigestionedeicontattinelcorsodellibro.Direttivecomeng-clickeng-mouseoversonoinsostanzanuovisistemipergestireglieventi,operazionecheavetesicuramentesvoltoconjQueryovanillaJavaScript,madirettivecomeng-repeatrappresenterannoforseunmodotuttonuovodilavorare,cheintrodurràunalogicanellavistapereseguireilciclodeidatievisualizzarlisullapagina.

Abbiamoancheanalizzatoledirettivechevalutanoimodellinelloscopeecompionodiverseazionisullabasedeilorovalori.ng-showeng-hidemostranoonascondonounelementosullabasedelvalorediunmodello.Loabbiamovistoancheconng-class,checihapermessodiaggiungeredelleclassiaglielementisullabasedeivalorideimodelli.

Page 49: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo3

Page 50: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Ifiltri

NelcapitoloprecedenteabbiamoesaminatounodeicomponentifondamentalidiAngularJS:ledirettive.Comemoltiframework,Angularoffrealtriparadigmicheciaiutanoasviluppareleapp.Ifiltripermettonodimanipolareeordinarefacilmenteidatidallavistaodalcontroller,ecomeperledirettive,neesistonoalcuniefficacigiàintegrati.

Sipossonoapplicareinmolticasieinquestocapitoloneesamineremoalcuni.Peresempio,èpossibilemanipolareunastringa,convertendola,localizzandolaotroncandola.IfiltriconsentonoanchedioperareconaltritipiJavaScript,comearrayeoggetti.Forsevicapiteràdiimpostareunaricercaperfiltrareunsetdidatidicuiaveteeseguitoilciclousandong-repeat.Tuttoquestoèpossibileconifiltri.

Primadiosservarealcunifiltriinclusi,esamineremocomeèpossibileapplicareunfiltrodallavista.

Page 51: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ApplicareunfiltrodallavistaÈpossibileapplicareifiltridirettamentealleespressioniall’internodeitemplate.

Ricordatecheun’espressioneètuttociòcheècompresoall’internodellasintassicondoppieparentesigraffeodiunadirettiva:

{{expression|filter}}

Èfacileservirsidiunfiltro;èsufficienteaggiungereilsimbolopipe(|)seguitodalnomedelfiltrocheintendiamoapplicareall’espressione.Possiamoprocedereallostessomodoperapplicarepiùfiltriaunasolaespressione.Èpossibileconcatenarnepiùdiunoeapplicarliinsequenza.Nell’esempioseguente,filter2verràapplicatoall’outputdelfilter1ecosìvia:

{{expression|filter1|filter2|filter3}}

Alcunifiltripossonoaveredegliargomenti,chesipossonoapplicarericorrendoaunasintassisimile:

{{expression|filter:argument1:argument2}}

InquestocapitoloillustreremoalcunifiltriinclusiinAngulardirettamentedallavistautilizzandolasintassicheabbiamoesaminato.Vedremocomeapplicareglistessifiltridalcontrollerecomecrearneuno.

CurrencyenumberIlprimofiltrocheanalizzeremoformattainumeriinvaluta.Nellaversione

localizzatabritannica-americana,aggiungealpostogiustounavirgolapersepararelemigliaiadaidecimali.Lifaancheprecederedalsimboloopportuno:

{{12345|currency}}

Ilsimbolodellavalutadipenderàdallaversionelocalizzata.Seutilizziamoquellabritannica-americana,perimpostazionepredefinita,Angularanteponeilsimbolodeldollaro($),mapossiamopassareilsimbolodanoisceltocomeargomento:

{{12345|currency:’£’}}

Èimportantericordarsidiracchiuderlotravirgolette,comesefosseunastringa.

Angularincludeancheunsecondofiltroperformattareinumeri,checioffremaggiorecontrollo;ciconsentedispecificareilnumerodicifredecimaliacuivogliamoarrotondareilnumero:

{{12345.225|number:2}}

Page 52: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

L’outputdiquestofiltrosarà12,345.23.Comepoteteosservare,ilnumeroèstatoarrotondatoaduedecimaliedèstataaggiuntaunavirgolapersepararelemigliaia.

LowercaseeuppercaseQuestiduefiltrisonoforseipiùsempliciinclusiinAngular.Convertonolastringa

inminuscoloomaiuscolo:

{{‘Stephen’|lowercase}}

{{‘Declan’|uppercase}}

L’outputdiquestifiltrièilseguente:

stephen

DECLAN

limitToInalcunicasipotrestevolerlimitareilnumerodicaratteridiunastringaodiun

array;questorisultatosipuòottenerefacilmenteinAngularJSutilizzandoilfiltrolimitTo:

{{‘Loremipsumdolorsitamet’|limitTo:15}}

Questofiltroaccettaunsoloargomento,cheèilnumerodicaratterialqualedovrebbelimitarsil’input.Inquestocasoabbiamolimitatoicaratteridiunastringa,mapotrebbetrattarsidiunarrayinunadirettivang-repeat,peresempio:

<divng-repeat=”array|limitTo:2”></div>

DateQuandosioperaconidatidaunaAPI,spessoladatavienefornitacomeoraUNIX

ocometimestampcompleto.Nonèmoltocomodo,mafortunatamenteAngularincludeunsistemasempliceperformattareledateconunfiltro:

{{expression|date:format}}

Questofiltroaccettaunargomento:format.Peresempio,seabbiamountimestampeintendiamoottenerel’anno,potremmoraggiungerefacilmentequestorisultatoconl’espressioneseguente:

{{725508723000|date:’yyyy’}}

Page 53: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Possiamocombinarloconl’inputgiornomeseeavremofacilmenteunastringadidatastandard:

{{725508723000|date:’dd/MM/yyyy’}}

Eccounelencodialcunideglielementipiùutilidacuipuòesserecostituitalastringaformat.UnelencocompletosipuòtrovaresulsitodiAngularJS.

Elemento Output Esempio

yyyy Annoinquattrocifre 2013

yy Annoinduecifre 13

MMMM Meseperesteso Dicembre

MMM Meseabbreviato Dic

MM Meseprecedutodazero 01

M Meseinnumero 1

dd Giornoprecedutodazero 01

d Giornoinnumero 1

EEEE Giornodellasettimana Lunedì

EEE Giornoabbreviatodellasettimana Lun

HH Oranelformato24oreprecedutadazero 01

H Oranelformato24ore 1

hh Oranelformato12oreprecedutadazero 01

h Oranelformato12ore 1

mm Minutoprecedutodazero 05

m Minuto 5

ss Secondoprecedutodazero 09

s Secondo 9

a AM/PM AMoPM

Z Fusoorario +0100

ww(solo1.3+) Settimanadell’annoprecedutadazero 03

w(solo1.3+) Settimanadell’anno 3

Esistonoinoltrealcuniformatipredefinitichepossiamoutilizzare;esaminiamoneuno:

{{725508723000|date:’medium’}}

Laparolachiavemediumèsolounodeiformatididefaultchequestofiltroriconosce,egeneraDec28,19922:12:03AM.

Eccounelencocompletodeiformatipredefinitiaccettatidalfiltrodate.

Parolachiave Equivalente Esempiomedium MMMd,yh:mm:ssa Sep3,201012:05:08pm

Page 54: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

short M/d/yyh:mma 9/3/1012:05pm

fullDate EEEE,MMMMd,y Friday,September3,2010

longDate MMMMd,y September3,2010

mediumDate MMMd,y Sep3,2010

shortDate M/d/yy 9/3/10

mediumTime h:mm:ssa 12:05:08pm

shortTime h:mma 12:05pm

Possiamoancheincluderevaloriletteralinellastringadelformato;peresempio:

{{725508723000|date:”h‘inthemorning’”}}

Ivaloriletteralidevonoessereracchiusitravirgolettesemplici.Dobbiamoquindicambiarelevirgolettesemplicicheracchiudonol’argomentoconlevirgolettedoppie.Sevolesteincluderenellastringaunasolavirgoletta,dovresteutilizzareduevirgolettesemplici:

{{725508723000|date:”h‘o’’clock’”}}

FilterQuestofiltro,conunnomechepuògenerareconfusione,consentediselezionare

facilmenteunsetsecondariodiiteminunarray.All’internodellavistaèpossibileutilizzarlocombinatoconladirettivang-repeatcheabbiamoillustratonelcapitoloprecedente.

Conessopossiamosviluppareunostrumentodiricercapotentechefiltreràl’array.Esaminiamol’esempiong-repeatdelCapitolo2:

<ul>

<ling-repeat=”contactincontacts”>

{{contact.name}}-{{contact.phone}}

</li>

</ul>

Primadiaggiungereilfiltro,dobbiamoaggiungerel’oggettopatternchesaràutilizzatoperlaselezionedall’array.Puòessereunmodello,unastringa,unoggettopatternounafunzione.Mentrecreiamounaricerca,aggiungiamounmodelloauninputditesto:

<inputtype=”text”ng-model=”search”>

Nonrestacheassociareilmodelloalladirettivang-repeat.Lopotetefarecomeconqualsiasialtrofiltro:inseriteunpipeseguitodalnomedelfiltro.Inquestocasodobbiamoancheaggiungereunargomentocheindicaalfiltroqualemodello,stringa,oggettoofunzioneintendiamoutilizzare:

Page 55: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

<ling-repeat=”contactincontacts|filter:search”>

Cosìpossiamoservircidelcampoditestochecreiamopereffettuarequalsiasiricercanell’array,checomprendenomi,numeriditelefonoeindirizzie-mail.Tuttavia,checosasuccedeseintendiamorestringerelaricercasoltantoallaproprietànamedeinostrioggetti?Èsufficientecambiareilmodello:

<inputtype=”text”ng-model=”search.name”>

Èimportantechelasciamoilnomedelmodelloding-repeatsusearch,altrimentiilfiltrononsilimiteràallaproprietàdesiderata.

Inalternativapotremmoutilizzarelasintassiseguenteperladirettivang-repeatperlimitareilfiltroaproprietàspecifiche.Inquestocasopossiamolasciareilnomedelmodellosusearch:

<ling-repeat=”contactincontacts|filter:{‘name’:search}”>

orderByOltreafiltrarel’oggettoall’internodelladirettivang-repeat,possiamoanche

ordinarlo.Èun’ottimasoluzioneseidatifornitidaunarraynonsonogiàordinatiosenonesisteun’opzioneperfarlo.

Attualmentel’oggettoètuttoconfusoenonpresentaalcunordineapparente.Osserviamocomepossiamoordinarlopernome:

<ling-repeat=”contactincontacts|filter:search|

orderBy:’name’”>

Ilprimoargomentochepossiamopassareèunastringaconilnomedellaproprietàinbaseallaqualeintendiamoordinarel’array.Sevolessimofiltraresecondoilnumeroditelefonool’indirizzoe-mail,potremmopassarequestivalori.

Possiamoanchepassareunsecondoargomentoattraversounbooleanochecontrollaseilfiltrodeveinvertirel’ordineomeno:

<ling-repeat=”..|orderBy:’name’:true”>

JSONL’ultimofiltroinclusoservesoprattuttoperildebugging.Trasformeràqualsiasi

oggettoJavaScriptinunastringaJSONperlavisualizzazionesullapagina.

Page 56: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Prendiamol’arraydicontatticheabbiamoutilizzatonelcapitoloprecedentepermostrareinazioneng-repeateapplichiamoilfiltrojson:

{{contacts|json}}

Ciòchesegueèl’outputdellavista:

[

{

“name”:”JohnDoe”,

“phone”:”01234567890”,

“email”:”[email protected]

},

{

“name”:”KaranBromwich”,

“phone”:”09876543210”,

“email”:”[email protected]

},

{

“name”:”DeclanProud”,

“phone”:”2341234231”,

“email”:”[email protected]

},

{

“name”:”PaulMcKay”,

“phone”:”912345678”,

“email”:”[email protected]

}

]

Comepotetevedere,èunasemplicerappresentazioneJSONdell’arraydioggetticreatoinprecedenza.

Page 57: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ApplicareifiltridaJavaScriptTalvoltavorreteapplicareunfiltroutilizzandoJavaScript,disolitodalcontroller;è

importantecapirecomepossiamoottenerequestorisultato,tramitedueopzioni.

Possiamoinserireilservizio$filternelcontrollereutilizzarequalsiasifiltroinclusonell’applicazione.Inalternativapossiamoinserireilfiltrocomesuoserviziodedicatoeutilizzarlodasolo.Entrambiimetodisonoperfettamentevalidiespettaavoisceglierequellochepreferite.

Esaminiamoliricorrendoinnanzituttoalservizio$filter.Consideriamoilfiltrojsoncheabbiamoappenavistoeutilizziamoconsole.logsullostessoarray.Inseriamoilservizionelcontroller:

functionAppCtl($scope,$filter){

}

Ottimo!Orapossiamoutilizzarlocosìcomefacciamocon$scope.Aquestofineèsufficientechiamarlocomeunafunzioneepassareilnomedelfiltrochedesideriamousare,chenelnostrocasoèjson:

$filter(‘json’);

Lastringarestituisceilfiltrostesso;possiamovederlonell’outputseapplichiamodirettamentelasintassiconsole.log.Ciòsignificachepossiamochiamareimmediatamentelafunzioneaggiungendounasecondaseriediparentesisubitodopo:

$filter(‘json’)($scope.contacts);

Comesappiamo,ilfiltrojsonnonaccettaargomenti.Tuttaviailprimoargomentodituttelefunzionideifiltrièinrealtàl’input.NonlovediamoquandolechiamiamodallavistapoichéAngularoperalasuamagiadietrolequintepersemplificarelecose.

Seracchiudetel’espressioneprecedenteinunaconsole.log,vedretechel’outputèidenticoaquellonellavistautilizzandolostessofiltro:

Page 58: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Inalternativa,senonvoletericorrerealservizio$filter,poteteinserireognifiltroseparatamentecomeunservizio.NelpatternvengonochiamatifilternameFilter.Perilnostroesempio,dobbiamoinserirejsonFilter:

functionAppCtl($scope,jsonFilter){

}

Puòessereutilizzatoallostessomododellafunzionerestituitadalservizio$filter,cosìdapermettercidipassarel’oggettodafiltrare:

jsonFilter($scope.contacts);

Orachesappiamocomeutilizzareifiltridalcontroller,vediamocomecrearneuno.

Page 59: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

SviluppareunfiltroComeabbiamovisto,ilfiltrolimitToèutilissimopertroncarestringheditesto.Ho

sempresentitolanecessitàdiunfiltrocheaggiungessedeipuntinidisospensionenelcasoincuiunastringasuperasseillimite.

FortunatamenteAngularciconsentediestendereifiltriinclusiesvilupparneunonuovo.

ModuliAquestoscopodobbiamocreareciòchevienechiamatomodulo.Essociconsente

diassociareunfiltroeutilizzarlonellevisteoneicontroller.LadocumentazionediAngularJSspiegaperfettamentecos’èunmodulo:

Sipuòpensareaunmodulocomeauncontenitoreperlediversepartidiun’app:controller,servizi,filtri,direttiveecosìvia.

Maperchédovremmoutilizzarneuno?Cisonounpaiodimotivi.Laragionepiùimportantechegiustificalaloroesistenzaèlafacilitàconcuièpossibilecrearecodiceriutilizzabile.

Immaginatedistarlavorandosuunapiattaformadiblogging.Potrestesviluppareunmodulodestinatoaunmediabrowseroaunmediauploader.Conterrebbeunaseriedicontroller,serviziefiltri,tuttiinsieme.Sevolesteutilizzarequestomediabrowserinunaltroprogetto,potrestesemplicementecopiareilmodulo.

Esistonoaltrimotiviperutilizzareimoduli.Sesicollaudal’unità,èsufficientecheitestcarichinosoloimodulipertinentiperassicurarelarapiditàdell’operazione,eilcodicediventapiùsemplicedacomprendereeseguireperchéognicomponenteèbeninseritotraglialtrielementi.

Creareunmodulo

Èmoltofacilecreareunmodulo;ciconsentediampliareilcoreperchéAngularnonammetteifiltripersonalizzatisenzalacreazionediunmodulo.InquestocasorealizziamounnuovomodulochiamatocontactsMgr.Ilsecondoargomentoèunsemplicearrayvuoto.Possonoesserciquantimodulidesideriamoelipossiamoincluderecomedipendenze,maperilmomentoquestololasceremovuoto:

angular.module(‘contactsMgr’,[]);

Page 60: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Tuttaviaènecessarioinserireunapiccolamodificanelmodoincuivieneaggiuntoilcontroller.Attualmenteèsolounafunzione,maènecessarioaggiungerloalmoduloperchéAngularlopossarecuperare:

angular.module(‘contactsMgr’,[])

.controller(‘AppCtl’,function($scope,jsonFilter){

});

Possiamoconcatenareicontrollernelmodulo.Avretenotatocheènecessarioutilizzareilmetodocontroller.Ilprimoargomentoèilnomedelcontroller,mentreilsecondoèlafunzionedicallbackconiserviziinseriti.

Seoracaricatel’app,vedretechenullafunzionacomeprevistoenonvienetrovatalafunzionedelcontroller.QuestoperchénonabbiamoindicatoadAngularqualemodulodesideriamoutilizzare.Ènecessarioaggiungereilnomedelmoduloalladirettivang-app:

<htmllang=”en”ng-app=”contactsMgr”ng-controller=”AppCtl”>

Unavoltainserito,tuttodovrebbeiniziareafunzionareperilversogiusto.Orastiamoutilizzandoilmoduloappenacreato.

CreareunfiltroDopoavercreatoilmoduloeaverlovistoinazione,possiamolavoraresulfiltro

limitTomigliorandolo.Convienepensareinnanzituttoalleoperazionichevorremosvolgesse.Possiamosuddividerelefunzioniinpochibrevipassi.

Consideral’inputconunsoloargomentoperillimite.Verificalalunghezzadell’inputrispettoallimite.Sel’inputèmaggioredellimite,troncalastringaeaggiungedeipuntinidisospensione.Altrimentirestituiscel’input.

Operandoconimodelli,lacreazionediunfiltrorisultamoltosimileallacreazionediuncontroller:

.filter(‘truncate’,function(){

});

Propriocomeabbiamofattoquandoabbiamospostatoilcontrollersuunnuovomodulo,utilizziamounnuovometodocheaccettadueargomenti:ilnomedelfiltroe

Page 61: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

unafunzionedicallback.Comevistoquandoabbiamoapplicatoifiltridalcontroller,quandosichiamaunfiltro,essorestituisceunasecondafunzione,chedobbiamoaggiungerequi:

.filter(‘truncate’,function(){

returnfunction(){

};

})

Abbiamoanchescopertocheilprimoargomentodiunfiltroèsemprel’inputoidatichefiltreremo.All’internodiquestafunzionepossiamoancheincludereargomentiaggiuntivi.Nelcasoditruncate,occorreunargomentoperindicarealfiltroaquanticaratteridovrebbelimitarelastringa:

.filter(‘truncate’,function(){

returnfunction(input,limit){

};

})

Lacostruzionedelfiltroècompletaeorapossiamoutilizzarlonellostessomododeglialtrifiltriesaminatiinprecedenza.Ovviamentenonabbiamoimpostatoalcunalogicaenonvienerestituitonulladallafunzionefiltro;pertantononverràvisualizzatonullasullapagina.

Oradobbiamoverificarelalunghezza,troncarelastringaeaggiungeredeipuntinidisospensione.Sipossonoottenerequestirisultatiinunastringagrazieaun’istruzioneternaria:

return(input.length>limit)?input.substr(0,limit)+’…’:

input;

Verifichiamolalunghezzadellastringa,eseèsuperioreallimite,latagliamoeaggiungiamodeipuntinidisospensione.Senonsoddisfalanostracondizione,verràrestituitol’inputoriginario.QuestoèimportanteperchéAngularnonvisualizzerànullasenonvienerestituitonulladalfiltro.

Assembliamoiltuttoedesaminiamolafunzionecompleta:

.filter(‘truncate’,function(){

returnfunction(input,limit){

return(input.length>limit)?input.substr(0,limit)+’…’

:input;

};

})

PossiamoutilizzareilnuovofiltronellostessomododelfiltrolimitTointegrato;sostituiamoloeosserviamoilrisultato:

{{‘Loremipsumdolorsitamet’|truncate:15}}

Comeprevisto,oral’outputincludedeipuntinidisospensione,mentreinprecedenzalastringaeratroncatadopoillimite.

Page 62: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. Comesipuòapplicareunfiltrodallavista?2. Inchemodopassiamogliargomentialfiltrodallavista?3. Qualefiltrodovremmoutilizzarepercreareunalivesearch?4. Comepossiamoutilizzareunfiltrodalcontroller?5. Checosadobbiamocreareprimadisviluppareunfiltro?

Page 63: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoOradovresteconoscerelafunzioneelagrandeutilitàdeifiltri,mariepiloghiamo

tuttociòcheabbiamoaffrontatoinquestocapitolo.

Abbiamoiniziatoaosservarecomevieneapplicatounfiltrodirettamentedallavistautilizzandolasintassicheprevedel’usodelpipeelaseparazionedegliargomenticonduepunti.Dopoaveranalizzatolebasi,abbiamoesaminatoinumerosifiltriinclusi.

Alcunisonofondamentalienonrichiedonoalcunargomento,macenesonoanchedipiùavanzaticheconsentonodiordinareofiltrareunarraydioggetti.

Oltreadapplicareifiltridallavista,abbiamoancheconsideratoiduemetodiperfiltraredalcontroller.Possiamoutilizzareilservizioincluso$filterodeciderediinserireifiltriseparatamente.

InfineabbiamovistocomeestendereAngularpercreareunfiltroalfineditagliareunastringaditesto.Primaperòabbiamovistocomecreareunmodulochecontenesseifiltrieicontroller.Dopoaverlorealizzato,siamoriuscitiacreareunfiltroeautilizzarlonellostessomododiquelliintegrati.

AbbiamoaffrontatomoltiparadigmieconcettifondamentalidiAngular.Nelprossimocapitolovedremocomeimpostareilsistemadiroutingpergestiremolteplicivisteecontrollerperl’appdigestionedeicontatti.

Page 64: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo4

Page 65: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Routing

Tuttelewebappsonocostituitedapiùpagineoviste,eAngularhatuttelecarteinregolapergestirequestoaspettoconilrouter(intesocomesistemadirouting,enoncomedispositivofisico).Forseconosceteilsistemadiroutingneiframeworklatoserver,comeRubyonRailsoLaravel.Angularèinteramentelatoclient,etuttalamagiaaccadeall’internodelfileHTMLalqualepuntailbrowser.Inquestocapitoloesamineremocomecreareroutestatichecontenentideiparametri.Individueremoinoltrealcuneinsidienellequalipotresteimbattervi.

Primadiiniziareelenchiamoleroutecheoccorrerannoperl’appdigestionedeicontatti.

Index:saràlapaginaprincipale,cheelencheràtuttiicontattiinunatabella.ViewContact:quipotremovisualizzareilcontattoneldettaglioemodificarequalunqueinformazionecorrelata.AddContact:includeràunformcheciconsentiràdiaggiungereuncontattoalgestore.

Questesonoleroutefondamentali;vediamocomecrearle.

Page 66: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

InstallarengRouteFindaAngularJS1.2,ilroutersièpresentatocomeunmoduloseparatoedesterno

rispettoaicomponentifondamentalidiAngular.Ilfilechecioccorre,angular-route.min.js,puòesserescaricatodalsitowebdiAngularnellasezioneExtrasall’internodellafinestradidownload.

Dopoaverloscaricato,trascinatelonelladirectoryjsdelprogettoeincludetelonellapaginadopoAngularJS:

<scriptsrc=”assets/js/angular-route.min.js”></script>

Inoltreènecessariocomunicarealmodulocheintendiamoutilizzareilrouter;dobbiamoquindiaggiungerloallalistadelledipendenzedelmodulo.Possonoesserepresentiquantedipendenzedesideriamo;peroraèsufficienteincluderengRoute:

angular.module(‘contactsMgr’,[‘ngRoute’])

Page 67: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

CreareroutedibaseComesappiamo,perconfigurareilrouterall’internodiAngularJS,ènecessarioun

modulo.NelCapitolo3neabbiamocreatounoalfinedisviluppareunfiltropersonalizzato.Possiamoutilizzarequestostessomoduloperleroute.

Leroutevengonocreatenelmetodoconfigdelmodulodell’applicazione:

angular.module(‘contactsMgr’,[‘ngRoute’])

.config(function($routeProvider){

})

Ilmetodoaccettaunafunzioneanonimaincuiinserireilservizio$routeProvidernecessario,chepresentasoltantoduemetodi:wheneotherwise.Peraggiungereunaroute,utilizziamoilmetodowhen,cheaccettadueparametri:ilpercorsodellastringaeleopzionidellarouteinquantooggetto:

angular.module(‘contactsMgr’,[‘ngRoute’])

.config(function($routeProvider){

$routeProvider.when(‘/’,{});

})

Nell’oggettodelleopzionidellaroutesonopresentidueproprietàcheciinteressano:controlleretemplateUrl.Laproprietàcontrollerchiamauncostruttorecontrolleresistenteonedefinisceunonuovotramiteunafunzioneanonima.LaproprietàtemplateUrlconsentedidefinireilpercorsoaunfileHTMLcheospiteràl’interomarkupdellavista.Inalternativapotremmodefinireiltemplatedirettamenteall’internodell’oggettoroute.Tuttavia,cosìfacendo,lasituazionesipotrebbebenprestocomplicare;questasoluzioneèconsigliabilesolopertemplatecontenentiunaoduerighe.

Esaminiamolaroutechedefiniremoperlapaginaindex:

$routeProvider.when(‘/’,{

controller:‘indexCtl’,

templateUrl:‘assets/partials/index.html’

});

IlpercorsodeltemplateèrelativoalfileHTMLdibase,quindiincludeladirectoryassets.PossiamoprocedereecreareiltemplateHTML.InAngularquestielementivengonochiamatipartialeliutilizzeremopertutteleviste.

L’argomentocontrollerall’internodellarouteèfacoltativo,mal’abbiamoinclusoperchéciserviràperl’applicazione.Creiamoilcontrollercheciconsentedisvilupparemodelliefunzionisoltantoperlavistaindex.

Nelfilecontroller.jspossiamoconcatenarloallafine:

Page 68: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

.controller(‘indexCtrl’,function($scope){

});

Aggiungiamolasecondarouteconilmetodoconfig.Ospiteràilformperaggiungereicontatti:

$routeProvider.when(‘/’,{

controller:‘indexCtl’,

templateUrl:‘assets/partials/index.html’

})

.when(‘/add-contact’,{

controller:‘addCtl’,

templateUrl:‘assets/partials/add.html’

});

Comenelcasodeicontroller,possiamoconcatenareleroute.Noncirestachecreareicontrollereipartialopportuni:

.controller(‘addCtl’,function($scope){

});

L’ultimaoperazionecheènecessariosvolgereprimacheAngularrendaoperativoilrouterconsistenell’includerenellapaginaladirettivang-view,cheinserisceilpartialdefinitonellaroute:

<divclass=”container”>

<ng-view></ng-view>

</div>

NOTA

Èpossibileincludereng-viewsoltantounavoltaperpagina.

Sipuòincluderequestadirettivacomesuoelemento.Quiabbiamopreferitoincluderlacomeunelementonelfileindex.htmlall’internodellaradice.Seèpresentequalcosanelcontenitore,cancellateloesostituiteloconng-view.

Seapriteilprogettonelbrowser,vedretechelarouteèstataaggiuntaall’URLedèprecedutadalsimbolo#.PurtropposeusereteChrome,probabilmenteipartialnonriuscirannoacaricarsi.Seapritelaconsole,vedreteunerroresimilealseguente:

CrossoriginrequestsareonlysupportedforHTTP.

Esistonoduesoluzioni.Possiamocaricareilcodicesuunserverweboppure,conChrome,possiamoavviareilbrowserutilizzandounflagperconsentirerichiestecross-originperilprotocollofile://inambienteOSXoperc:/inambienteWindows.

InOSX,eseguitequestocomandonelterminale:

open-a‘GoogleChrome’--args-allow-file-access-from-files

Page 69: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

InaltrisistemibasatisuUnixeseguiteilseguente:

google-chrome--allow-file-access-from-files

InWindows,ènecessariomodificareilcollegamentosuldesktopperaggiungereunflagallafinedelladestinazione:

C:\...\Application\chrome.exe--allow-file-access-from-files

SenonvoleteeseguireChromeconunflag,potetefargirarel’appdigestionedeicontattisuunserverweb.PotresteservirvidiquellointegratoinPythonoPHP,odiun’appveraepropriacomeMAMPoWAMP.

Modificateladirectorydelprogettoedeseguiteilseguentecomandopertestarel’applicazionesuunserverwebPython:

python-mSimpleHTTPServer8000

Poteteaccederealocalhost:8000nelbrowserpervisualizzarel’app.Inalternativa,sepreferiteeseguireunserverwebintegratoinPHP,potetefarlonelseguentemodo:

php-Slocalhost:8000

Page 70: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RouteconparametriDopoaverimpostatopiùroute,dobbiamocapirecomeincludereiparametrialloro

interno.Questoèunaspettoimportanteperconsentireuncertodinamismoall’internodell’appdigestionedeicontatti;peresempio,liutilizzeremopervisualizzareuncontattospecificofacendoriferimentoaunIDnumericooaunindice.

Èfacileinserirli;èsufficienteaggiungereunsegnapostoconduepuntiseguitidalnomedelparametrocheintendiamocreare.Osserviamolaroutecherealizzeremopervisualizzareilcontatto.Possiamodinuovoconcatenarlaalleroutegiàesistenti:

.when(‘contact/:id’,{

controller:‘contactCtl’,

templateUrl:‘assets/partials/contact.html’

});

Possiamoaggiungerefacilmentenelcontrollerquantiparametridesideriamo.Saràsufficienteinserireunservizioepotremoaccedereatuttiiparametridellaroutecomeoggetti:

.controller(‘contactCtl’,function($scope,$routeParams){

console.log($routeParams);

});

Seaccedetealocalhost:8000/#/contact/1eapritelaconsole,vedreteiparametridellarouteregistraticomeoggettoJS.

Ciòsignificachepossiamoaccedereaqualsiasiproprietàdell’oggettotramitelasintassistandard:

$routeParams.id;

Page 71: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RoutedifallbackL’ultimaroutedaconfigurareèquellacheverràvisualizzataquandononsitrova

nessunaroutecorrispondente.Potrestecreareunapagina404,mavediamocomeèpossibilereindirizzareunarouteinvecedivisualizzareuntemplate.

Percreareunaroutedifallback,utilizziamoilsecondometodochecioffreilservizio$routeProvider:otherwise:

.otherwise({

redirectTo:‘/’

});

Inquestomodo,selarouterichiestanoncorrispondeanessunadiquelledefinitenelrouter,Angularciriportaallapaginadell’index.

Page 72: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RoutinginHTML5oeliminazionedelsimbolo#

Oraabbiamoconfiguratotutteleroutefondamentaliepossiamoaccedereapartialdistintiperognuna.Èunottimorisultato,ancheseleroutecheseguonoilsimbolo#nell’URLnoncipiacciono.Fortunatamenteesisteunsistemafacileperrimediare,attivandociòcheAngulardefiniscehtml5Mode.

QuestamodalitàconsenteadAngulardisfruttareilpushStateneibrowsermodernifornendoalcontenutounfallbackperibrowserlegacy,comeIE8.

AbilitareHTML5ModePerconsentirequestanuovamodalità,riesaminiamoilmetodoconfig.Come

abbiamofattoinprecedenza,dobbiamoinserirviunservizio:

.config(function($routeProvider,$locationProvider){

...

$locationProvider.html5Mode(true);

})

Oraabbiamoinseritounsecondoservizio:$locationProvider,checiconsentedisfruttareilmetodohtml5Mode,cheaccettaunvalorebooleanoperattivarloodisattivarlo.

Ilserviziooffreunsecondometodo,eanchesenonneapprofitteremonelcorsodellosviluppodell’app,èopportunoconoscerlo.IlmetodohashPrefixpermettediaggiungerenell’URLunprefissodopoilsimbolo#.Peresempio,potremmoaggiungereunpuntoesclamativoetrasformareilprefissoinunhashbang(#!):

$locationProvider.hashPrefix(‘!’);

Laprossimafiguramostral’URLdell’applicazioneesuddividel’indirizzonellediversesezionidellaroute.

Page 73: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap
Page 74: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

CollegarelerouteCollegareleroutenonèdiversodacollegarelepaginesuunsitoweb.Utilizziamo

untagàncorae,invecedicollegarelapagina,colleghiamolaroute.

Peresempio,sevolessimocollegareilpulsanteAddContactnellabarradinavigazione,dovremmoimmetterequestocodice:

<ahref=”/add-contact”>AddContact</a>

Alclicsullink,Angularvisualizzerebbeautomaticamenteilpartialcorrettoecambierebbeanchel’URL.Seavetedecisodinonutilizzarehtml5Mode,potetecomunqueeffettuareilcollegamentomedianteun’àncora,mal’attributohrefsaràleggermentediverso,perchéènecessarioaggiungereilsimbolodelcancelletto:

<ahref=”#/add-contact”>AddContact</a>

Page 75: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. Qualefileomodulodobbiamoincludereperconsentireilrouting?2. Qualemetodoutilizziamopercreareleroute?3. Checosadobbiamoinserirenelmetodoperriuscireacreareunaroute?4. Inchemodocreiamounaroute?5. Checosapossiamoutilizzarequandonessunaroutecorrispondealpercorso

corrente?6. Inchemodopossiamoeliminareilsimbolo#nell’URL?

Page 76: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoInquestocapitoloabbiamotrasformatol’applicazione,edaun’appconun’unica

paginasiamopassatiaunamultipaginaemultiroutenellaqualesvilupperemoilnostrogestoredicontatti.Abbiamoiniziatoaprogettareleroutefondamentalidell’appprimadiinstallareilmodulonecessario.

Abbiamovistocomeèpossibileutilizzarenelmoduloilmetodoconfigperimpostareleroute,eperfarloabbiamoinseritoilservizio$routeProvidereutilizzatoimetodiwheneother.Cosìabbiamoimpostatoroutestaticheedinamichecontenentiparametri.

Infineabbiamoanalizzatocomeeliminareilsimbolo#dall’URLmedianteilpushStatediHTML5ecollegareentrambiitipidiroute.NelprossimocapitolopopoleremoipartialconilayoutchesvilupperemograzieaBootstrap.

Page 77: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo5

Page 78: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Leviste

NelCapitolo4abbiamovistocomeèpossibiletrasformarel’applicazioneinunawebappconpiùrouteepiùviste.AbbiamosfruttatoilrouterdiAngulareimpostatoipartialpertuttelevistefondamentali.OraèilmomentodicrearelevistemedianteBootstrapcosìdapoterpopolarel’appconidati.Analizziamounoperunoipartial.

Page 79: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

PopolarelavistaIndexLavistaIndexèciòchevienevisualizzatoquandoapriamol’app.Forseconviene

elencarequituttiicontatti;infattiavremobisognodiunrapidoaccessoalleinformazionimemorizzate.

Unatabellapuòessereun’opzioneefficace,maènecessariorifletteresuciòcheverràmemorizzatonelgestoredeicontatti.Eccounalistadeipossibiliitem:

NomeIndirizzoe-mailNumeroditelefonoIndirizzoSitowebNoteGravatar(unserviziodiavatarriconosciutoalivellomondialesviluppatodaicreatoridiWordPress)

NonoccorrevisualizzaretuttequesteinformazioninellavistaIndex.Nondimenticatechesaràanchepresentel’opzioneperscorrereicontattiequindiavremolapossibilitàdivisualizzarepiùinformazioni.

Unasceltaragionevolesembraquelladivisualizzarenome,indirizzoe-mailenumeroditelefonoinunatabellaconunlinksucuifareclic.

ApriteilpartialdellavistaIndex;sitrovainassets/partials/index.html.Peroraquestofileèvuoto;aggiungeteall’iniziol’headerdellapagina:

<divclass=”page-header”>

<h1>AllContacts</h1>

</div>

Nondobbiamoracchiuderloinuncontenitorepoichéilpartialènidificatonelfileprincipaledell’appindex.htmlsullarouteeviabbiamogiàinclusoilcontenitore:

<table>

<thead>

<tr>

<th>Name</th>

<th>EmailAddress</th>

<th>PhoneNumber</th>

<th>Actions</th>

</tr>

</thead>

<tbody>

<tr>

<td>KaranBromwich</td>

<td>[email protected]</td>

<td>0123456734</td>

<td><ahref=”#”>View</a></td>

</tr>

Page 80: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

<tr>

<td>DeclanProud</td>

<td>[email protected]</td>

<td>01234567890</td>

<td><ahref=”#”>View</a></td>

</tr>

</tbody>

</table>

Èunastrutturafunzionale,ancheselapaginanonhaunbell’aspetto.Comelamaggiorpartedeicomponenti,Bootstrappermettediapplicareglistilialletabelle,ancheseènecessarioincludereunaclasseaggiuntivaperrenderlidisponibili.AggiungetelaclassetablealtagdiaperturadellatabellaeBootstrapmetteràsubitounpo’d’ordineaggiungendoibordinecessariefacendoinmodocheoccupil’interalarghezza.

Sonopresentiinoltrealcuneclassisecondariecheèpossibileincluderepervivacizzareunpo’latabella.

table-bordered:aggiungeunbordoattornoatuttiilatidellatabellaedellecelle.table-striped:aggiungeunosfondogrigioarighealternateperfacilitarelalettura.table-hover:modificalosfondodellarigaall’hover.table-condensed:eliminaunapartedelpaddingsuperioreeinferioreinmododaridurrel’altezzadellatabella.

Oltreaquesteclassi,neesistonoaltrecheèpossibileapplicareallerigheoallecelleechecoloranolosfondodellerighepercontestualizzarle.

active:aggiungeallarigalostatohover.success:coloralosfondodiverde,perindicarecheun’azionehaavutosuccesso.info:attiral’attenzionesuunarigaosuunacellasegnalandoun’informazione.warning:indicachepuòesserenecessariaun’azioneecoloralacelladigiallo.danger:richiamal’attenzionesuunerroreosuunproblema.

Perilmomentoaggiungeremolaclassetable-striped,mastaavoisperimentarelealtreclassiintegrate.

Latabellainiziaadavereunbell’aspetto.Vedreteperòchesuunoschermodidimensionipiùpiccolerisultatagliataorizzontalmente.Perrimediareènecessarioracchiuderlainunaltroelementochecipermettadieffettuareloscorrimentosuschermipiùpiccoli:

<divclass=”table-responsive”>

</div>

Page 81: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Orahaunaspettonettamentemigliorepoichéilcontenutononvienepiùtagliatoeillayoutresponsivenonsiinterrompe.L’ultimaoperazionechefaremosullatabellaètrasformareillinkdellavistainunpulsante.Bootstrapoffrenumerosistiliperipulsantidicuipossiamoavvalerci.

Tuttiipulsantisonocombinazionidelleclassirelative:

alpulsantepredefinito;alcontesto;alledimensioni.

Tutteinsiemeoffronoilcontrollochecioccorrealfinediscegliereilpulsantegiustoperl’occasionegiusta.Combiniamolepercreareunpulsantechebensiintegrinellatabella:

<ahref=”#”class=”btnbtn-defaultbtn-xs”>View</a>

Laprimaclasseapplicaalcunistilipredefinitiaipulsanti;lasecondaassegnailcolore(inquestocaso,quellopredefinitoèilbianco)el’ultimadefinisceledimensioni.Inalternativapotremmoutilizzareunatraleclassidescrittenellaprossimatabellapermodificareilcoloredelpulsante.

Nomedellaclasse Descrizionebtn-default Pulsantebiancoconunbordogrigio

btn-primary Pulsanteblu

btn-success Pulsanteverde

btn-info Pulsanteazzurro

btn-warning Pulsantearancione

btn-danger Pulsanterosso

btn-link Pulsanteconlostilediunlink

Oltreaimpostareledimensionipredefinite,altretreclassilemodificano.Nelcodiceprecedenteabbiamogiàutilizzatobtn-xsperrimpiccioliremoltoilpulsante,mapotremmoutilizzareanchebtn-smperfareinmodocheappaiaunpo’piùpiccolodiquellopredefinitoobtn-lgperingrandirlo.

LavistaIndexècompletaedèprontaperesserepopolata.Nell’immagineseguenteosserviamoilrisultato.

Page 82: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap
Page 83: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

PopolarelavistaAddContactÈchiarociòdicuiavremobisognonellavistaAddContact:unformcheci

consentadidigitareleinformazionirichieste.FortunatamenteBootstrapcioffremoltocontrollonell’organizzazionedeicampi.Abbiamogiàelaboratoidatichememorizzeremo;orasitrattasolodiindividuarequalèiltipodicampomigliore:

Name:campoditestoEmailaddress:campoe-mailPhonenumber:campoperilnumeroditelefonoAddress:areaditestoWebsite:campoditestoNotes:areaditestoGravatar:N/D

SiccomeGravatarusal’indirizzoe-mailperfornirel’immagine,quinondobbiamorichiederealcunainformazioneaggiuntiva.Abbiamointuttoseicampi;quindiduecolonnesonosufficienti.

Innanzituttoapriamoilformeaggiungiamoalsuointernolecolonne.Abbiamogiàlaclassedelcontenitore;cioccorronounanuovarigaeleduecolonne.ComeabbiamovistonelCapitolo2,ilsistemaagrigliadiBootstrapcontiene12colonne;ricordiamoceloquandocreeremoillayout:

<form>

<divclass=”row”>

<divclass=”col-sm-6”>

</div>

<divclass=”col-sm-6”>

</div>

</div>

</form>

Comeabbiamofattoinprecedenza,utilizziamoilprefissocol-smperfareinmodochelecolonnesicomprimanosuitabletosuidispositivimobilipiùpiccoli.

Potremmoinserireleetichetteegliinputdirettamentenellecolonne,maperunaspaziaturaottimale,ènecessarioracchiudereglielementiinuntagdivconlaclasseform-group:

<divclass=”form-group”>

<labelfor=”name”>Name</label>

<inputtype=”text”id=”name”>

</div>

Page 84: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

PersfruttareglistilidiBootstrapnegliinput,aggiungiamolaclasseform-control.Seaggiungessimolaclassecontrol-labelall’etichetta,applicherebbeunpo’dipaddingaggiuntivo:

<divclass=”form-group”>

<labelfor=”name”class=”control-label”>Name</label>

<inputtype=”text”id=”name”class=”form-control”>

</div>

Aggiungiamoall’internoglielementirestanti:ilnome,ilnumeroditelefonoel’indirizzonellacolonnadisinistrael’indirizzoe-mail,ilsitowebelenoteinquelladidestra.

FormorizzontaliIlformpresentamoltobene.Senonvipiaccionoleetichetteinalto,potete

collocarleasinistraconunaleggeramodifica.Aggiungendolaclasseform-horizontalaltagdiaperturadelform,leclassiform-groupsicomportanocomelerighediunagriglia;pertantopossiamoapplicareleclassidellecolonneaglielementiallorointerno.Eccoilcodiced’esempio:

<divclass=”form-group”>

<labelfor=”name”class=”col-sm-4control-label”>Name</label>

<divclass=”col-sm-8”>

<inputtype=”text”id=”name”class=”form-control”>

</div>

</div>

Dopoaverinclusolaclasseform-horizontal,vedretecheèpossibileaggiungereall’etichettaleclassiapplicabiliallecolonnediBootstrap.Siccomeform-controlimpostalalarghezzasu100%,siadattaall’elementogenitorechedobbiamoracchiudereinunelementoaggiuntivo.Abbiamoinclusoanchelaclassecontrol-labelequindil’etichettaècentrataverticalmente.

Ilformapparemoltomenodisordinatograzieallaclasseform-horizontal;proseguiamoeracchiudiamotuttigliinputnell’elementoform-control.

Talvoltavorretefornireall’utentemaggioriinformazionidiquellestrettamentenecessarie.Lepoteteincluderesottol’inputcorrispondenteutilizzandountagspanassociatoallaclassehelp-block:

<divclass=”form-group”>

<labelfor=”notes”class=”col-sm-4control-label”>Notes</label>

<divclass=”col-sm-8”>

<textareaid=”notes”class=”form-control”></textarea>

<spanclass=”help-block”>Anyadditionalinformationaboutthe

contact.</span>

</div>

</div>

Page 85: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Noncirestacheaggiungereunpulsantediinvio.NelleversioniprecedentidiBootstrap,eraracchiusoinunelementoconlaclasseform-actions.InBootstrap3,invece,èsufficienteutilizzarelostessoform-groupcheabbiamousatofinora.Seapplicheretelostileform-horizontal,dovretedistanziarelecolonne:

<divclass=”form-group”>

<divclass=”col-sm-offset-4col-sm-8”>

<buttonclass=”btnbtn-primary”>AddContact</button>

</div>

</div>

Poichél’etichettaoccupaquattrocolonne,ènecessariostaccareilpulsantedellostessospazioinmodochesiabenallineato.

Amepiacevailcontrastocheoffrivalavecchiaclasseform-actions.FortunatamentepossiamoottenereunrisultatosimilericorrendoalcomponentewelldiBootstrap.Inquestocasoabbiamospostatolaclasseform-groupchecontieneilpulsantesubmitsubitosottolarigagiàesistente(ricordatevicheform-horizontalfasìchetuttiigruppisicomportinocomerighe)eabbiamoaggiuntolaclassewell:

<divclass=”form-groupwell”>

<divclass=”col-sm-offset-2col-sm-10”>

<inputtype=”submit”class=”btnbtn-primary”value=”Add

Contact”>

</div>

</div>

Infine,percompletarelapagina,assegneremolostessoelementopage-headercheabbiamoinclusonellavistaIndexelocollocheremosubitoall’iniziodelmarkup:

<divclass=”page-header”>

<h1>AddContact</h1>

</div>

Ilrisultatofinalesaràilseguente.

Page 86: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap
Page 87: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

PopolarelavistaViewContactL’ultimopartialchedobbiamopopolareèlaschermataincuiverràvisualizzatoil

contatto.Siamostatitentatidiinserirlocomeunform,macipiacel’ideadiaveredeltestostatico,chepossiamodecideredimodificareinalcuneparti.

DovremovisualizzarelestesseinformazionicheabbiamoimmessonellavistaAddContact,oltrealgravatar.

TitoloegravatarInnanzituttoincluderemounaclassepage-header.Ospiteràuntagh1conall’internoil

nomedelcontatto:

<divclass=”page-header”>

<h1>DeclanProud</h1>

</div>

Quiincluderemoancheilgravatar:vediamocome.Perorautilizzeremoalcuneimmaginisegnapostoprovenientidahttp://placehold.it.Forsenonconoscetequestosito:quitrovatesegnapostoditutteledimensioni.Abbiamobisognodiun’immagine50px×50px,cheinseriremomedianteilcodiceseguente:

<imgsrc=”http://placehold.it/50x50”>

Modificatenepureledimensioniavostropiacimento.Poteteinserirlasubitoprimadelnomedelcontattoneltagh1.Vogliamoancheaggiungerelaclasseimg-circle:

<divclass=”page-headerrow”>

<h1><imgsrc=”http://placehold.it/50x50”class=”img-circle”>

DeclanProud</h1>

</div>

Questaclasseèunadelletredisponibiliperapplicareunpo’distilealleimmagini;aggiungeunarrotondamentodegliangoliparial50%percreareuncerchio.Èanchedisponibileimg-rounded,chearrotondagliangoli,oltreaimg-thumbnail,cheaggiungeunbelbordodoppio.

Laclasseform-horizontalSiamofortunatiperchépossiamoriutilizzarebuonapartediquellocheabbiamo

fattonellavistaAddContact.Laclasseform-horizontalsicomporteràaltrettantobeneseèpresentedelcontenutostaticoalpostodeicampi.Questapaginadiventeràin

Page 88: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

seguitolaschermatadiediting,oltreaesserelaschedadelcontatto;pertantoèutilepoterutilizzarelaclasseperentrambeleviste.

Questavoltaperòricorreremoauntagdivenonaunelementodelformperracchiudereillayoutconduecolonne:

<divclass=”form-horizontal”>

<divclass=”row”>

<divclass=”col-sm-6”>

...

</div>

<divclass=”col-sm-6”>

...

</div>

</div>

</div>

Apartequestapiccolamodifica,illayoutèidentico.Abbiamolastessarigaeleseicolonnedellavistacreateinprecedenza.

Possiamoancheutilizzareleclassiform-groupoltrealleclassicontrol-label,checiconsentonodistrutturareefficacementel’etichettasenzausareunalistaounatabella,comepossiamovederediseguito:

<divclass=”form-group”>

<labelfor=”name”class=”col-sm-4control-label”>Name</label>

<divclass=”col-sm-8”>

<p>DeclanProud</p>

</div>

</div>

Tuttaviaselocarichiamonelbrowser,vedretechel’etichettaeilcontattononsonobenallineati.Perrimediarepossiamoincludereun’altraclasseneltagparagraph:

<pclass=”form-control-static”>DeclanProud</p>

Aggiungetelaintuttiicampi.Abbiamoripresolostessolayoutprecedenteconnome,numeroditelefonoeindirizzonellacolonnadisinistraeindirizzoe-mailesitowebenoteinquelladidestra.

Siamosoddisfattidiquestolayout.Tuttavia,quandoloridimensioniamo,sembracherimangamoltospaziobiancoadestra.Sarebbepreferibilemodificarelecolonneprincipaliinmodochesianovisibiliinquestolayoutanchesudispositivimobili.

Nellarigasostituiamolaclassecol-sm-6conlaseguente:

<divclass=”col-xs-6”>

</div>

Inquestomodootterremoduecolonnesudispositivipiùpiccoliedeviteremoilproblemadellospaziobiancoineccesso.

Diseguitopoteteosservareilrisultato:

Page 89: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap
Page 90: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. Perchénonènecessarioincludereuncontenitoreneipartial?2. Oltreatable,qualiclassièpossibileaggiungereaunatabellaperattribuireun

po’distile?3. Comepossiamocreareungrandepulsanteazzurro?4. Inchecosadevonoessereracchiusileetichetteegliinput?5. Inchemodolaclasseform-horizontalmodificailform?6. Checosautilizziamopervisualizzareunmessaggiodiaiutoaggiuntivoperun

campodelform?7. Qualitreclassipossiamoapplicarealleimmaginiequalirisultatiproducono?

Page 91: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoOraabbiamotrelayoutprincipalicompleti.Abbiamoottenutoquestorisultato

senzascrivereunasolarigadiCSSsfruttandoglistilieicomponentifondamentalidiBootstrap.

NellavistaIndexabbiamoesaminatocomeBootstrapincludestilipredefinitieapplicaleclassisecondarieperaggiungereunpo’distile.ÈunpatterncheBootstraputilizzasempre,el’abbiamovistoinazioneconipulsantiegliinput.

ConlavistaAddContactabbiamoimparatoqualisonoisistemimiglioriperorganizzareunformeabbiamostabilitodiapplicareform-horizontal.Lapotremoriutilizzarequandocreeremolaschedadelcontatto.

Nelprossimocapitoloimpareremoacollegarelevisteadatidinamici.UtilizzeremoAngularJSpercrearecontatti,passaredaunoall’altroevisualizzarlinellatabella,modificarliocancellarli.

Page 92: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo6

Page 93: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

CRUD

FinoraabbiamoesploratoiparadigmidiAngularesviluppatolastrutturadell’appgrazieaBootstrap.Inquestocapitolocibaseremosulleideeeiconcetticheabbiamoesaminatonelcorsodellibroperrendereoperatival’app.

CRUDèl’acronimodiCreate,Read,UpdateeDelete(creare,leggere,aggiornareecancellare),tuttociòcheservepersviluppareun’appdigestionedeicontattiefficiente.

AnalizzeremoogniletteradiquestoacronimoevedremocomeèpossibilesfruttarepienamenteAngular.

Page 94: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ReadPerilmomentoignoreremolapartecreativaepasseremosubitoallaletturadei

dati.Neutilizzeremodifittizisottoformadiunarraydioggettinelcontroller.

Nelprossimolistatovediamocomevengonoformattatieciòchedobbiamoincludere.

.controller(‘indexCtl’,function($scope){

$scope.contacts=[

{

name:‘StephenRadford’,

phone:‘0123456789’,

address:‘123,SomeStreet\nLeicester\nLE12AB’,

email:‘[email protected]’,

website:‘stephenradford.me’,

notes:‘’

},

{

name:‘DeclanProud’,

phone:‘91234859’,

address:‘234,SomeStreet\nLeicester\nLE12AB’,

email:‘[email protected]’,

website:‘declanproud.me’,

notes:‘Somenotesaboutthecontact.’

}

];

})

Siccomeabbiamoassociatol’arrayalloscope,possiamoaccedervidirettamenteall’internodellavista.Medianteladirettivang-repeatesaminatanelCapitolo2,èpossibileavviareilciclodell’arraypervisualizzareicontattinellatabella:

<trng-repeat=”contactincontacts”>

<td>{{contact.name}}</td>

<td>{{contact.email}}</td>

<td>{{contact.phone}}</td>

<td><ahref=”/contact/{{$index}}”class=”btnbtn-defaultbtn-

xs”>View</a></td>

</tr>

Questocodicehaunaspettomoltofamiliare.Abbiamoassociatoladirettivaall’elementocheintendiamoripetere(inquestocasolarigadellatabella)eutilizzatoledoppieparentesigraffepervisualizzareidatideicontatti.

Nellinkosserveretequalcosadileggermentediverso.Ladirettivang-repeatciconsentediottenerel’indicedell’oggettocorrenteutilizzando$index.RicorderetechelaroutedelsingolocontattoaccettaunnumeroID.Utilizzeremol’indicedell’arraycomeIDinmododapoteraccederefacilmentealcontattoquandoneavremobisogno.

Condividereidatitraleviste

Page 95: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Ciòcheabbiamorealizzatofinorapresentaunproblema.AnchesefunzionaperfettamenteperlavistaIndex,èdeltuttoinutilequandointendiamovisualizzareununicocontatto.Infattiilnostroarraydicontattiècontenutonelcontrollerdell’indiceepertantononpuòesserecondiviso.

Condividereidatimediante$rootScope

Sonodisponibiliduesistemipercondividereidatitraleviste:ilprimoè$rootScope.Cosìcomeesisteunoscopeperognivista,l’applicazionestessanehauno,loscoperadice(rootscope),chefunzionaallostessomodo.

Perutilizzarloènecessarioinserireunnuovoserviziochesichiama$rootScope:

.controller(‘indexCtl’,function($scope,$rootScope){

$rootScope.contacts=[

{

name:‘StephenRadford’,

phone:‘0123456789’,

address:‘123,SomeStreet\nLeicester\nLE12AB’,

email:‘[email protected]’,

website:‘stephenradford.me’,

notes:‘’

},

{

name:‘DeclanProud’,

phone:‘91234859’,

address:‘234,SomeStreet\nLeicester\nLE12AB’,

email:‘[email protected]’,

website:‘declanproud.me’,

notes:‘Somenotesaboutthecontact.’

}

];

$scope.contacts=$rootScope.contacts;

})

Possiamoassociarenellostessomododeglielementiall’oggettoscoperadice.Inquestocasol’abbiamoaggiuntoanchealloscopedellavista,maavremmopotutomodificarefacilmentelavistaperaccederedirettamentealloscoperadice:

<trng-repeat=”contactin$root.contacts”>

Peraccederedallavistaaqualsiasielementonelloscoperadice,èsufficienteanteporrealnomedelmodelloilprefisso$rootseguitodaunpunto.

QuestometododicondivisionedeidatinonsfruttatuttiglistrumentichecioffreAngularegeneramoltaconfusionenell’applicazione.

NOTA

Ilricorsoa$rootScope,esoprattutto ilsuoaccessodallavista,èunapraticasconsigliataepuòostacolare lagestionedelprogetto;percondividere idatièpreferibileutilizzareuncontrolleralivellodell’applicazioneounserviziopersonalizzato.

Page 96: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Creareunserviziopersonalizzato

Unasoluzionemigliorepercondividereidatitralevisteèsviluppareunsistemapersonalizzato.Unservizioèinsostanzaunaclasseallaqualeèpossibileaccederedopoaverlainseritaneicontroller,cosìcomeabbiamovistocon$scope.

InAngularJSneesistonotretipi:.service(),.factory()e.value().Tuttisonosingleton,deidesignpatternchefannoinmodochediessiesistaunasolaistanzasuunoggetto.Liesamineremotuttiprimadisvilupparneuno.

Value

Ilpiùessenzialedeitreèilmetodovalue.Aggiungiamoloalmodulo:

.value(‘demoService’,‘abc123’);

Comepossiamovedere,sitrattadiunserviziosemplicissimocheaccettadueparametri:ilnomedelserviziocheintendiamocreareeilvalorechedovrebbeavere.Questidatipossonoesserecondivisinell’applicazioneinserendolineicontroller:

.controller(‘indexCtl’,function($scope,demoService){

$scope.demo=demoService;

});

Èmoltosemplice,maoffreunmodorapidoefacilepercondividereidati.Potremmovolercondividere,peresempio,unachiaveAPItramolteplicicontroller.Ilmetodovaluesarebbelasoluzioneideale.

Factory

Valueèsempliceedefficace,manonoffremoltefunzioni.InveceilserviziofactorydiAngularcipermettedichiamarealtriservizitramitelaDI(dependencyinjection),econsenteanchel’inizializzazionedelservizioel’inizializzazionelazy.Riscriviamol’esempiocontenentevaluesostituendoloconfactory:

.factory(‘demoService’,functiondemoServiceFactory(){

return‘abc123’;

});

NOTA

Inquestocasoabbiamochiamatolafunzione[serviceName]Factory.Anchesenonènecessario,èopportunofarloperchéconsenteundebuggingmoltopiùsemplicenell’analisidellostack.

Funzionerà,maperun’appcosìessenziale,èunsistemafintroppoelaboratoedèpreferibileutilizzarevalue.Comeabbiamoscoperto,factorypuòchiamarealtriservizi.CreiamoneunaltroeinseriamoildemoServiceiniziale:

.factory(‘anotherService’,function[‘demoService’,

anotherServiceFactory(demoService){

Page 97: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

returndemoService;

});

IlserviziofactorypuòanchemodificareilvalorefornitocidademoService,mavieneutilizzato,piùfrequentemente,perconnettersiaun’API.Comenelcasodivalue,factoryrestituiscetipiJavaScript.Eccocomerestituisceunoggetto:

.factory(‘anotherService’,function[‘demoService’,

anotherServiceFactory(demoService){

return{

connect:function(){

}

};

});

Ilmetodoconnectdefinitonell’oggettorestituitosaràdirettamenteaccessibilequandoinseriamoilservizionelcontroller:

.controller(‘indexCtl’,function($scope,anotherService){

anotherService.connect();

});

Service

L’ultimotipodiserviziopresenteinAngularJSvienechiamatoservice(unnomechegeneraconfusione,comeilfiltroFilter).Produceunsingletonalparidivalueefactory,invocandoperòuncostruttoremediantel’operatorenew.Anchequestopuògenerareconfusione;cerchiamodifarechiarezza.

NelseguentecasoèpresentelafunzionedelcostruttoreNotifiercheèunsemplicealiasperilmetodowindow.alertdelbrowser:

functionNotifier(){

this.send=function(msg){

window.alert(msg);

}

}

Potremmoaggiungerladirettamentenelcontrollerechiamarlainquestomodo:

varnotifier=newNotifier();

notifier.send(‘Hello,World’);

Anchesefunzionerebbe,nonèlasoluzioneottimale.EsevolessimoutilizzarenuovamentelafunzioneNotifierinunaltrocontroller?Comesappiamo,possiamocondividerequestotipodielementiricorrendoaunserviziodiAngularJS.Confactory,otterremmoqualcosadelgenere:

.factory(‘notifierService’,functionnotifierFactoryService(){

returnnewNotifier();

});

Page 98: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Nientemale,maquestoèproprioiltipodirisultatoperilqualeèstatoconcepitoservice.Creaun’istanzaerestituisceunoggetto:

.service(‘notifierService’,Notifier);

Eccofatto!Angularprenderàilcostruttore,necreeràun’istanzaerestituiràl’oggetto.Possiamoinserirlonelcontrollereutilizzarlocomeprevisto:

.controller(‘indexCtl’,function($scope,notifierService){

notifierService.send(‘Hello,World’);

});

Sviluppareunservizio

Potremmoutilizzareserviceofactorypercondividereicontattitraicontroller,masiccomenoncreiamoalcunaistanza,serviamocidifactory:

.factory(‘contacts’,functioncontactsFactory(){

})

Comeabbiamovisto,èsolol’oggettorestituitoacontenereimetodieleproprietàpubbliche.Èpossibilesfruttarequestoaspettoincludendol’arraydicontattiprivatamente,consentendochesiarestituitoeaccessibilesoltantodametodipubblici:

varcontacts=[

];

Ilservizioincluderàduemetodiperleggereicontatti.Ilprimorestituiràl’interoarray,mentreilsecondounsolooggettocontattochedipendedall’indiceassegnatoaesso.Restituiamol’oggettocontenentequestiduemetodievediamoinchecosaconsistono:

return{

get:function(){

returncontacts;

},

find:function(index){

returncontacts[index];

}

};

Entrambisonofunzionimolto“dibase”.Ilmetodogetrestituiscel’interoarray,mentreilmetodofindaccettaunindicecherestituisceilcontattorichiesto.Assembliamoiltuttoeosserviamoilrisultato:

.factory(‘contacts’,function(){

varcontacts=[

{

name:‘StephenRadford’,

phone:‘0123456789’,

address:‘123,SomeStreet\nLeicester\nLE12AB’,

email:‘[email protected]’,

website:‘stephenradford.me’,

Page 99: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

notes:‘’

},

{

name:‘DeclanProud’,

phone:‘91234859’,

address:‘234,SomeStreet\nLeicester\nLE12AB’,

email:‘[email protected]’,

website:‘declanproud.me’,

notes:‘Somenotesaboutthecontact.’

}

];

return{

get:function(){

returncontacts;

},

find:function(index){

returncontacts[index];

}

};

})

Orapossiamoinserirequestoservizionelcontroller,cosìcomeabbiamofattocon$scopee$rootScope:

.controller(‘indexCtl’,function($scope,contacts){

$scope.contacts=contacts.get();

})

Abbiamoanchepassatoalnuovometodoicontattinelloscope,equestohamessoordinenelcontroller.Seaggiungiamoconsole.logalserviziodicontatti,vedremochenonèpossibilevedereidatigrezzi,masoloiduemetodiaiqualiabbiamoavutoaccesso.

Utilizzareiparametridellaroute

Oracheilserviziofunzionaadovere,possiamoiniziareapopolarelavistacontenenteununicocontatto.Aquestoscopodovremoestrarrel’IDdallaroute.

NelCapitolo4abbiamoesaminatorapidamentecomeèpossibileaccedereaiparametridellaroute,maricapitoliamol’argomento.Innanzituttoènecessarioinserireunaltroservizionelcontrollerdell’unicocontatto:$routeParams.Questoserviziorestituisceunoggettocontuttiiparametrinellaroutecomeproprietàseparate:

.controller(‘contactCtl’,function($scope,$routeParams,

contacts){

Page 100: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

$scope.contact=contacts.find($routeParams.id);

});

Inquestocasoabbiamoaccessoalparametroidcheutilizziamopertrovareilcontattocorrettomedianteilserviziocheabbiamocreatoinprecedenza.Lopassiamoallavistacreandounnuovomodellosulloscopechiamatocontact.

Estraiamotutteleinformazionipertinentinelpartialcontact.html.Ricordatechetuttiidatisonoproprietàdelcontattodelmodelloepossiamoaccederviinquestomodo:

{{contact.name}}

Funzionatuttotranneperalcunidettagli.Idatiriguardantil’indirizzodovrebberorispettareifineriga,ecipiacerebbericavaredinamicamentel’immaginedelgravatar.Perottenerequestirisultatiènecessariocreareunfiltroeunadirettiva.

CreareunadirettivapersonalizzataAbbiamosperimentatol’efficaciadelledirettiveefinoranonavevamoalcun

motivopersvilupparneunanuova.Maperincludereilgravatar,ènecessariocrearneunapersonalizzata.

Cosìcomepericontroller,ifiltrieiservizi,lanuovadirettivadeveessereassociataalmoduloutilizzandoilmetodopertinente:

.directive(‘gravatar’,function(){

})

Comepericontroller,ifiltrieiservizi,ilmetododirectiverichiededueparametri.Ilprimoèilnomedelladirettiva,ilsecondoèunafunzione.Unadirettivadeverestituireunoggetto,eleproprietàdell’oggettorestituitodefinisconoilcomportamentodelladirettiva.

Laprimaproprietàcheimposteremoèrestrict;definisceilmodoincuièpossibileutilizzareladirettiva.Abbiamogiàvistocomeèpossibileavvalersidellamaggiorpartedelledirettivecomeattributioelementipersonalizzati,maAngularciconsenteanchediusarleinaltriduemodi.Èpossibileimpostarequestivaloriperlaproprietàrestrict.

A:ladirettivapuòessereassociatasoloutilizzandounattributo,<divgravatar></div>.E:ladirettivapuòessereutilizzatacomeelementopersonalizzato,<gravatar></gravatar>.

Page 101: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

C:ladirettivapuòessereutilizzataaggiungendolacomeclasseall’elemento,<divclass=”gravatar”></div>.M:consentel’esecuzionedelladirettivaattraversouncommentoHTML,<!--directive:gravatar-->.

NOTA

Perledirettiveèpreferibileutilizzareattributiedelementirispettoaclassiecommenti.

L’impostazionepredefinitadiAngularèlaprima,comeattributo.Possiamoutilizzareperòlacombinazionedeivalorimenzionatipermettereapuntoilmodoincuiintendiamoutilizzareladirettiva.SelaimpostiamosuAEpotremochiamarlatramiteunattributoounelementopersonalizzato:

.directive(‘gravatar’,function(){

return{

restrict:‘AE’

}

})

Seènecessario,potremmoanchecreareuntemplateperladirettiva.Puòessereinclusodirettamentenell’oggettoutilizzandolaproprietàtemplate,oppure,ricorrendoallaproprietàtemplateUrl,possiamocaricaredall’URIspecificatounfileditemplateesterno.Siccomequicreiamosoltantountagimg,possiamoaggiungerlodirettamentenell’oggetto:

.directive(‘gravatar’,function(){

return{

restrict:‘AE’,

template:‘<imgng-src=”{{img}}”class=”{{class}}”>’

}

})

Questotemplatesicomportacomeleviste.Abbiamoaggiuntoduesegnapostoperl’URIdell’immagineoltrealleclassicheintendiamoincludere.

Perfarfunzionareiltutto,occorreassociareunafunzioneallaproprietàlinknell’oggetto.Daquièpossibileaccederealloscope,all’elementoalqualeèassociataladirettivaeaqualsiasiattributodiquell’elemento:

.directive(‘gravatar’,function(){

return{

restrict:‘AE’,

template:‘<imgsrc=”{{img}}”class=”{{class}}”>’,

link:function(scope,elem,attrs){

}

}

})

Perrecuperarel’immaginedelgravatar,sideveapplicarelafunzionehashall’indirizzoe-maildelcontattotramitemd5.Purtroppononèunmetodonativodi

Page 102: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

JavaScriptedènecessarioincludereunalibreriaseparata.Neabbiamoinclusaunanegliassetriguardantiquestocapitolo,chepotetescaricare;puòessereinclusacomevariabilesingle-line:

.directive(‘gravatar’,function(){

return{

restrict:‘AE’,

template:‘<imgsrc=”{{img}}”class=”{{class}}”>’,

replace:true,

link:function(scope,elem,attrs){

varmd5=function(s){function

L(k,d){return(k<<d)|(k>>>(32-d))}functionK(G,k){var

I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&

1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^21474

83648^F^H)}if(I|d){if(x&1073741824){return(x^3221225472^F^H)}else{

return(x^1073741824^F^H)}}else{return(x^F^H)}}function

r(d,F,k){return(d&F)|((~d)&k)}function

q(d,F,k){return(d&k)|(F&(~k))}function

p(d,F,k){return(d^F^k)}function

n(d,F,k){return(F^(d|(~k)))}function

u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return

K(L(G,H),F)}function

f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return

K(L(G,H),F)}function

D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return

K(L(G,H),F)}function

t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return

K(L(G,H),F)}functione(G){varZ;varF=G.length;varx=F+8;vark=(x-

(x%64))/64;varI=(k+1)*16;varaa=Array(I-1);vard=0;var

H=0;while(H<F){Z=(H-

(H%4))/4;d=(H%4)*8;aa[Z]=(aa[Z]|(G.charCodeAt(H)<<d));H++}Z=(H-

(H%4))/4;d=(H%4)*8;aa[Z]=aa[Z]|(128<<d);aa[I-2]=F<<3;aa[I-

1]=F>>>29;returnaa}functionB(x){var

k=””,F=””,G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F=”0”+G.toString

(16);k=k+F.substr(F.length-2,2)}returnk}function

J(k){k=k.replace(/rn/g,”n”);vard=””;for(var

F=0;F<k.length;F++){var

x=k.charCodeAt(F);if(x<128){d+=String.fromCharCode(x)}else{if((x>1

27)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCh

arCode((x&63)|128)}else{d+=String.fromCharCode((x>>12)|224);d+=Str

ing.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|12

8)}}}returnd}varC=Array();varP,h,E,v,g,Y,X,W,V;var

S=7,Q=12,N=17,M=22;varA=5,z=9,y=14,w=20;var

o=4,m=11,l=16,j=23;var

U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=25623

83102;V=271733878;for(P=0;P<C.length;P+=16){h=Y;E=X;v=W;g=V;Y=u(Y,

X,W,V,C[P+0],S,3614090360);V=u(V,Y,X,W,C[P+1],Q,3905402710);W=u(W,

V,Y,X,C[P+2],N,606105819);X=u(X,W,V,Y,C[P+3],M,3250441966);Y=u(Y,X

,W,V,C[P+4],S,4118548399);V=u(V,Y,X,W,C[P+5],Q,1200080426);W=u(W,V

,Y,X,C[P+6],N,2821735955);X=u(X,W,V,Y,C[P+7],M,4249261313);Y=u(Y,X

,W,V,C[P+8],S,1770035416);V=u(V,Y,X,W,C[P+9],Q,2336552879);W=u(W,V

,Y,X,C[P+10],N,4294925233);X=u(X,W,V,Y,C[P+11],M,2304563134);Y=u(Y

,X,W,V,C[P+12],S,1804603682);V=u(V,Y,X,W,C[P+13],Q,4254626195);W=u

(W,V,Y,X,C[P+14],N,2792965006);X=u(X,W,V,Y,C[P+15],M,1236535329);Y

=f(Y,X,W,V,C[P+1],A,4129170786);V=f(V,Y,X,W,C[P+6],z,3225465664);W

=f(W,V,Y,X,C[P+11],y,643717713);X=f(X,W,V,Y,C[P+0],w,3921069994);Y

=f(Y,X,W,V,C[P+5],A,3593408605);V=f(V,Y,X,W,C[P+10],z,38016083);W=

f(W,V,Y,X,C[P+15],y,3634488961);X=f(X,W,V,Y,C[P+4],w,3889429448);Y

=f(Y,X,W,V,C[P+9],A,568446438);V=f(V,Y,X,W,C[P+14],z,3275163606);W

=f(W,V,Y,X,C[P+3],y,4107603335);X=f(X,W,V,Y,C[P+8],w,1163531501);Y

=f(Y,X,W,V,C[P+13],A,2850285829);V=f(V,Y,X,W,C[P+2],z,4243563512);

W=f(W,V,Y,X,C[P+7],y,1735328473);X=f(X,W,V,Y,C[P+12],w,2368359562)

;Y=D(Y,X,W,V,C[P+5],o,4294588738);V=D(V,Y,X,W,C[P+8],m,2272392833)

;W=D(W,V,Y,X,C[P+11],l,1839030562);X=D(X,W,V,Y,C[P+14],j,425965774

0);Y=D(Y,X,W,V,C[P+1],o,2763975236);V=D(V,Y,X,W,C[P+4],m,127289335

3);W=D(W,V,Y,X,C[P+7],l,4139469664);X=D(X,W,V,Y,C[P+10],j,32002366

56);Y=D(Y,X,W,V,C[P+13],o,681279174);V=D(V,Y,X,W,C[P+0],m,39364300

74);W=D(W,V,Y,X,C[P+3],l,3572445317);X=D(X,W,V,Y,C[P+6],j,76029189

);Y=D(Y,X,W,V,C[P+9],o,3654602809);V=D(V,Y,X,W,C[P+12],m,387315146

1);W=D(W,V,Y,X,C[P+15],l,530742520);X=D(X,W,V,Y,C[P+2],j,329962864

5);Y=t(Y,X,W,V,C[P+0],U,4096336452);V=t(V,Y,X,W,C[P+7],T,112689141

5);W=t(W,V,Y,X,C[P+14],R,2878612391);X=t(X,W,V,Y,C[P+5],O,42375332

41);Y=t(Y,X,W,V,C[P+12],U,1700485571);V=t(V,Y,X,W,C[P+3],T,2399980

Page 103: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

690);W=t(W,V,Y,X,C[P+10],R,4293915773);X=t(X,W,V,Y,C[P+1],O,224004

4497);Y=t(Y,X,W,V,C[P+8],U,1873313359);V=t(V,Y,X,W,C[P+15],T,42643

55552);W=t(W,V,Y,X,C[P+6],R,2734768916);X=t(X,W,V,Y,C[P+13],O,1309

151649);Y=t(Y,X,W,V,C[P+4],U,4149444226);V=t(V,Y,X,W,C[P+11],T,317

4756917);W=t(W,V,Y,X,C[P+2],R,718787259);X=t(X,W,V,Y,C[P+9],O,3951

481745);Y=K(Y,h);X=K(X,E);W=K(W,v);V=K(V,g)}var

i=B(Y)+B(X)+B(W)+B(V);returni.toLowerCase()};

}

}

})

Dopoaverinclusolafunzionemd5,potremoaccedereall’immaginedelcontattodalgravatar.Passeremodueelementiallafunzionedellink.Ilprimosaràl’indirizzoe-mail,mentreilsecondoparametrofacoltativosaràcostituitodalledimensionidell’immaginecheintendiamorecuperare.

Gliattributipassatiallafunzionesonosemplicioggettiaiqualipossiamoaccedere.Peresempio,seintendiamorecuperareilvaloredell’attributodell’indirizzoe-mail,possiamoaccedervimedianteattrs.email.

Abbiamoanchedefinitolaproprietàreplace,chesostituiràl’elementoalqualeabbiamoassociatoladirettivaconiltemplatespecificato.Perimpostazionepredefinita,Angularaggiungeràiltemplatecomeelementofiglio.

Finiamorapidamenteesperimentiamolanuovadirettiva:

.directive(‘gravatar’,function(){

return{

restrict:‘AE’,

template:‘<imgsrc=”{{img}}”class=”{{class}}”>’,

link:function(scope,elem,attrs){

varmd5=function(s){...};

varsize=(attrs.size)?attrs.size:64;

scope.img=‘http://gravatar.com/avatar/’+md5(attrs.email)+’?s=’+size;

scope.class=attrs.class;

}

}

})

Abbiamoutilizzatounoperatoreternarioperaverelapossibilitàdiimpostareledimensionidell’immagine.Abbiamoancheassociatoleclassiassegnateall’elemento,oltreaunirel’URLdelgravataralloscope.

Ladirettivaèpronta.Proviamoautilizzarlaconunattributo:

<divgravataremail=”{{contact.email}}”size=”50”class=”img-

circle”></div>

Ottimo,sembrafunzionaretutto.Vienevisualizzatoilgravatarevieneinclusalaclassecheproduceunabellaimmaginecircolare.Purtroppoessaèracchiusaneltagdivalqualeabbiamoassociatoladirettivaequindisispostasuunanuovariga.CiòaccadeperchénonabbiamocomunicatoadAngularcheintendiamosostituirel’elementoesistenteconiltemplatecompilato.Aquestoscopoimpostiamosutruelaproprietàreplacedell’oggettodelladirettiva:

Page 104: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

.directive(‘gravatar’,function(){

return{

restrict:‘AE’,

template:‘<imgsrc=”{{img}}”class=”{{class}}”>’,

replace:true,

link:function(scope,elem,attrs){

varmd5=function(s){…};

varsize=(attrs.size)?attrs.size:64;

scope.img=‘http://gravatar.com/avatar/’+md5(attrs.email)+’?s=’+size;

scope.class=attrs.class;

}

}

})

Seaggiorniamoilbrowser,vedremochealpostodell’immagineracchiusanell’elementooriginarioèpresentelanostraimmagine.Inalternativaavremmopotutochiamareladirettivatramiteunelementopersonalizzato:

<gravataremail=”{{contact.email}}”size=”50”class=”img-

circle”></gravatar>

SenonservespecificatamenteilsupportoaIE8(nonpiùsupportatoinAngularJS1.3+),ledirettivecheinseriscononuovielementitramitel’utilizzodiuntemplatedovrebberovenirechiamatemedianteunelementopersonalizzato,comenell’esempioprecedente.

Ledirettivechemanipolanoelementiesistenti,peresempiochiamandounplug-injQuery,dovrebberovenirechiamatesoltantotramiteunattributo.

Laprossimafiguramostralanuovadirettivaquandovienevisualizzatouncontatto.

Page 105: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RispettareifinerigaAttualmenteicampiaddressenotesnonrispettanoifinerigaperchélenuoverighe

devonoessereconvertiteininterruzionidirigaHTML.FortunatamenteAngularsemplificaalmassimoquestaoperazionemedianteunfiltropersonalizzato.

ComeabbiamovistorealizzandounfiltronelCapitolo3,descriveremorapidamenteilfiltroparagraphcheènecessariocreareperconvertireilfineriga\nin<br/>:

.filter(‘paragraph’,function(){

returnfunction(input){

return(input)?input.replace(/\n/g,‘<br/>’):input;

};

})

Seaggiungiamoquestofiltroall’indirizzousandolasintassicheprevedel’operatorepipe(|),noteremoqualcosadistrano.LeinterruzionidipaginavengonoconvertiteinentitàHTMLevisualizzatesullapagina.Permotividisicurezza,Angularesegueautomaticamentel’escapedelleentitàHTMLperimpedireloscriptingcross-site.

Page 106: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Siccomenonintendiamoovviamentevisualizzarle,dobbiamoutilizzareunadirettivainclusaperlegareilmodelloallapagina.Ladirettivang-bind-htmlprodurràesattamentequestorisultato.Eccolainazioneneltagparagraph:

<pclass=”form-control-static”ng-bind-html=”contact.address|

paragraph”></p>

Manonfunzionaancora.Secontrolliamolaconsole,Angulargenerailseguenteerrore:

Error:[$sce:unsafe]Attemptingtouseanunsafevalueinasafe

context.

InfattiAngularrichiedeilmodulongSanitizecheèpossibilescaricaredallasezioneExtrasall’indirizzohttps://angularjs.org/.Ilmodulofiltraiframmentidicodicepericolosi,comegliscript,producendounoutputripulitoesicuro.

ProcuratevelodalsitodiAngular,aggiungeteloalladirectoryjseincludetelonelfileprincipaleindex.html:

<scripttype=”text/javascript”src=”/assets/js/angular-

sanitize.min.js”></script>

Dopoaverinclusoilmodulonellapagina,ènecessarioinserirlocomedipendenzadelnostromodulo,cosìcomeabbiamofattoconngRoute:

angular.module(‘contactsMgr’,[‘ngRoute’,‘ngSanitize’])

Seaggiornatelapagina,vedretecheoral’indirizzooccupapiùrighe,comeprevisto.

ImpostarelaricercaeaggiungerelapageClassactive

L’ultimoargomentodaaffrontarenell’ambitodelReadèlaricerca.PoichélaricercafiltreràlatabellanellavistaIndex,dobbiamoreindirizzarlaquandoiniziamoadigitare.Inoltreilmodellocheutilizzeremodovràessereaccessibileovunque.

DobbiamoanchecapirecomeimpostarelapageClassactive.AlmomentoèfissasuBrowsemasarebbebellorenderladinamica.

Entrambiquestiobiettivinonsipossonoraggiungereconng-view;ènecessariocreareuncontrollerperl’interaapplicazione.Questosignificachesaremoingradodiaccedereovunquealmodelloperlaricerca:

.controller(‘appCtl’,function($scope,$location){

});

Page 107: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Perreindirizzarelapaginaabbiamoinseritoilservizio$location.Essooffrel’accessoalmetodopath,chepossiamosfruttareperrealizzareilnostrointento.Adifferenzadeicontrollerdellaroute,ènecessariochiamarlosullapaginaaggiungendoloaltagdiaperturaHTML:

<htmllang=”en”ng-app=”contactsMgr”ng-controller=”appCtl”>

Laricerca

Oracheilcontrollerèinizializzato,possiamoprocedere.Ladirettivang-keyupsiattiverànonappenainizieremoadigitarenellacaselladiricerca,reindirizzandociallavistaIndex.

Aggiungiamol’handleralcontroller:

.controller(‘appCtl’,function($scope,$location){

$scope.startSearch=function(){

$location.path(‘/’);

};

});

Sitrattadiunafunzioneabbastanzasempliceedifacilecomprensione.Quandoaggiungeremoladirettivaallacaselladiricerca,essamodificheràilpercorsocorrentenellavistaIndex.Procediamoeimpostiamola.Senonl’avetegiàfatto,èilmomentodiassegnareancheunmodelloallacaselladiricerca:

<formclass=”navbar-formnavbar-right”role=”search”>

<inputtype=”text”class=”form-control”placeholder=”Search”ng-

model=”search”ng-keyup=”startSearch()”>

</form>

Oracheabbiamovistocomereindirizzare,èsufficientefiltrareng-repeatcomeabbiamofattoinprecedenza:

<trng-repeat=”contactincontacts|filter:search”>

Ricordatechesevoletelimitarloalnome,ènecessariomodificareilmodelnellacaselladiricercanelseguentemodo:

<inputtype=”text”class=”form-control”placeholder=”Search”ng-

model=”search.name”ng-keyup=”startSearch()”>

LapageClassactive

InfineènecessarioimpostarelapageClassactive.Dobbiamoverificareilpercorsocorrenteeaggiungere,senecessario,unaclasse.Aquestoscopoutilizziamong-classe

Page 108: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

unafunzionenelcontrollerdell’app.

Lafunzioneverificheràseilpercorsocorrenteèlostessodiquellocheèstatopassato:

$scope.pageClass=function(path){

return(path==$location.path())?‘active’:‘’;

};

Sec’ècorrispondenza,restituiràlaclasseactive,altrimentinulla.Aggiungiamolaaentrambiglielementidellanavigazione:

<ling-class=”pageClass(‘/’)”><ahref=”/”>Browse</a></li>

<ling-class=”pageClass(‘/add-contact’)”><a

href=”/add-contact”>AddContact</a></li>

Dopoaveraggiuntoladirettivang-classall’elementodellalista,lapaginacorrentemostratadallaclasseactivediventainteramentedinamicaecorretta.

Page 109: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

CreateFinoraabbiamotrascuratolaprimaletteradell’acronimoCRUD,maoraèvenuto

ilmomentodifareunpassoindietroeimpostareilformdiaggiuntadeicontatti.Dobbiamoinnanzituttoverificarechetuttigliinputdelformabbianoassociatoilmodelloopportuno:

<inputtype=”text”id=”name”class=”form-control”ng-

model=”contact.name”>

Poichéabbiamorealizzatounserviziopergestireicontatti,èragionevoleestenderloperriuscireacreareconessoicontatti.Definiamounmetodocreatecheportiilcontattonell’arrayeloaggiungaall’oggettodelservizio:

create:function(contact){

contacts.push(contact);

}

Orariflettiamosuciòchevogliamoaccadadopol’inviodelform.Intendiamoinserireuncontattonell’arrayutilizzandoilmetodoappenacreatonelservizio,fornireunfeedbackpositivosuquestaoperazioneeinfinecancellaretuttodalform:

$scope.submit=function(){

contacts.create($scope.contact);

$scope.contact=null;

$scope.added=true;

};

Conilprecedentecodicesiamoriuscitinelnostrointento:abbiamopassatoilcontattoalservizio,reimpostatoilmodellodelcontattoedefinitounmodellochepossiamoverificareperfornireilfeedback.

Esistonoduesistemiperchiamarelafunzioneappenacreata.Potremmoaggiungerlacomedirettivang-clickalpulsantesubmit,maforseèpiùsaggioeaccessibileaggiungerlaaunadirettivang-submitnelform:

<formclass=”form-horizontal”ng-submit=”submit()”>

Sitrattadiincluderelafinestradiavvisopercomunicareall’utentecheilcontattoèstatoaggiuntoconsuccesso.Vogliamocheperimpostazionepredefinitasianascosta,cosìutilizzandong-showeosservandoilmodelaggiunto,possiamodeciderequandovisualizzarla:

<divclass=”alertalert-success”ng-show=”added”>

Thecontactwasaddedsuccessfully.

</div>

Page 110: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

UpdateComericorderete,nonabbiamocreatounavistadestinataunicamenteallamodifica

deicontatti.Possiamosfruttarelostessopartialcheabbiamoutilizzatoperaggiungereicontattioppurefarequalcosadipiùstimolanteconlavistacontenenteunsolocontattoecreareunadirettivapermodificareidati.

Èimprobabilechesianecessariomodificareinunavoltasolatuttiidatidiuncontatto;spessositratteràdicambiaresoltantoilnumeroditelefonool’indirizzoe-mail.LanostraideaèquelladivisualizzareiltestoafiancodiunpulsanteEdit.Alclicsudiesso,potremomodificarequeldatodelcontatto.

Chiamiamoladirettivaeditableedeseguiamolacomeabbiamofattoinprecedenza:

.directive(‘editable’,function(){

return{

};

})

Èopportunolasciarelasceltadiincluderlacomeelementopersonalizzatooppureutilizzarlamedianteunattributo.Perilmomentolautilizzeremosoltantocomeattributo,maforseinfuturopotrebberorichiederlaaltriprogetti:

.directive(‘editable’,function(){

return{

restrict:‘AE’,

templateUrl:‘/assets/partials/editable.html’

};

})

Questavoltanonsaràsufficienteunarigadimarkup,cosìabbiamodecisodiutilizzarelaproprietàtemplateUrl.Sitrattasoltantodicreareilreferencepartial,comeabbiamofattoconleroute.

ScopeOltreadeciderediutilizzareunURLperiltemplate,studieremounanuova

proprietà:scope.Essacioffremaggiorecontrollosulloscopecheintendiamoutilizzareconladirettiva.

Inquestocasoselaimpostiamocomehashsicreeràunnuovoscopeisolato.Nonereditadalgenitore,equindinondovremopreoccuparcidellaletturaodellamodificaaccidentaledeidatinelloscopedellavista.Inquestocasoabbiamoaggiuntoduevaloriallafunzionehashdelloscope:

.directive(‘editable’,function(){

return{

Page 111: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

restrict:‘AE’,

templateUrl:‘/assets/partials/editable.html’,

scope:{

value:‘=editable’,

field:‘@fieldType’

}

};

})

Lachiaveèilnomecheassegniamoalnuovoscope,mentreilvaloreèunattributodell’elemento.Notatecheabbiamoantepostoduediversiprefissiaivalori,chepertantosicomporterannoinduemodimoltodiversi.

NOTA

RicordatechegliattributiseparatidauntrattinosonoconvertitiinCamelCasedaAngular.

Quandoilprefissocorrispondealsegno=,possiamolegareunmodellodelloscopegenitorealloscopedelladirettiva.Nondobbiamoquindiutilizzarelasintassi{{}}epossiamoapprofittaredelbindingdeidatibidirezionale.

Neavremobisognoperchémodificheremoilvaloredelmodellocollegatoall’internodelladirettiva.

Seanteponiamoilsimbolo@,ladirettivautilizzeràilvaloreletteraledell’attributo.Possiamoutilizzarelasintassi{{}}perpassareilvalorediunmodellooimmettereunastringa.Quandoutilizziamoilsimbolo@nessunmodelloècollegato.

ControllerAbbiamovistoinprecedenzacomepossiamoutilizzareilmetodolinknella

direttiva,maneabbiamoancheunaltroadisposizione.Ilmetodocontrollerfunzionaesicomportapropriocomeuncontrollerdirettamenteassociatoalmodulo.Possiamoinserirequalsiasiservizionecessarioetuttocisembreràmoltofamiliare.

Ladifferenzarispettoalinkconsistenell’ordinenelqualevieneelaborato.Ilmetodocontrollervieneeseguitoprimachel’applicazioneabbiafinitodiesserecompilata,mentreilmetodolinkdopo.Dovremmoutilizzaresemprecontroller,amenochenoncreiamounadirettivawrapperperunplug-injQueryoqualcosachedeveessereeseguitodopochetuttohafinitodicaricarsi.

Inprecedenzaabbiamoutilizzatolinkperladirettivadelgravatarpoichévolevamodescrivereledifferenzetraidueapprocciall’internodelladirettiva.Aggiungiamoilmetodocontrolleralladirettiva.Inquestafasedovrebbepresentarsicosì:

.directive(‘editable’,function(){

return{

restrict:‘AE’,

Page 112: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

templateUrl:‘/assets/partials/editable.html’,

scope:{

value:‘=editable’,

field:‘@fieldType’

},

controller:function($scope){

}

};

})

NOTA

Laproprietàcontrollernelladirettivasi comportacomeunasortadiAPIeconsenteallealtredirettivedicomunicareleuneconlealtre,adifferenzadilink.

AssemblareiltuttoAbbiamoimpostatoloscopeeilcontroller.Oraèilmomentodipopolareilpartial

edefinirelafunzionalità.VisualizziamoilvaloredelmodelloeincludiamoilpulsanteEditcheattiveràl’editor:

<spanng-bind-html=”value|paragraph”></span><buttonclass=”btn

btn-defaultbtn-xs”>Edit</button>

Comericorderete,abbiamoimpostatol’aliasdelnomedell’attributomodificabilesuvalue,edèproprioquestocheutilizzeremo.Dobbiamoinoltreprevederetipidicampidiunarigaodipiùrighe;pertantoricorreremoang-bind-htmlealfiltroparagraph.

Sfrutteremong-showeng-hideperanalizzareunmodellonelloscopedelladirettiva.Èopportunoconsentireall’utentedicancellarelemodificheequindinonmodificheremoilvalorecheabbiamopassatodirettamente.Aggiungereilseguentecodicealcontrollercreaunnuovomodellochepossiamomodificare,oltreagenerarequalcosacheng-showeng-hidepossonotenered’occhio:

$scope.editor={

showing:false,

value:$scope.value

};

Èpossibileutilizzareilmodelloeditor.showingpercreareduesezionineltemplate.UnasezioneverràvisualizzataprimachefacciamoclicsuEdit,l’altradopo:

<divng-hide=”editor.showing”>

<spanng-bind-html=”value|paragraph”></span><buttonclass=”btn

btn-defaultbtn-xs”>Edit</button>

</div>

<divng-show=”editor.showing”>

</div>

Creiamolafunzionecheutilizzeremopermostrareonasconderel’editor,chechiameremodang-click:

Page 113: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

$scope.toggleEditor=function(){

$scope.editor.showing=!$scope.editor.showing;

};

OraagganciamotuttoalpulsanteEditnelpartial:

<spanng-bind-html=”value|paragraph”></span><buttonclass=”btn

btn-defaultbtn-xs”ng-click=”toggleEditor()”>Edit</button>

Ladirettivacipermetteràdiscegliereiltipodiinputnecessario(testo,e-mail,areaditestoecosìvia)anchesepreferiamol’impostazionepredefinita,unacaselladitestodiunariga,perchéèciòcheutilizzeremoconmaggiorefrequenza.Inquestocasoabbiamooptatoperunoperatoreternarioperverificareseèstatoimpostatounvaloreosesideveutilizzarel’impostazionepredefinita:

$scope.field=($scope.field)?$scope.field:‘text’;

Ladirettivang-ifèstataaggiuntadirecenteinAngularJS1.2.Adifferenzading-showeng-hide,associaodissociaelementidalDocumentObjectModel(DOM)senonsoddisfanolacondizione;inquestocasoèperfettaperverificareiltipodicampo:

<divng-show=”editor.showing”>

<divng-if=”field==‘textarea’”>

<textareang-model=”editor.value”class=”form-

control”></textarea>

</div>

<divng-if=”field!=‘textarea’”>

<inputtype=”{{field}}”ng-model=”editor.value”class=”form-

control”>

</div>

</div>

Comepotetevedere,èsemplicedautilizzareeoffreuncontrollocompletosiacheintendiamoutilizzareun’areaditestoounelementodiinput.Abbiamoanchepopolatol’attributotypedeltaginputconilvalorecheèstatopassatoeinclusoinentrambiglielementinelnuovomodello.

Noncirestacheinserireneltemplateduepulsantipersalvareocancellare.Sarebbeopportunosepararliconunfilettoorizzontale:

<divng-hide=”editor.showing”>

<spanng-bind-html=”value|paragraph”></span><buttonclass=”btn

btn-defaultbtn-xs”ng-click=”toggleEditor()”>Edit</button>

</div>

<divng-show=”editor.showing”>

<divng-if=”field==‘textarea’”>

<textareang-model=”editor.value”class=”form-

control”></textarea>

</div>

<divng-if=”field!=‘textarea’”>

<inputtype=”{{field}}”ng-model=”editor.value”class=”form-

control”>

</div>

<hr>

<buttonclass=”btnbtn-successbtn-xs”ng-

click=”save()”>Save</button>

<buttonclass=”btnbtn-defaultbtn-xs”ng-

click=”toggleEditor()”>Cancel</button>

</div>

Page 114: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

AbbiamoassociatoilpulsanteSaveaunanuovafunzionesavechedobbiamoancoracreare;ilpulsanteCancelutilizzalastessafunzionetoggleEditorprecedente.

Lafunzionesaveèsemplice;assegnailnuovomodellocheabbiamocreatoaquellocheabbiamolegatoinprecedenzaalladirettivaechiamalafunzionetoggleEditorpernasconderetutto:

$scope.save=function(){

$scope.value=$scope.editor.value;

$scope.toggleEditor();

};

Abbiamoterminatoladirettivamodificabile,macomepossiamoutilizzarla?Nelpartialcontact.htmlabbiamovisualizzatoinprecedenzatuttiimodelliall’internodeitagparagraphricorrendoallasintassiconledoppieparentesigraffe.Oracheladirettivafatuttoquestoalpostonostro,possiamosostituireilcontenutodeltag<p>eaggiungeredueattributi:

<pclass=”form-control-static”editable=”contact.email”field-

type=”email”></p>

Dopoaversostituitotuttiimodelli,dovresteottenereuneditorvisivodifacileutilizzoperognisezionedelcontatto.

Page 115: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

DeleteÈpossibilecancellareicontattigrazie,nuovamente,alservizio.Creeremoun

metodofinalecheaccetteràunindicedell’arrayelocancellerà.SiccomedeleteèunaparolachiavediJavaScript,utilizzeremodestroycomenomedelmetodo:

destroy:function(index){

contacts.splice(index,1);

}

Èunmetodomoltosemplice.Prendiamol’indiceeutilizziamoilmetodonativosplicepercancellarlodall’array.Oradobbiamocreareunafunzionesulloscopedellavistaindexingradodichiamarequestometododalservizio:

$scope.delete=function(index){

contacts.destroy(index);

};

Infineaggiungiamounpulsanteallacolonnadelleazionidellatabellapercancellarealclicilcontattovoluto:

<buttonclass=”btnbtn-dangerbtn-xs”ng-

click=”delete($index)”>Delete</button>

Page 116: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. Indicateduemodiconiqualièpossibilecondividereidatitraleviste.2. Qualisonoitretipidiservizidisponibili?3. Checosaènecessarioincludereperutilizzareng-bind-html?4. Qualèladifferenzatraimetodilinkecontrollerdiunadirettiva?5. Quandosiutilizzaloscopeisolato,checosasignificanoiprefissi=e@?6. Inchemodopossiamolimitareunadirettivaaunelementoeauncommento?7. Perchéènecessariocreareuncontrollerpertuttal’applicazione?8. Inchemodootteniamol’indicediunoggettodang-repeat?

Page 117: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoInquestocapitoloabbiamoaffrontatomoltiargomentiedèunabuonaidea

riepilogarli.Agrandilineeabbiamotrasformatociòcheeranotemplatestaticiinun’apppienamentefunzionantechepermetteilCRUD(Create,Read,Update,Delete).

Nelfrattempoabbiamoscopertomoltoaltro.Abbiamoesaminatoilsistemamigliorepercondividereidatitralevistecreandounserviziopersonalizzatopergestireicontatti.Ilserviziocompletociconsente,ovunquenell’applicazione,direcuperaretuttiicontatti,trovarneunosolo,aggiungerneunonuovoocancellarlo.

Oltreadefinireunserviziopersonalizzato,abbiamoanchecreatonuovedirettive.Laprimacihapermessodivisualizzarel’immaginediungravatarbasatasuunindirizzoe-mail.Abbiamoscopertoimoltepliciediversimodidiutilizzodiunadirettiva,tramiteunattributooperfinouncommentoHTML.

Lasecondadirettivacheabbiamocreatoèunpo’piùcomplessa.Abbiamoconsideratoscopeisolatieladifferenzatraimetodilinkecontrollerdiunadirettiva;inoltreabbiamosviluppatounottimosistemapermodificareidatidelcontatto.

NelcapitoloseguentevedremoinazionelalibreriaditerzepartiAngularStrapcheciconsentediavvalercideiplug-indiBootstrapall’internodiAngular.

Page 118: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo7

Page 119: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

AngularStrap

Abbiamodescrittol’elevatonumerodicomponentipresentiinBootstrap;oraesamineremol’utilizzodeiplug-inJavaScriptdisponibili.Èpossibilecrearedelledirettiveperciascunodiessi,malacommunitydiAngularforniscegiàunriccomodulochiamatoAngularStrap.

InquestocapitoloconsidereremoAngularStrap,iplug-incheBootstrapcipermettediutilizzareeilmodoincuièpossibileinserirlinell’applicazione.

Page 120: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

InstallareAngularStrapInnanzituttodobbiamoscaricareAngularStrap.Poteteprocurarvelodalsito

http://mgcrea.github.io/angular-strap/.Fateclicsulpulsantedidownloadinaltoadestraescaricatel’ultimaversionecomefileZIP.

Quest’ultimocontiene,tral’altro,tuttiimodulisingolisottoformadiuncomodofileminificato.Trovereteiduefilecheciservononelladirectorydist.Copiateangular-strap.min.jseangular-strap.tpl.min.jsnelladirectoryjsdelprogetto.Includetelinelfileindex.htmldellaradicedopoAngulareprimadelmodulodelprogetto:

<scripttype=”text/javascript”src=”/assets/js/angular-

strap.min.js”></script>

<scripttype=”text/javascript”src=”/assets/js/angular-

strap.tpl.min.js”></script>

Comeperognialtromodulo,ènecessarioinserirlonell’applicazione.Ladichiarazioneèsituatanellaprimarigadelcontroller.js;ilnomedelmoduloAngularStrapèmgcrea.ngStrap.DiseguitoabbiamoaggiuntoAngularStrapcomeunadipendenzadelmodulocontactsMgr:

angular.module(‘contactsMgr’,[‘ngRoute’,‘ngSanitize’,

‘mgcrea.ngStrap’])

Manonèfinitaqui.AngularStrapdipendedalmodulongAnimatechedobbiamoancoraincluderenelprogetto.LopossiamoscaricarefacendoclicsullinkExtrasnellafinestramodaledidownloadall’indirizzohttps://angularjs.org/.

AggiungetelaversioneminificataalladirectoryjsdelprogettoeincludetelaprimadiAngularStrap:

<scripttype=”text/javascript”src=”/assets/js/angular-

animate.min.js”></script>

IlmodulongAnimatenondeveessereinseritonelprogettoamenochenonvogliateusarloaldifuoridelledirettivediBootstrap.ConsentedisfruttareleanimazioniCSSinmodulicomengShowengHideperottenereuneffettoditransizioneinvecedivisualizzaresemplicementequalcosa.

PotremmoanchesvilupparedelleanimazionidautilizzareinsiemeconAngularStrap,ancheseAngularMotionèilsuocompagnoperfetto.SitrattadiunsemplicefogliodistilechecontieneanimazionipredefiniteprontedautilizzareconilmodulongAnimate.

Page 121: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Possiamoscaricarel’ultimaversionedalsitohttp://mgcrea.github.io/angular-motion/facendoclicsulpulsantedidownloadinaltoadestra.AnchequestofileZIPcontieneifilesorgenteoltreallaversioneminificataprontaperlaproduzione,presentenelladirectorydist.Copiatelanelprogettoeincludetelanellapaginacomefogliodistilesecondario:

<linkrel=”stylesheet”href=”/assets/css/angular-motion.min.css”>

Orapotremocreareeffettiditransizione,farscorrere,ridimensionareeruotareleanimazionifornitedaAngularMotioninsiemeconledirettiveAngularStrap.

Forsevisembreràstranochenonsianecessarioincludereloscriptdeiplug-indiBootstrap.C’èunmotivo:ledirettivecheabbiamoinclusoconAngularStrapnonsonosemplicifunzioniwrappercheeseguonojQuery,mariscritturecompletechesfruttanoappienoAngular.

Page 122: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

UtilizzareAngularStrapDopoaverinstallatoAngularStrap,esaminiamoalcunisuoiplug-inecome

utilizzarli.

Primadiiniziare,impostiamorapidamenteunambientedemo.Duplichiamoilfileindex.htmlerinominiamolodemo.html.ModificheremoancheilcontrollerindemoCtrleloaggiungeremoalfilecontroller.js.Inquestomodoavremounospazioincuioperare.

LafinestramodaleUnafinestramodaleèunparadigmaUImoltocomunenelleapp.Èunottimo

sistemapervisualizzarepocheinformazionisenzaindirizzarel’utenteaunanuovapagina.

Puòesserechiamataalclicsuunpulsanteacuièapplicataladirettivabs-modal:

<buttonclass=”btnbtn-primary”bs-modal=”modal”>Show

Modal</button>

Ilvalorechevienepassatoèunmodellodelloscope;èunhashcontenenteduevalori:titleecontent.Eccoloall’internodelcontroller:

$scope.modal={

title:‘ModalTitle’,

content:‘Modalcontent’

};

Esistonoalcuneopzionidasfruttareconladirettivamodal;sonoapplicateall’elementocomeattributiefatteprecederedadata-.Peresempio,seintendiamomodificarel’animazione,possiamoscriverequestocodice:

<buttonclass=”btnbtn-primary”bs-modal=”modal”data-

animation=”am-fade-and-scale”>ShowModal</button>

cheutilizzeràl’animazionefade-and-scalediAngularMotion.RicordatevidivisitareilsitodiAngularMotionperunalistacompletadelleanimazionidisponibili.

Latabellaseguente,trattadalsitodiAngularStrap,illustralalistaditutteleopzionidisponibiliperladirettivamodal.

Nome Tipo Impostazionepredefinita Descrizione

animation stringa am-fade Applicaun’animazioneCSS.

backdropAnimation stringa am-fade Applicaun’animazioneCSSallosfondo.

placement stringa 'top'Posizionaladirettivamodal:inalto(top)/inbasso(bottom)/alcentro(center).

Page 123: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

title stringa '' Valorepredefinitodeltitolo.

content stringa '' Valorepredefinitodelcontenuto.

html booleano false Sostituisceng-bindconng-bind-html.

backdropbooleanoo'static'

true

Includeunelementomodaledellosfondo.Utilizzastaticperlosfondo,chenonchiudelafinestramodalealclic.

keyboard booleano trueChiudelafinestramodalequandosipremeiltastoEsc.

container stringa/false falseAggiungelafinestramodaleaunelementospecifico.Esempio:container:'body'.

template percorso false Sefornito,scavalcailtemplatepredefinito.

contentTemplate percorso falseSefornito,recuperailpartialeloincludecomecontenutointerno.

TooltipItooltipsonounottimosistemaperoffriresuggerimentieconsiglisenzaessere

invadenti.AngularStrapnesemplifical’inclusione;liattiviamoconilclic,l’hoveroilfocus:

<buttonclass=”btnbtn-link”bs-tooltip=”tooltip”>what’s

this?</button>

Inquestocasoabbiamounpulsante(alqualeèstatoapplicatounostileinmododafarlosembrareunlinkgraziealleclassidiBootstrap)eabbiamoinclusoladirettivabsTooltip.

Cosìcomeabbiamofattoconladirettivamodal,possiamopassareunmodelloalladirettiva.Questavoltadobbiamoincluderesoltantolaproprietàtitlenell’oggetto:

$scope.tooltip={

title:‘TooltipTitle’

};

Perimpostazionepredefinitailtooltipcompariràall’hoversulpulsante,maèpossibilemodificarlafacilmenteutilizzandogliattributidatacheabbiamovistoinprecedenza:

<buttonclass=”btnbtn-link”bs-tooltip=”tooltip”data-

trigger=”click”>what’sthis?</button>

Ladirettivaciconsenteanchedilegarlaauninputemostrareiltooltipalfocus.Ancheilposizionamentopuòesseredefinitodall’attributodata:

<inputtype=”text”bs-tooltip=”tooltip”data-trigger=”focus”data-

placement=”right”>

Page 124: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Questocodicemostreràiltooltipadestraquandol’inputottieneilfocus.DiseguitopotetevederelalistaditutteleopzionipresentenelladocumentazionediAngularStrap.

Nome Tipo Impostazionepredefinita Descrizione

animation stringa am-fade Applicaun’animazioneCSS.

placement stringa 'top'Posizionailtooltip:top/bottom/left/rightoqualsiasialtracombinazionecomebottom-left.

trigger stringa 'hover'Definiscecomesiattivailtooltip:click/hover/focus.

title stringa '' Valorepredefinitodeltitolo.

html booleano false Sostituisceng-bindconng-bind-html.

delay numero/oggetto 0

Ritardalacomparsaolascomparsadeltooltip(ms);nonsiapplicaaun’attivazionemanuale.Sevieneindicatounnumero,ilritardosiapplicasiaahidesiaashow.Lastrutturadell’oggettoèlaseguente:delay:{show:500,hide:100}.

container stringa/false falseAggiungelafinestramodaleaunelementospecifico.Esempio:container:'body'

template percorso false Sefornito,scavalcailtemplatepredefinito.

contentTemplate percorso falseSefornito,recuperailpartialeloincludecomecontenutoall’interno.

PopoverIpopoversonounasortaditooltipestesoefornisconoun’areatitleecontent.

Similiaitooltip,sipossonoattivarealclic,all’hoveroalfocus:

<buttonclass=”btnbtn-primary”bs-popover=”popover”>Show

Popover</button>

Ilmodelloassociatoèidenticoperformatoaquelloutilizzatoperlafinestramodalepoichécontieneleproprietàtitleecontent:

$scope.popover={

title:‘Title’,

content:‘Popovercontent’

};

Ovviamentetuttoèmodificabilemediantegliattributidata.Laprossimatabellariportaunalistacompletadelleopzioni.

Nome Tipo Impostazionepredefinita Descrizione

animation stringa am-fade Applicaun’animazioneCSS.

placement stringa 'top'Posizionailtooltip:top/bottom/left/right,oqualsiasialtracombinazionecomebottom-left.

Page 125: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

trigger stringa 'hover' Definiscecomesiattivailtooltip:click/hover/focus.

title stringa '' Valorepredefinitodeltitolo.

content stringa '' Valorepredefinitodelcontenuto.

html booleano false Sostituisceng-bindconng-bind-html.

delay numero/oggetto 0

Ritardalacomparsaolascomparsadeltooltip(ms);nonsiapplicaaun’attivazionemanuale.Sevieneindicatounnumero,ilritardosiapplicasiaahidesiaashow.Lastrutturadell’oggettoèlaseguente:delay:{show:500,hide:100}

container stringa/false falseAggiungelafinestramodaleaunelementospecifico.Esempio:container:'body'.

template percorso false Sefornito,scavalcailtemplatepredefinito.

contentTemplate percorso falseSefornito,recuperailpartialeloincludecomecontenutoall’interno.

AlertAbbiamogiàvistocomeèpossibileutilizzarelefinestrediBootstrapperoffrireun

feedbackagliutenti.AngularStrapciconsentedievidenziarle,applicareuneffettoditransizioneopermettereagliutentidirimuoverle.Utilizziamoladirettivaalertaggiungendol’attributobs-alertaunelemento:

<buttonclass=”btnbtn-primary”bs-alert=”alert”>Show

Alert</button>

L’oggettodelmodellodefiniscenonsoloiltitoloeilcontenutomaanchelaclassecontextcheutilizzeremo.Puòesseresuccess,info,warningodangeremodificheràopportunamenteilcoloredellosfondoedeltesto:

$scope.alert={

title:‘Title’,

content:‘Alertcontent’,

type:‘success’

};

Definiremoconprecisionedoveverràaggiuntalafinestradiavviso;possiamoutilizzarel’attributodata-containerperdefinireunelementospecificoincuidesideriamovisualizzarla.Creiamounnuovoelementoincimaallapaginaperilcontenitore:

<divid=”alertContainer”></div>

Aggiungiamoloalpulsantemediantel’attributodata-container:

<buttonclass=”btnbtn-primary”bs-alert=”alert”

data-container=”#alertContainer”>ShowAlert</button>

Page 126: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Oraquandofaremoclicsulpulsante,incimaalloschermocompariràlafinestradiavviso.SulsitodiAngularStrapèdisponibilelalistaseguenteditutteleopzionidisponibili.

Nome Tipo Impostazionepredefinita Descrizione

animation stringa am-fade Applicaun’animazioneCSS.

placement stringa 'top'Posizionailtooltip:top/bottom/left/rightoqualsiasialtracombinazionecomebottom-left.

title stringa '' Valorepredefinitodeltitolo.

content stringa '' Valorepredefinitodelcontenuto.

type stringa 'info' Valorepredefinitodeltipo.

keyboard booleano trueChiudelafinestradiavvisoquandosipremeiltastoEsc.

container stringa/false falseAggiungelafinestramodaleaunelementospecifico.Esempio:container:'body'.

template percorso false Sefornito,scavalcailtemplatepredefinito.

Page 127: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

UtilizzareiservizidiAngularStrapLamaggioranzadeimoduliinclusiinAngularStrapesponeancheiserviziper

l’applicazione.Possiamoutilizzarlipermostrareelementi,comefinestremodali,finestrediavvisoepopoversenzaesserecostrettiaricorrerealledirettive.

Vediamocomeutilizzareilservizio$alertpermostrareunafinestradiavvisodalcontroller.Ciserviremodelladirettivang-clicksuunpulsanteperavviarla.Creiamoinnanzituttounpulsanteeassociamoladirettivang-click:

<buttonclass=”btnbtn-success”ng-click=”showAlert()”>Alertvia

Service</button>

ImposteremorapidamentelafunzioneshowAlert()nelcontroller.Comeprimacosaoccorrecreareunafinestradiavvisoutilizzandoquestoservizio.Inseriamo$alertnelcontrollerecreiamounanuovaistanzadiunafinestradiavvisoconilcodiceseguente:

controller(‘demoCtl’,function($scope,$alert){

varalert=$alert({

title:‘AlertTitle!’,

content:‘Here\’ssomecontent.’,

type:‘danger’,

container:‘#alertContainer’,

show:false

});

});

Ilcostruttoredelservizioaccettaunafunzionehashseguendolostessopatternaccettatodalladirettiva.Quipossiamoincluderequalsiasiopzione,comeilcontenitorealqualedesideriamoaggiungerelafinestradiavviso.Perimpostazionepredefinitalafinestradiavvisochevienecreatacompariràautomaticamente.Pernasconderlaènecessarioincluderelaproprietàshoweimpostarlasufalse.

Infinenonrimanechedefinirel’handlershowAlert().L’istanzadellafinestradiavvisocreatadalserviziocioffretremetodidicuipossiamoservirci:show(),hide()etoggle().Utilizziamoshow():

$scope.showAlert=alert.show;

Sefacciamoclicsulnuovopulsante,lafinestradiavvisocompariràincimaallapagina(oovunqueabbiamoposizionatoilcontenitore)esicomporteràcomeprevisto.

Page 128: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

IntegrareAngularStrapDopoavervistocomeèpossibileutilizzaremoltiplug-in,ènecessariorenderli

operativievivacizzarel’appdigestionedeicontatti.Utilizzeremoiplug-intooltipealertperfornireagliutentisuggerimentiefeedback.

SostituiamoinnanzituttoiltestodelsuggerimentosottolacasellaNotesnellavistaAddContactconuntooltip:

<textareaid=”notes”class=”form-control”ng-model=”contact.notes”

bs-tooltipdata-title=”Anyadditionalinformationaboutthe

contact.”data-trigger=”focus”

data-placement=”bottom”></textarea>

Invecedicreareunmodelloelegarloalladirettiva,hapiùsensosfruttarel’attributodata-titledisponibile.Inquestocasoabbiamopreferitocollocarlosottoeavviarloalfocus.

Potrebberoessereopportuneduefinestrediavviso.Unaèquellapreesistentedopol’aggiuntadiunnuovocontatto;l’altracomparedopoavercancellatouncontattonellavistaIndex.

Consideriamoprimalafinestradiavvisopreesistente.Sidevesostituirel’elementoalertconilcontenitorecreatoinprecedenza:

<divid=”alertContainer”></div>

Possiamoinserireilservizio$alerteprepararel’istanzadellafinestradiavvisoprimadivisualizzarlaall’internodellafunzionesubmit.Essaavràlaseguenteconfigurazione:

varalert=$alert({

title:‘Success!’,

content:‘Thecontactwasaddedsuccessfully.’,

Page 129: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

type:‘success’,

container:‘#alertContainer’,

show:false

});

L’aggiungeremoall’alertContainercreatoinprecedenza.Inquestocasoilcontextrichiedeunmessaggiodisuccesso;pertantoabbiamoimpostatotypesusuccess.

Noncirestachemostrarelafinestradiavvisodopocheèstatocreatoconsuccessouncontatto:

$scope.submit=function(){

contacts.add($scope.contact);

$scope.contact=null;

alert.show();

};

Possiamoprocedereallostessomodoquandocancelliamouncontattoperoffriremaggiorefeedbackall’utente.Comeprima,collochiamoilcontenitorenellaposizioneincuivorremmochecomparisserolefinestrediavvisonellavistaIndex:

<divid=”alertContainer”></div>

Dobbiamoinserireilservizio$alertnelcontroller:

.controller(‘indexCtrl’,function($scope,contacts,$alert){

OrapossiamoutilizzareilservizioappenainseritopercrearedeletionAlert:

vardeletionAlert=$alert({

title:‘Success!’,

content:‘Thecontactwasdeletedsuccessfully.’,

type:‘success’,

container:‘#alertContainer’,

show:false

});

Perconcludere,noncirestachefarcomparirelafinestradiavvisoquandofacciamoclicsulpulsantedelete:

$scope.delete=function(index){

contacts.destroy(index);

deletionAlert.show();

};

Eccocomedovrebbeesserel’output:

Page 130: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap
Page 131: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. DaqualemodulodipendeAngularStrap?2. QualèilnomedelprogettochepossiamoutilizzareperleanimazioniCSS

predefinite?3. Checosaènecessarioanteporreagliattributiperutilizzarlicomeopzioni

all’internodelledirettivediAngularStrap?4. Qualisonoiquattrosistemiconiqualièpossibileattivareunpopoveroun

tooltip?5. Qualisonoitremetodidisponibilipercreareun’istanzamedianteilserviziodi

alert?

Page 132: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoInquestocapitoloabbiamovistocomeèfacileavvalersideinumerosimoduli

integratiinAngularStrap.AnchesenonpossonoutilizzaredirettamenteJavaScriptdiBootstrap,sonotutticomponentilegatiaquestoframeworkeoperanosenzasoluzionedicontinuitàall’internodell’applicazione.Abbiamoesaminatosoloalcunideiplug-indisponibilieilmodoincuièpossibileutilizzarlimedianteledirettive.Talvoltaunadirettivanonèlasoluzionemigliore;inalternativaèpossibilericorrereaiservizicompresiinAngularStrap.Nelcapitoloseguentevedremocomeèpossibileconnetterel’applicazionealserverperrecuperareememorizzareicontatti.

Page 133: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo8

Page 134: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Connessionealserver

Finoral’applicazioneèancorainteramentefront-endedè,pertanto,piuttostoinutile.Ènecessariomemorizzareicontattiperpoterlirecuperareinseguito.Aquestoscopociconnetteremoaunservercheospiteràun’APIRESTfulchegeneraJSON.

Angularoffrediversepossibilitàperconnettersialserver.Inquestocapitoloneesamineremoalcune,oltreaintrodurredellealternativechepotreteapprofondireinseguito.

Nonvedremocomesvilupparel’aspettorelativoallatoserver,chenonrientranegliambitidellanostratrattazione.Tuttaviaèpresentenellerisorsescaricabilidellibro.

Eccogliargomenticheaffronteremo:

comeestrarreidatidalservermediante$http;comeutilizzareedovetrovarengResource;lealternativedellacommunitytracuiRestAngular;integrazionenell’applicazionedellanuovaconnessioneconilserver.

Mettiamociall’opera.

Page 135: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Connettersicon$httpAngularincludegiàalcunimetodidibassolivelloperrecuperareeinviareidati.

Seaveteutilizzato$.ajax,$.posto$.getinjQuery,sareteavostroagio.

Comesapete,questimetodisonodisponibilisottoformadiunserviziocheèpossibileinserireneicontrolleroneiservizi.Diseguitopoteteosservareilservizio$httpinseritonelcontroller:

.controller(‘indexCtrl’,function($scope,contacts,$alert,

$http){

})

IlservizioincludealcunimetodichefunzionanocontuttiiverbidelprotocolloREST.Imetodiseguentisonodisponibiliall’internodi$http.

$http.get():accettaunURLeunoggettoconfigfacoltativo.EsegueunarichiestaHTTPGET.$http.head():accettaunURLeunoggettoconfigfacoltativo.EsegueunarichiestaHTTPHEAD.$http.post():accettaunURL,unoggettodataeunoggettoconfigfacoltativo.EsegueunarichiestaHTTPPOST.$http.put():accettaunURL,unoggettodataeunoggettoconfigfacoltativo.EsegueunarichiestaHTTPPUT.$http.delete():accettaunURLeunoggettoconfigfacoltativo.EsegueunarichiestaHTTPDELETE.$http.jsonp():accettaunURLeunoggettoconfigfacoltativo.IlnomedellafunzionedicallbackdovrebbeesserelastringaJSON_CALLBACK.$http.patch():accettaunURL,unoggettodataeunoggettoconfigfacoltativo.EsegueunarichiestaHTTPPUT.

Tuttiquestimetodisonoscorciatoieperlafunzioneprincipale$http(),cheaccettaunargomento:unoggetto.Lefunzioniprimamenzionateimpostanoilverboe/oiltipodicontenutocheintendiamorecuperare.

Peresempio,idueframmentidicodiceseguentisonoidentici,mailsecondoèmoltopiùleggibile:

$http({

method:‘GET’,

url:‘http://localhost:8000’

});

Page 136: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

$http.get(‘http://localhost:8000’);

RecuperareidatièfacileeAngularbeneficiadeipatternPromisessviluppatidaPromises/A+eresipopolaridajQuery.Ilpatternciconsentedideterminarefacilmentesel’URLalqualeabbiamoavutoaccessoharestituitounarispostapositivaohageneratounerrore.

Puòsembrarecomplesso,mainsostanzasitrattadiunaseriedimetodichepossiamoconcatenarepercrearefacilmenteunapprocciotry/catchperlechiamateasincrone.Seracchiudiamoconsole.login$http.get(),vedremotuttiimetodidisponibilivisualizzatinellaconsole.

Tuttiimetodiaccettanoun’unicafunzionedicallback,conl’eccezionedithen,cheaccettaduemetodi,unoperilsuccessodell’operazioneeunaltroperl’errore.Vediamocomepossiamoutilizzarli.Nelcontrollerdell’index,sostituiamoallarigacontacts.get()ilseguentecodice:

$http.get(‘http://localhost:8000’)

.success(function(data){

$scope.contacts=data;

})

.error(function(){

window.alert(‘Therewasanerror!’);

});

Angularsioccuperàdelresto.Lafunzionedicallbackperilmetodosuccessvieneeseguitaquandovienerestituitouncodicedistatus2xx;altrimentivieneeseguitounerrore.

Avremmopotutoabbreviareilcodiceprecedenteutilizzandoilmetodotheneduefunzionidicallback,nelseguentemodo:

$http.get(‘http://localhost:8000’)

.then(function(result){

$scope.contacts=result.data;

},function(){

window.alert(‘Therewasanerror!’);

});

Page 137: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

QuestofaperòrisparmiarepococodiceedèmenoleggibileperaltrisviluppatorichepotrebberononconoscereAngularJS.Notatechedatanonèl’argomentopassatoallefunzionidicallbackall’internodelmetodothen;otteniamoinveceunoggettocontenentedati,statoeheader.

InviareidatiComeilrecuperodeidati,illoroinviomediante$httpèmoltofacileesimile

all’implementazionedijQuery.Lafunzione$http.post()sicomportanellostessomododi$http.get()maaccettaunsecondoparametro:unhashcontenentetuttiidaticheintendiamoinviarealserver:

$http.post(‘http://localhost:8000’,{

name:‘DeclanProud’,

email:‘[email protected]’,

...

});

Analogamente,ilmetodopostrestituisceancheunapromiseconglistessimetodiesaminatiprima:

$http.post(‘http://localhost:8000’,{

name:‘DeclanProud’,

email:‘[email protected]’,

...

})

.success(function(){

...

})

.error(function(){

...

});

Page 138: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ConnettersiconngResourceGlihelperdellaconnessionedibassolivellocome$httpsonoottimiper

connessionisingole,madiventanobenprestoscomodiperlagestionediuninteroprogetto.FortunatamenteAngularoffreunaltrosistemaconilqualeaccedereaidatilatoservergrazieaunmodulofacoltativochiamatongResource.

IncluderengResourceComengRoute,ilmodulongResourcesitrovaallinkExtrasnellafinestramodaledi

downloadall’indirizzohttps://angularjs.org/.Scaricateloetrascinatelonelladirectoryjsdelprogetto.IncludetelodopoAngularnelfileradiceHTML:

<scripttype=””text/javascript””src=”/assets/js/angular-

resource.min.js”></script>

VerificatecheilmodulocontactsMgrsappiachengResourceèunadipendenza:

angular.module(‘contactsMgr’,[‘ngRoute’,‘ngSanitize’,

‘mgcrea.ngStrap’,‘ngResource’])

ConfigurarengResourceIlmoduloesponeilservizio$resourcecheèpossibileinserireneicontrolleronei

servizi.Imetodiinclusisonodiunlivellopiùalto,einfattiutilizzano$httpperinteragireconilserver.Inseriamoilservizio$resourcenelserviziodigestionedeicontatticreatonelCapitolo7evediamocomeconnettersialserver:

.factory(‘Contact’,functionContactFactory($resource){

...

})

Ilservizioincludeunmetodocheutilizzeremoperimpostarelaconnessione.Restituiscealcunefunzionisottoformadiunoggettoresource.Sarannoquestefunzioniarecuperareeainviareidatialedalserver.

Vediamocomepossiamoservircidiquestometodosingoloeciòcherestituisce:

varResource=$resource(‘http://localhost:8000/contacts/:id’,

{id:‘@id’});

Ilcodicerestituiràl’oggettoseguente,consistenteinazionicheèpossibileutilizzareperrecuperare,salvareocancellareidati:

{

‘get’:{method:’GET’},

‘save’:{method:’POST’},

Page 139: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

‘query’:{method:’GET’,isArray:true},

‘remove’:{method:’DELETE’},

‘delete’:{method:’DELETE’}

};

Ilprimoparametroèlaradicedellarisorsasulserver.Peresempio,sestessimosviluppandounsistemadiblogging,avremmoalcunerisorsecomepost,tageautori.Èanchepossibileaggiungeredeisegnaposto,comepotremmofaredurantelacreazionediunaroute.

Ilsecondoparametroèunhashcheincludeivaloripredefinitideisegnaposto.Seilvalorepredefinitodiunsegnapostopresentasseilprefissocontenenteilsimbolo@,quelvaloresarebberecuperatodall’oggettodatachevienepassatoquandoaccediamoalserver.

Possiamoanchepassareunterzoparametroperestendereleazionipredefinitechevengonorestituite.AggiungiamounmetodoupdatecheutilizzeràilverboPUTperaggiornareuncontattoesistentesulserver:

varResource=$resource(‘http://localhost:8000/contacts/:id’,

{id:‘@id’},{

update:{method:‘PUT’}

});

Comepotetevedere,sitrattadiunoggettoJSstandardincuièpossibiledefiniremoltepliciazionipersonalizzate.Esistonoalcunielementicheèpossibileincludereall’internodell’oggettoconfigurationassociatoall’azione,maprobabilmentesarànecessarioimpostaresoltantomethodeisArray.LaproprietàmethodselezionaqualeverboHTTPènecessarioutilizzare(inquestocasoPUT),eisArrayèunbooleanocheserveaindicareangResourceseilserverrestituiràununicoitemounarraydiitem.

RichiederealserverSiamoriuscitiaconfigurarengResource;oradobbiamosoloattivarlo,operazione

moltofacile.Sitrattadiutilizzareunadelleazionirestituitedall’oggetto$resource.

Intendiamorecuperaretuttiicontatti:ilmetodoquerysembralasoluzioneideale.UtilizzailmetodoGETelaproprietàisArrayvieneverificata:

.factory(‘Contact’,functionContactFactory($resource){

varResource=$resource(‘http://localhost:8000/:id’,{id:

‘@id’},{

update:{method:‘PUT’}

});

return{

get:function(){

returnResource.query();

},

...

Page 140: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

};

})

Eccofatto!Nondobbiamopreoccuparcidell’unwrappingdellepromiseperchéquestoaspettovienegestitoautomaticamentedangResource.Noncirestacherieseguirelachiamata$httpinindexCtlalmetodoContact.get():

$scope.contacts=Contact.get();

Siccomenonutilizzeremopiùunarrayditipohard-code,nonpossiamoaccedereasingolicontattiservendocidiunindice.LamaggiorpartedelleAPIrestituisceunIDdegliitemequestanonfaeccezione.Modifichiamo{{$index}}dang-repeatutilizzatonellink,peravvalercidell’IDinvecechedeisingolicontatti;dovrebbetrovarsiall’incircaariga23nelfilepartials/index.html:

<ahref=”/contact/{{contact.id}}”class=”btnbtn-defaultbtn-

xs”>View</a>

Ènecessariomodificareilmetodofindnelserviziodeicontattiperrecuperareununicocontattoinbaseall’IDaessoassegnato.Abbiamogiàimpostatolarisorsaperammettereunparametroid;noncirestachepopolarloquandoutilizzeremoilmetodogetdellarisorsa:

find:function(id){

returnResource.get({id:id});

},

Abbiamoanchemodificatoilnomedelparametrodaindexaidperrenderlopiùleggibilesequalcunaltrodovesselavorareinseguitoalprogetto.

InviarealserverQuestoèciòchevienerecuperatodalserver,mainchemodopossiamocreareun

nuovocontattooaggiornarneunoesistenteconngResource?EsaminiamoprimacomecrearneunoeosserviamocomengResourcegestiscequestoaspetto.Modificheremoilmetodocreatenelserviziodigestionedeicontattiperrestituireunanuovaistanzadellarisorsa:

create:function(){

returnnewResource();

},

QuestodiventeràilmodellonellavistaAddContact.Sicomportacomeprevisto,madàaccessoaunmetodo$saveperpassarloalserver.Chiamiamoilnuovometodocreateeassegniamoloalmodellocontactall’internodiaddCtl:

$scope.contact=Contact.create();

Page 141: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Tuttodovrebbecomportarsicomeprevistoquandocarichiamolavista;oraènecessariosostituirealmetodocontacts.set,ormainonpiùattivo,l’handlersubmitperlanuovafunzione$saveoffertadallarisorsa:

$scope.submit=function(){

$scope.contact.$save();

$scope.contact=Contact.create();

alert.show();

};

Abbiamoanchemodificato$scope.contact,chenonvienepiùeliminatomarecuperaunanuovaistanzadellarisorsadalservizio.

Analogamentepossiamoutilizzarelastessaazioneupdatecreatainprecedenzapersalvarelemodifichediuncontattoesistente.Aquestoscopoènecessarioservirsidiuneventopersonalizzatoinmodocheilcontrollersappiaquandosalviamolemodificheall’internodelladirettivamodificabile.GlieventipersonalizzatisicomportanopropriocomegliomologhinativiJavaScript,alparidiclickemouseover.Èpossibilemettersiinascoltoedeseguiredelleazioniquandovengonoattivati.

Percreareuneventopersonalizzato,utilizziamoilmetodo$scope.$emit.Accettadueparametri:ilnomedell’eventoel’arraydiparametricheintendiamopassareallistener.Inquestocasononènecessariopassarealcunparametro;chiamiamosemplicementel’eventosalvatoeinseriamolonellafunzione$scope.saveall’internodelladirettivamodificabile:

$scope.$emit(‘saved’);

Ascoltareuneventoèaltrettantofacile:èsufficienteutilizzareilmetodo$scope.$on.Essoaccettadueparametri:ilprimoèilnomedell’eventodaascoltare,ilsecondoèlafunzionedell’handler.AggiungiamoilseguentecodicealcontrollercontactCtl:

$scope.$on(‘saved’,function(){

...

});

Seavessimopassatodeiparametriall’evento,sarebberostatiaccessibilicomeparametrinellistenerdeglieventieilprimosarebbesemprestatol’eventoJS.

Illistenereseguiràilmetodo$updatesulmodellocontact.Tuttavia,siccomel’eventovieneemessoprimacheilmodelloabbiaconclusol’aggiornamento,dobbiamospingerloallafinedellostackodellacodacorrente.SeconosceteJavaScript,sapretecheèpossibileutilizzaresetTimeout.Èpropriociòchefaremo,mainvecediservircidisetTimeout,opteremoperilserviziowrapperdiAngular:$timeout.

Dobbiamoinserirlonelcontroller:

Page 142: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

.controller(‘contactCtrl’,function($scope,$routeParams,Contact,

$timeout){

...

})

PoisitrattasemplicementediutilizzarlocomesetTimeout:

$scope.$on(‘saved’,function(){

$timeout(function(){

$scope.contact.$update();

},0);

});

Orasemodifichereteuncontattoefareteclicsulpulsantesave,idativerrannosalvatisulserver.

CancellareicontattiInfine,noncirestacheimpostareilpulsantedelete.Modifichiamoilmetodo

all’internodelserviziodeicontatti:

destroy:function(id){

resource.delete({id:id});

}

Inquestocasochiamiamoilmetododeletesullarisorsa;volendoavremmopotutoutilizzareremovechesvolgelastessaoperazione.Abbiamonuovamentemodificatoilnomedelparametroindexperrenderlopiùleggibile.

Dobbiamoancoracompiereun’operazioneinquestaistanza:aggiornarelafunzionedeletenelcontrollerindexCtl.Analizziamoallorailmetodofinito:

$scope.delete=function(index){

Contact.destroy($scope.contacts[index].id);

$scope.contacts.splice(index,1);

alert.show();

};

Siccomedobbiamosiaeseguireilpingdelserversiarimuoverlodall’arraylocale,ènecessariocontinuareautilizzareindex.NellachiamataContact.destroy()accediamoalcontattoopportunoerecuperiamoilsuoID.Locancelliamodirettamentedall’arraylocaleutilizzandoilmetodoJSnativospliceperfareinmodochetuttosiasincronizzato.

GestionedeglierroriÈpossibilegestireglierroricomefaremmocon$http.Tutteleazionicheabbiamo

esaminatoaccettanoduefunzionidicallback:unaperilsuccessoel’altraperl’errore.Eccoilmetodogetconincluseentrambelefunzionidicallback:

Page 143: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

returnResource.get({id:id},function(){

window.alert(‘Success!’);

},function(){

window.alert(‘Error!’);

});

Cosìpossiamoinformarel’utentecheesisteunproblemaoeseguirealtreazionisenecessario.Siccomelofacciamodaunservizio,èopportunoincluderedueparametriperconsentirechequestefunzionidicallbackvenganoimpostatedalcontrollerquandovienechiamatoilmetodoinquestione:

find:function(id,success,error){

returnRgesource.get({id:id},success,error);

},

Page 144: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

SistemialternatividiconnessioneAbbiamogiàesaminatoalcunisistemiconiqualièpossibileconnettersialservere

configurarel’apppersfruttarengResource.Esistonoaltrimodulicheèpossibileutilizzareperconnettersiaunserver;neconsidereremorapidamentedue.

RestAngularRestAngularèunprogettodellacommunitycheoffreunservizioperconnettersi

adAPIRESTful,comengResource.Presentaalcunedifferenzesignificativecheèopportunoconoscere.

L’aspettopiùimportantedatenerepresenteècheRestAngularutilizzapromisepropriocome$http.Pertantosiaccedeaunpatternperdeterminareseunachiamatahaavutosuccessoomeno,maquestosignificacheesistonopassiaggiuntividacompiereechenonèpossibileassegnarlosemplicementeaunmodello.

Ancheseènecessarioscrivereunpo’piùdicodiceacausadell’utilizzodellepromise,nondovretetrascrivereisegnapostoseguendoilpatternREST;RestAngularlofaràalpostovostro.

PreferiamongResource.RestAngularrichiedealcunipassaggiinpiù,mentrengResourcefunzionaperfettamenteconinostriservizi.TuttaviavalesemprelapenasperimentareciòchepotrebberivelarsiefficaceperleproprieesigenzeequindiconsigliamodiprovareancheRestAngular.

UtilizzareRestAngular

ÈpossibilescaricareRestAngulardalsitohttps://github.com/mgonto/restangulareincluderlocomequalunquealtromodulo.Vedremorapidamentecomeimpostarloeinchemodoèpossibileottenereunalistadeicontatti.

ApprezziamolacapacitàdiRestAngulardiimpostareunURLdibase.ÈpossibiledefinirlonelmetodoglobaleconfigdelmodulotramiteilservizioRestangularProvider:

.config(function($routeProvider,$locationProvider,

RestangularProvider){

RestangularProvider.setBaseUrl(‘http://localhost:8000/’);

})

Dopoaverimpostatol’URLdibase,possiamoutilizzareRestAngularnominandolarisorsaallaqualeintendiamoaccedereeunmetododiRestAngular:

Page 145: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Restangular.all(‘contacts’).then(function(contacts){

$scope.contacts=contacts;

});

Comepotetenotare,RestAngularsibasasulpatterndellepromiseutilizzatoda$httpedènecessarioeseguirel’unwrappingperassegnarealmodelloidatirestituiti.

LeggeteladocumentazionediRestAngularsuGitHubperunalistacompletadeimetodicheèpossibileutilizzare.

FirebaseFirebaseèunserviziorelativamentenuovocheconsentedicrearefacilmente

un’applicazioneintemporealesenzascrivereunasolarigadicodicediback-end.QuandosioperaconAngular,l’aziendaoffreun’utilelibreriadihelperpersincronizzarefacilmenteidaticonilsuoservizio.

LadashboarddiFirebaseconsentedivisualizzareidatiinunastrutturaadalberocomprimibilesimileaquellamostratasuccessivamente.

Dopoavercreatounaccountall’indirizzohttp://firebase.comeconfiguratol’app,ègiuntoilmomentodiimpostareAngularFire.DobbiamoincludereilclientFirebaseeAngularFire,chesipossonotrovareall’indirizzohttp://angularfire.com.

ÈmoltofacilerecuperareidatidaFirebase,considerandochetuttoavvieneintemporealeequalsiasimodificacompiutaaltrovesirifletteautomaticamentenell’applicazione.Comelamaggiorpartedeimoduli,AngularFireesponeunservizio,inquestocaso$firebase.Possiamoinserirloneicontroller,nelledirettiveoneiservizi,nelseguentemodo:

.factory(‘Contact’,functionContactFactory($resource,$firebase){

...

})

Page 146: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ÈpossibileavviarelaconnessioneconFirebaseutilizzandoilsuoclientJS:

varcontacts=new

Firebase(“https://<yourbase>.firebaseio.com/contacts”);

IlservizioAngularFirefacilitailrecuperodeidatidaFirebase.Questoèciòchepotremmofareconilmetodogetdelnostroservizio:

get:function(){

return$firebase(contacts);

},

Ancheaggiungereicontattièmoltofacile.Dopoaverrecuperatoidati,otteniamol’accessoaimetodi$add,$removee$update:

$firebase(contacts).$add({

name:‘DeclanProud’,

...

});

SeapriteilpannellodicontrollodiFirebaseeaggiungetemanualmenteuncontatto,vedretechequestocompariràautomaticamentenellalistadeicontatti.Ovviamenteèesageratoperun’appcomequestachegestisceicontatti,maapreinfinitepossibilitàperclientdichat,notificheealtroancorasenzaesserecostrettiascrivereunasolarigadicodicediback-end.

Page 147: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. Chetipodioggettorestituisceilmetodo$http?2. Inchemodoèpossibileottenereunarraydicontattieassegnarliaunmodello

con$http?3. Checosasignificailsimbolo@inunaconfigurazionediparametripredefinita?4. IndicateleduedifferenzeprincipalitrangResourceeRestAngular.5. InchemodoFirebasecreal’applicazione?

Page 148: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoInquestocapitoloabbiamotrasformatol’applicazionedaun’appfront-endche

utilizzavadatiditipohard-codeinunachesiinterfacciaconun’APIpermemorizzareerecuperareleinformazioni.AbbiamoscopertocomeèflessibileAngularesaminandoquattrodiversimetodiperconnettersiaunserver.

Iservizidibassolivellocome$httpsonoottimiinalcunicasi,maperlosviluppodiun’applicazionecompleta,abbiamovistocheèopportunoutilizzarequalcosadipiùraffinato.ModulicomengResourcemantengonolabasedicodicegestibileerispondentealprincipioDRY(Don’tRepeatYourself).

Nelprossimocapitoloapprofondiremoquestoconcettoanalizzandoduerunnerdicodice:Gruntegulp.

Page 149: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo9

Page 150: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Itaskrunner

Ilprogettohaunbell’aspetto,manonèefficiente.AbbiamoinclusodiecifileJavaScript,checomportanodiecirichiestedirete,senzaconsiderareilfogliodistile.Ciòsignificachelapaginaimpiegheràpiùtempoacaricarsi.Alterminedelcaricamento,ilbrowserdovràrecuperareognifileJavaScriptecompilarlo.

Potremmoprenderemanualmentequestifileeconcatenarliinunosolo.Tuttavialavorandoalprogettoèprobabilechecontinueremoaeffettuarealtremodifiche,esarebbeirritanteripeterecontinuamentequestoprocesso.

Itaskrunnersonounottimosistemaperautomatizzareattivitànoiose.Nondovremopiùconcatenareeminificaremanualmente,maavremoun’installazionechecontrolleràlemodificheneifileelicreeràautomaticamente.

Anchesenonliavetemaiutilizzati,probabilmenteavretesentitoparlareditaskrunnercomeGruntegulp.InquestocapitololimetteremoentrambiallaprovaperconcatenareeminificareifileJavaScriptinununicofile.

Page 151: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

InstallareNodeeNPMSiaGruntsiagulpsibasanosuNodeeilsuoNodePackageManager(NPM).Se

avetegiàinstallatoeconfiguratoNode,tralasciatequestoparagrafo.Esamineremol’installazionesuMac,mailprocessoèsimileperWindows.GliutentiLinuxdovrannocompilaredalfilesorgenteovisitarehttps://github.com/joyent/node/wiki/Installing-Node.js-via-package-managerperinstallarlotramiteungestoredipacchetti.

Andateall’indirizzohttp://nodejs.org/download/escaricatel’installerappositoperlapiattaforma.Apritelo,accettateilcontrattodilicenzaecompletatelaprocedura.

Setuttosisvolgecomeprevisto,dovrestevedercomparireunmessaggiosimile:

Nodewasinstalledat

/usr/local/bin/node

npmwasinstalledat

/usr/local/bin/npm

Verificateche/usr/local/binsitroviin$PATH.Senonsietesicurichesitrovinelvostropercorso,eseguitequestocomandodaterminale:

echo$PATH

Page 152: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Cercate/usr/local/bin.Senonlotrovate,aggiungetequantoseguea~/.bash_profileoppure~/.zshrc:

exportPATH=/usr/local/bin:$PATH

AllafinedellaproceduraNodeeNPMsarannoinstallati.Potreteaccedereaicomandinodeenpm,evisaràpossibileinstallareGruntogulpnelprogetto.

NOTA

Potrebbe essere necessario riavviare la sessione del terminale per far funzionare tutto comeprevisto.

Page 153: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

UtilizzareGruntDopoaverinstallatoNode,sfruttereteGrunt.Laconfigurazioneavvieneintrefasi:

lostrumentodarigadicomando,l’installazionelocalediGruntnelprogettoelaconfigurazionedelGruntfile.

Installarel’interfacciaarigadicomandoInstallarelacommand-lineinterface(CLI)èmoltofacilegrazieaNPM.È

sufficienteeseguirequantoseguenelterminale.Ilflag–gverificheràl’installazioneglobalediGrunt:

npminstall-ggrunt-cli

Asecondadeipermessi,potresteeseguirlocomeroot.SusistemiOSXobasatisu*nix,sitrattadieseguirloconilprefissosudo.InWindows,ènecessarioaprirelashelldicomandocomeamministratori.

Alterminedell’installazione,ilcomandogruntsaràdisponibileeverràaggiuntoalpercorsodelsistema,epotràvenireeseguitodaqualsiasidirectory.

InstallareGruntPerutilizzareGruntnelprogettoènecessarioaggiungereduefile:package.jsone

Gruntfile.js.

Ilfilepackage.jsonnonvieneutilizzatodaGrunt,madaNPM.Indicaalgestorequalipacchettiservonoalprogettoquandoeseguiamol’installer.Gruntfile.jsèciòcheconfiguraGrunt.Forniscediverseindicazionialtaskrunner,daqualifileconsiderareaqualiattivitàeseguire.

Creareunfilepackage.json

Creiamoilfilepackage.jsonaffinchéNPMsappiaqualifilerecuperare.DiseguitoilfileJSONcompletato.IlNodePackageManagerciconsentiràdicrearlofacilmenteeseguendoilcomandonpminit:

{

“name”:“ContactsMgr”,

“version”:“1.0.0”,

“description”:“AsimplecontactsmanagerinAngularJS+

Bootstrap”,

“dependencies”:{

“grunt”:“~0.4.1”,

Page 154: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

“grunt-contrib-uglify”:“~0.2.0”,

“grunt-contrib-watch”:“~0.5.3”

}

}

Comepotetenotare,sitrattadiunoggettoJSONstandardconalcuneproprietàchiaveimpostate.Ilnome,laversioneeladescrizionesonorichiesti,mautilizzatisoltantoquandodistribuiamoilprogettosottoformadiunpacchettosuNPM.Laproprietàdependenciesèilpuntoincuiavvengonoprocessiinteressanti.

Gruntsitrovaincimaallalistadelledipendenze.Glialtripacchetticheabbiamoinclusosvolgerannolapartepiùrilevantedellavoro.Ilpacchettogrunt-contrib-uglifyconcateneràeminificheràifileJSel’ultimopacchettonellalistacontrolleràifileallaricercadimodificheedeseguiràattivitàspecifiche.

NOTA

Èimportantericordarecheilnomedelpacchettonondevecontenerespaziocaratterispeciali.

CreareilfileGruntfile.js

Gruntfileèmoltoimportante.ConsideratelocomeilmanualediistruzionidiGrunt,chesenzadiessononsaprebbechecosafare.Tuttalaconfigurazioneavvieneall’internodellaseguentefunzionewrapperdiGrunt:

module.exports=function(grunt){

};

NOTA

ÈimportantecheGruntfile.jsvengasalvatonellaradicedovesivuoleeseguireGruntecheilnomedelfileiniziconlaGmaiuscola.

Lamaggiorpartedeiplug-inrichiederàl’utilizzodelmetodoinitConfigdiGrunt,edèciòcheutilizzeremoconilplug-inuglify:

module.exports=function(grunt){

grunt.initConfig({

...

});

};

All’internopossiamoconfigurareiplug-inutilizzandoilnomecomechiave.Possiamoancheottenereleinformazionidirettamentedalfilepackage.json,comeilnomedautilizzarenelleattività:

grunt.initConfig({

pkg:grunt.file.readJSON(‘package.json’)

});

Page 155: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

QuestocodicecaricheràilfileJSONeloassegneràallachiavepkg,consentendocidiaccedereaqualsiasiinformazioneimpostatainprecedenzaavvalendocidellasintassistandardperitemplate(<%=%>).

Quandoconfigureremol’attivitàuglify,imposteremodueproprietà:optionsebuild.Laproprietàoptionsconsentedidefinireelementicomeibannercheintendiamoincluderenelfilecompilato,creareunamappadeifilesorgenteoseintendiamoconcatenareperildebugging.

Laproprietàbuildèiltargetepossiamoattribuirlequalsiasinomedesideriamo.Peresempio,unapotrebbechiamarsideveun’altraproductioncondiverseopzioni.Puòaccettareleproprietàsrcedest,checiconsentonodiimpostarequalifilevengonoinclusiequaligenerati.Èanchepossibiledefinireunaltrooggettooptions,utilequandointendiamoutilizzaremolteplicitarget.Eccol’attivitàuglifyconl’hashoptions:

grunt.initConfig({

pkg:grunt.file.readJSON(‘package.json’),

uglify:{

options:{

banner:‘/*!<%=pkg.name%><%=

grunt.template.today(“yyyy-mm-dd”)%>*/\n’

}

}

});

Inquestocasoabbiamoinclusoilbannernell’oggettooptions.Siccomeilfilepackage.jsonèstatoconvertitoinunoggettoJS,èsufficienteutilizzarelasintassistandardperaccederealnome.Gruntcomprendeancheduehelperdicuipossiamoavvalerci.Vedretecheinquestocasoricaviamoladataodierna,maèanchepossibileutilizzareilmetodogrunt.template.dateperformattareuntimestampJS.Puòessereutilequandointendiamoincludereladatainunbanneroinunnomefile.

Oraimpostiamoiltarget.Laproprietàsrcpuòessereunastringaounarray.Inquestocaso,siccomeutilizziamoalcunifileJS,dovremoservircidiunarray.LaproprietàdestèilpercorsorelativoalfilechevogliamocheGruntcreiperimpostazionepredefinita,mapuòancheesseremodificatomedianteilmetodogrunt.file.setBase.Abbiamoaggiuntol’oggettobuildeimpostatoleproprietàsrcedest:

grunt.initConfig({

pkg:grunt.file.readJSON(‘package.json’),

uglify:{

options:{

banner:‘/*!<%=pkg.name%><%=

grunt.template.today(“yyyy-mm-dd”)%>*/\n’

},

build:{

src:[

‘assets/js/vendor/jquery.js’,

Page 156: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

‘assets/js/vendor/bootstrap.js’,

‘assets/js/vendor/angular.js’,

‘assets/js/vendor/angular-animate.js’,

‘assets/js/vendor/angular-resource.js’,

‘assets/js/vendor/angular-route.js’,

‘assets/js/vendor/angular-sanitize.js’,

‘assets/js/vendor/angular-strap.js’,

‘assets/js/vendor/angular-strap.tpl.js’,

‘assets/js/controller.js’

],

dest:‘assets/js/build/<%=pkg.name%>.js’

}

}

});

Abbiamoutilizzatoilnomedelpacchettocomenomefileetuttiifileminificatisonostatisostituiticonleversioninonminificate.Poichéminificheremotutto,ènecessarioutilizzareleversionidisviluppodeifileperevitareproblemidurantelacompilazione.

L’ordinedeifilenell’arraysrcèlostessoconcuisarannoinclusinelfiledidestinazione.SiccomeabbiamobisognochejQuerysiainclusoprimadiAngulareAngularprimadeimoduli,èimportanteimpostarlibene.

Ilplug-inècompilato,maGruntnonsacheintendiamoutilizzarel’attivitàuglifycheabbiamoscaricatoinprecedenzadaNPM.AquestoscopoènecessarioutilizzareilmetodoloadNpmTasks:

grunt.loadNpmTasks(‘grunt-contrib-uglify’);

Siinseriscenellafunzionemodule.exportsefainmodocheilGruntfilecompletosiacomeilseguente:

module.exports=function(grunt){

grunt.initConfig({

pkg:grunt.file.readJSON(‘package.json’),

uglify:{

options:{

banner:‘/*!<%=pkg.name%><%=

grunt.template.today(“yyyy-mm-dd”)%>*/\n’

},

build:{

src:[

‘assets/js/vendor/jquery.js’,

‘assets/js/vendor/bootstrap.js’,

‘assets/js/vendor/angular.js’,

‘assets/js/vendor/angular-animate.js’,

‘assets/js/vendor/angular-resource.js’,

‘assets/js/vendor/angular-route.js’,

‘assets/js/vendor/angular-sanitize.js’,

‘assets/js/vendor/angular-strap.js’,

‘assets/js/vendor/angular-strap.tpl.min.js’,

‘assets/js/controller.js’

],

dest:‘assets/js/build/<%=pkg.name%>.js’

}

}

});

grunt.loadNpmTasks(‘grunt-contrib-uglify’);

};

Page 157: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

EseguireGrunt

Orapossiamoeseguirel’attivitàgruntuglifychegenereràilfileContactsMgr.jscompleto.

Sesostituiteaidieciscriptilnuovofilenellaradiceindex.htmlecaricatel’applicazione,noteretechenonfunzionanullaevedreteilseguenteerroredellaconsole:

Error:[$injector:unpr]Unknownprovider:a

Comepartedelprocessodiminificazione,inomidellevariabilivengonosostituiticonleloroversioniabbreviate.SappiamocheAngularsibasamoltosulladependencyinjection,cheosservailnomedellavariabileperinserireilserviziocorrettoneicontrollerenelledirettive.

FortunatamenteAngularoffreunasoluzionerapidaefacile.Sitrattadicambiarelefunzioninellequaliinseriamoiservizi,congliarraycontenentiinomideiservizicheintendiamoinserireelafunzionecomesuoivalori.Eccocomeappareconfigdelmodulo:

.config([‘$routeProvider’,‘$locationProvider’,

function($routeProvider,$locationProvider){

...

}])

Finchélafunzioneèl’ultimanell’array,Angularesamineràlevariabilieutilizzeràilserviziocorrispondentedell’array.Gruntnonmodificheràilvaloredegliitem

Page 158: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

nell’arraypoichésitrattadistringheenondinomidivariabili;èquindiimportantechel’ordinenell’arraycorrispondaaciòchevieneinseritonellafunzione.

Èsufficienteaggiungerequestiwrapperperl’arraynelfilecontroller.jspoichéatuttelelibrerieeaimodulicheabbiamoutilizzatoègiàstatoapplicatoquestoprocesso.

Ricordatecheancheicontrollernelledirettivedevonoutilizzarelanotazionedegliarray.

Impostarewatch

SiamoriuscitiaconfigurareGruntpercompilareifileefunzionabenissimo.TuttavianonsarebbepiùunprocessoautomaticosedovessimoeseguiregruntuglifyognivoltacheintroduciamounamodificaneifileJavaScript.Gruntpuòtenered’occhiopernoiquestiaspettiedeseguireautomaticamentealcuneattivitàquandoapportiamodellemodificheaifile.

Aquestoscopoutilizziamoilpacchettogrunt-contrib-watchcheabbiamorecuperatoprimadaNPM.Laconfigurazioneèmoltosempliceerichiedesolodueproprietà:filesetasks:

watch:{

files:[

‘assets/js/*.js’

],

tasks:[‘uglify’]

},

Utilizziamol’asteriscocomecaratterejollyaffinchéGruntindividuiifile.jsnelladirectoryassets/js.Possiamocollocarequanteattivitàdesideriamonell’arraytask,everrannoeseguiteinordine.

L’esecuzionedigruntwatchnelTerminalefaràinmodocheGruntcontinuiavenireeseguitoinbackground.Nonappenaunfilevienemodificato,entrainazioneedeseguel’attivitàuglify,concatenandoeminificandoifileJavaScript.

Crearel’attivitàpredefinita

Spessoavretebisognodieseguiremoltepliciattivitàinunavoltasola.Gruntviconsentedifarloregistrandol’attività:

grunt.registerTask(‘default’,[‘uglify’]);

Ilprimoparametroèilnomedell’attività,mentreilsecondoèl’arraydelleattivitàchedesideriamoeseguire.L’utilizzodellaparolachiavedefaultcomunicaaGruntche

Page 159: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

questaèl’attivitàdaeseguirequandononnespecifichiamouna.Peresempio,potremmoeseguirel’attivitàdefaultinunodeiduemodiseguenti:

gruntdefault

grunt

Page 160: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

UtilizzaregulpGulpèabbastanzanuovoeprendelemossedaGrunt.Acausadellasuavita

relativamentebreve,nonesistonomoltiplug-indisponibili.Tuttaviac’èuglifyeilloronumeroèincontinuacrescita.IlvantaggioèchegulpmiraasemplificarelaconfigurazioneeaeseguireleattivitàpiùvelocementediGrunt:spettaavoideciderequaledeidueèpiùadattoalvostroprogetto.

ComeGrunt,gulpècostituitodadueparti:lostrumentodarigadicomandoglobaleel’installazionelocalecheincluderemonelprogetto.

InstallaregulpglobalmenteÈmoltofacileinstallaregulpglobalmentemedianteununicocomandoNPM:

npminstall-ggulp

PotrestedoverloeseguirecomeradiceutilizzandosudooattraversoilpromptdeicomandidiWindowscomeamministratori.

Alterminedell’installazione,ilcomandogulpsaràdisponibiledalterminale.

InstallareledipendenzedigulpPropriocomeconGrunt,ènecessariocreareunfilepackage.json,checonterràtutte

ledipendenzedelprogetto.Iniziamoainstallaregulp:

{

“name”:“ContactsMgr”,

“version”:“1.0.0”,

“description”:“AsimplecontactsmanagerinAngularJS+

Bootstrap”,

“dependencies”:{

“gulp”:“~3.6.0”

}

}

Possiamoaggiungeremanualmenteuglifyalfilepackage.json,oppurericorrereaNPMperquestaoperazione:

npminstall--save-devgulp-uglify

Ilflagsave-devindicaaNPMchevogliamocheloaggiungaalfilepackage.json.Inalternativapotremmoutilizzareilflag--save,masiccomegulpvieneusatosoltantoinfasedisviluppo,nonciservedurantelaproduzione.

Page 161: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Adifferenzadelplug-inuglifydiGrunt,nonconcateneràifileedovremoricorrereaunaltroplug-inperquestoscopo:

npminstall--save-devgulp-concat

ImpostaregulpfileAdifferenzadiGrunt,ilfilegulpfilenondeveiniziareconlaletteraGmaiuscola,

ancheseospitalaconfigurazioneesicollocanellaradicedelprogetto.Seilconcettoallabasedelfileèsimile,laconfigurazioneèmoltodiversa.

RicorderetecheGruntfilerichiedevaunafunzionewrapperperpoteraccedereatuttiimetodiGrunt.Congulpèunpo’differenteeognipacchettocheotterremograzieaNPMpotrebbeesserenecessarionelfile.Includetequantosegueall’iniziodelgulpfile.

vargulp=require(‘gulp’);

varuglify=require(‘gulp-uglify’);

varconcat=require(‘gulp-concat’);

varpkg=require(‘./package.json’);

Possiamoancheincludereleinformazionidelfilepackage.jsonrichiedendolonellostessomododiunpacchettoNPM.Icaratteri./all’inizio,indicanoaNodediguardarenellastessadirectorydelgulpfilequandoeseguiamogulp.

Inquestocasononesistealcunoggettodiconfigurazione,equestosemplificalecose.Tuttoavvieneall’internodelleattività.Eccol’attivitàuglifycompleta:

gulp.task(‘uglify’,function(){

gulp.src(paths.js)

.pipe(concat(‘ContactsMgr.min.js’))

.pipe(uglify())

.pipe(gulp.dest(‘assets/js/build’));

});

Ilmetodogulp.taskaccettadueparametri:ilnomedell’attivitàeunafunzioneanonimachecontienetuttociòchefaràl’attività.

Abbiamoinclusounavariabileingulp.src.Cosìlapotremoutilizzareinseguitoeoffriràmaggioreflessibilitàsenzaesserecostrettiascriverlaognivolta:

varpaths={

js:[

‘assets/js/vendor/jquery.js’,

‘assets/js/vendor/bootstrap.js’,

‘assets/js/vendor/angular.js’,

‘assets/js/vendor/angular-animate.js’,

‘assets/js/vendor/angular-resource.js’,

‘assets/js/vendor/angular-route.js’,

‘assets/js/vendor/angular-sanitize.js’,

‘assets/js/vendor/angular-strap.js’,

‘assets/js/vendor/angular-strap.tpl.min.js’,

‘assets/js/controller.js’

Page 162: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

]

};

Eccol’oggettopathsalqualefacciamoriferimento.SitrattadellostessoarraydifilecheabbiamoinclusoprimainGruntfile.

Gulputilizzaglioperatoripipeperelaborareidati.Tuttiipacchettiaiqualiabbiamofattoriferimentoall’iniziodelfilegulpfilesonofunzioni.Ilplug-inconcataccettailnomedelfilecheintendiamogenerarecomeoutput.Abbiamorecuperatoilnomedalfilepackage.jsoneaggiuntol’estensione.js.Ilplug-inuglifyoffreunnumerodiopzionichepossiamopassarecomeunhashJSperfacilitareildebugging,eilmetodogulp.destcheutilizziamociconsentediimmettereilnomedelladirectorydell’output.

Dopoaverimpostatol’attività,potremmoeseguiregulpuglify,maprimaènecessarioimpostareanchewatch.AdifferenzadiGrunt,nonènecessarioincludereunulterioreplug-inperquestoscopo,poichésipresentacomeunaltrometododigulp:

gulp.task(‘watch’,function(){

gulp.watch(paths.js,[‘uglify’]);

});

L’impostazioneèmoltosemplice.Creiamounanuovaattivitàeutilizziamoilmetodogulp.watch,attraversandol’arraydifilecheintendiamoosservareepoil’arraydiattivitàchevogliamoeseguirequandoquestifilecambiano.

Impostiamorapidamenteun’attivitàpredefinitapercompletareilfilegulpfile:

gulp.task(‘default’,[‘uglify’]);

Eccoilfilegulpfile.jscompletocheconfiguraefficacementeleattività:

vargulp=require(‘gulp’);

varuglify=require(‘gulp-uglify’);

varconcat=require(‘gulp-concat’);

varpkg=require(‘./package.json’);

varpaths={

js:[

‘assets/js/vendor/jquery.js’,

‘assets/js/vendor/bootstrap.js’,

‘assets/js/vendor/angular.js’,

‘assets/js/vendor/angular-animate.js’,

‘assets/js/vendor/angular-resource.js’,

‘assets/js/vendor/angular-route.js’,

‘assets/js/vendor/angular-sanitize.js’,

‘assets/js/vendor/angular-strap.js’,

‘assets/js/vendor/angular-strap.tpl.min.js’,

‘assets/js/controller.js’

]

};

gulp.task(‘uglify’,function(){

gulp.src(paths.js)

.pipe(concat(pkg.name+’.js’))

Page 163: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

.pipe(uglify())

.pipe(gulp.dest(‘assets/js/build’));

});

gulp.task(‘watch’,function(){

gulp.watch(paths.js,[‘uglify’]);

});

gulp.task(‘default’,[‘uglify’]);

OrapossiamoeseguiregulpuglifyogulpnelterminaleperconcatenareeminificareifileJavaScript.Aparteunsingoloutilizzo,possiamoancheeseguiregulpwatchperverificarel’esistenzadieventualimodificheedeseguireautomaticamentel’attivitàuglify.

Page 164: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiorganizzareilprogettoDopoaverimpostatoiltaskrunner,èilmomentodiriorganizzareilprogettoper

ottenereunabasedicodicepiùgestibile.Separeremoicontroller,ledirettive,ifiltrieiserviziinfiledistintiperteneretuttoinordine.

Iniziamoaelaborareunanuovastrutturadidirectorycomeillustralaseguentefigura.

Abbiamospostatotuttofuoridelladirectoryassets/jsnelladirectoryappdellaradice.Quandopasseremoallaproduzione,nonintendiamodistribuireifilesorgente,quindièunabuonaideatoglierlidalladirectoryassetsdoverimarrannoifilecompressi.

Lanuovadirectoryappèstatastrutturatainmodoleggermentediverso.Cisonotrecartellecomponents,vendoreviewseunfilemodule.js.Icomponentisonoitemcondivisi,quindinelcasodell’app,collochiamoquiledirettiveeiservizi.LacartellavendorcontienetuttiifileJSditerzepartimentrelacartellaviewstuttiiprincipalicontrollerperleviste.

Dopoavercreatolenuovedirectory,possiamoiniziareaseparareicontrollerindiversifileperincluderlinelladirectoryviews.Devonoancoraessereassociatialmoduloeaquestoscopopossiamoutilizzareladichiarazioneangular.module(‘contactsMgr’)all’iniziodelfile.

Ecco,peresempio,ilcontrollercontactCtl;nominatelocontact.jseinseritelonellacartellaviews:

angular.module(‘contactsMgr’).controller(‘contactCtl’,[‘$scope’,

‘$routeParams’,‘contacts’,‘$timeout’,function($scope,

$routeParams,contacts,$timeout){

$scope.contact=contacts.find($routeParams.id);

Page 165: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

$scope.$on(‘saved’,function(){

$timeout(function(){

$scope.contact.$update();

},0);

});

}]);

Orachetuttiicontrollersonostatiseparati,passiamoalledirettive.Lesposteremonellacartellacomponentsconlanuovadirectoryappdellaradice.Cosìcomeconicontroller,ènecessarioverificarechesianoancoraassociatealmodulo.

Copiateognidirettivainfileseparatieassegnateaessel’estensione.directive.js.Peresempio,ilgravatarsitroverànellacartellacomponentsesaràgravatar.directive.js,mentreladirettivamodificabilesaràeditable.directive.js.

Siccomeifiltrisonoanch’essicomponenticondivisi,possiamocollocarliinsiemeconledirettiveenominarliallostessomodo.Posizionateiduefiltriinfileseparati:truncate.filter.jsenewLine.filter.js.L’ultimocomponenteèilserviziocontactscheutilizziamoperconnettercialserver.Createunnuovofilecontacts.service.jsecopiatelo.

Dopoaversistematovisteecomponenti,dobbiamoverificarecheilnuovofilemodule.jscontengaciòchedovrebbe,ossiailmodulo.CopiateilcontenutodelfilecontactsMgr.jsdalladirectoryassets/jsnelfilemodule.js.Dopoaverspostatotuttiifile,cancellateilcontenutodelladirectoryjs.Quiaggiungeremoinseguitounfileinteramenteminificato.

DobbiamoconfigurareGrunt/gulpaffinchéosservilenuovedirectoryegeneril’ouputnelladirectoryjsall’internodellacartellaassets.IpercorsiaggiornatinelGruntfileoifilegulpfiledovrebberoessereiseguenti:

‘app/vendor/jquery.js’,

‘app/vendor/bootstrap.js’,

‘app/vendor/angular.js’,

‘app/vendor/angular-animate.js’,

‘app/vendor/angular-resource.js’,

‘app/vendor/angular-route.js’,

‘app/vendor/angular-sanitize.js’,

‘app/vendor/angular-strap.js’,

‘app/vendor/angular-strap.tpl.js’,

‘app/module.js’,

‘app/components/**/*.js’,

‘app/views/**/*.js’

Angularsioccupadellagestionedelledipendenze,maciòchecontaèl’ordine.Carichiamojquery.jsprimadiangular.jsaffinchéAngularsappiachevogliamoutilizzarequestoenoniljqLiteincluso.

TuttiimodulivendornecessitanodiAngularchedeveessereinclusoprimadiessi.Inoltreicomponentielevisterichiedonoilcaricamentodelmodulo,altrimentinon

Page 166: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

sapràachecosaassociarsi.

Primadieseguireiltaskrunnerdesiderato,modificateladestinazionedaassets/js/buildadassets/js.

Eseguiteiltaskrunnerpercompilarel’applicazionecheaveteriorganizzato.Infinemodificateilfilealqualefateriferimentoinindex.htmloracheladestinazioneècambiata:

<scripttype=”text/javascript”

src=”assets/js/ContactsMgr.js”></script>

Apriteilbrowserpercontrollarechetuttoappaiacomeprevisto.Setuttosicomportasecondoipiani,ilgestoredeicontattidovrebbefunzionareallaperfezione.

NOTA

Senonfunzionacomedovrebbe,controllatelaconsole.Probabilmenteavetetralasciatoqualcosaol’aveteinclusonell’ordinesbagliato.

Page 167: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. SuqualeambientesibasanosiaGruntsiagulp?2. Perchéserveunfilepackage.json?3. Qualeplug-invieneutilizzatoperminificareifile?4. ChecosaènecessariofareaifileAngularprimadiminificarli?

Page 168: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoInquestocapitoloabbiamoesaminatoduestrumentimoltoefficaciesimili.Ci

hannoconsentitononsolodiridurrenotevolmenteilnumerodellerichiesteHTTP,maanchediriorganizzarecompletamentel’app.

SiaGruntsiagulpottengonolostessorisultato,edèunaquestionestrettamentepersonalescegliereiltaskrunnerdautilizzare.Riteniamogulppiùrapidoefaciledaconfigurare,maindubbiamenteGruntvantaunnumeromaggiorediplug-inedèunostrumentodisponibiledapiùtempoepiùcollaudato.

NelcapitoloseguentevedremocomeutilizzarequestiduetaskrunnerperprendereifileLesscheutilizzaBootstrapecompilarliinunaversionepersonalizzata.

Page 169: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo10

Page 170: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

PersonalizzareBootstrap

Finoral’applicazioneèpiuttostoconvenzionale.SiamoriuscitiasfruttareappienoBootstrap,mal’aspettopredefinitononhanulladinuovo.BootstrapèprogettatoperesserepersonalizzatoeutilizzaLessoilpreprocessoreCSSSASSpervelocizzareesemplificarequestaoperazione.

NelcorsodiquestocapitolostudieremocomeèpossibilecompilareilsorgenteLessdiBootstrapprimadipersonalizzarel’aspettoaffinchél’applicazionesiaveramenteunanostracreazione.Affronteremoiseguentiargomenti.

IfondamentidiLess.PersonalizzareBootstrap.CompilareLessconGruntogulp.ImpostareLiveReload.ItemidiBootstrap.

Page 171: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

CompilareLessconGruntogulpPrimadiiniziareapersonalizzarel’app,èunabuonaideascoprirecome

trasformarenumerosifileLessinununicofogliodistile.AbbiamogiàvistocomeimpostareGruntegulpperconcatenareeminificareifileJavaScript;orautilizzeremoquestistessitaskrunnerpercompilareLess.

ScaricareilsorgenteInnanzituttoprocuriamocil’ultimaversionediBootstrapeinseriamoifileLessnel

progetto.Visitiamohttp://getbootstrap.com/efacciamoclicsuDownloadBootstrap.Comparirannotreopzioni:Bootstrap,SourcecodeeSass.Scegliamol’opzioneSourcecodeperchéincludeifileLesscheèpossibilepersonalizzareecompilare.

Comepotetenotare,ilsorgentediBootstrapèdiecivoltepiùgrandedellaversioneminificata.Pertenereinordineiltutto,copiateladirectorylessdalmaterialecheavetescaricatonellacartellaassetsall’internodelprogetto.Ladirectorycontienei40filelesschecostituisconoglistilidiBootstrap.

CompilareconGruntComeabbiamovisto,Gruntèunefficientetaskrunner.Possiamoavvalercidella

minificazionedeiJavaScriptperautomatizzarelacompilazionediLessconCSS.AquestoscopoGruntricorreaunplug-incheèpossibilerecuperaredaNPM.Includiamolonelpackage.jsondelprogettoedeseguiamonpminstalldalterminale.TuttaviaèmoltopiùsempliceeseguireununicocomandoelasciarecheNPMaggiungaladipendenzanelfilepackage.jsondelprogetto,nelmodoseguente:

npminstallgrunt-contrib-less--save-dev

Dopoaverinstallatoilplug-in,possiamoconfigurarlonelfileGrunt.Tuttoavvienenuovamentenell’oggettoconfig.Imposteremoduetarget:unoperlosviluppoeunaltroperlaproduzione.Cosìpotremodefinireleopzioniperogniscenario.Peresempio,perlaproduzionepotremmovolerminificareilCSS,maquestaoperazionenonèsempreauspicabileinfasedisviluppo.

Seguelaconfigurazionecompletaperl’attivitàless:

less:{

dev:{

files:{

‘assets/css/bootstrap.css’:

‘assets/less/bootstrap.less’

Page 172: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

}

},

production:{

options:{

cleancss:true

},

files:{

‘assets/css/bootstrap.css’:

‘assets/less/bootstrap.less’

}

}

}

Neltargetdevnonabbiamoimpostatoopzioni,maproductionpresentailflagcleancssimpostatosutrueperridurreledimensionideifileminificandol’output.L’oggettofilesusalasintassiabbreviataperleproprietàsrcedestcheabbiamoesaminatoconfigurandoGrunteutilizzandouglifyperifileJavaScript.

NondimenticatedicaricareanchequestomodulodaNPM,altrimentiGruntnonriusciràadaccedereall’attivitàless.InseritelonelwrapperdiGrunt:

grunt.loadNpmTasks(‘grunt-contrib-less’);

Orasaràpossibilecompilareglistili.Possiamoeseguirequantoseguenelterminalepersvolgerel’attività:

gruntless

Questoperòproduceuneffettononvoluto,poichél’attivitàvieneeseguitasuentrambiitargetunodopol’altro.

Possiamolimitarlaaunsolotargetspecificandoilnomedeltargetdopoiduepunti:

Page 173: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

gruntless:dev

ImpostareWatcheLiveReload

Ovviamenteilprincipioallabasedell’utilizzodiuntaskrunnercomeGruntogulpèautomatizzaretuttiquestiprocessi.Èpossibileutilizzareilplug-inwatchcomeabbiamofattonelCapitolo9pereseguireun’attivitàquandounfilecambia.Questocipermetteanchediutilizzarelivereloadsullapaginaconl’ausiliodiunplug-indelbrowser.

Laconfigurazioneèfacilepoichéabbiamogiàinstallatoilplug-in.Eccol’impostazionecorrenteperl’attivitàwatch:

watch:{

files:[

‘assets/js/*.js’

],

tasks:[‘uglify’]

}

Potremmoaggiungereladirectorylessall’arrayfilesel’attivitàlessall’arraytasks.Inquestomodoentrambeleattivitàverrannoeseguitequandocambieràunfile.jso.less;tuttavianonèquestoilnostroobiettivo.Separandoleinduetarget,avremomaggiorecontrollosulleattivitàchesarannoeseguite:

watch:{

js:{

files:[

‘assets/js/*.js’

],

tasks:[‘uglify’]

},

less:{

files:[

‘assets/less/*.less’

],

tasks:[‘less:dev’]

}

}

Perquantoriguardalaconfigurazione,noncambianulla.Abbiamosoloseparatoiduetipidifilepereseguirerispettivamenteuglifyeleattivitàless:dev.

Ilplug-inhaancheunaltroassonellamanica.Fungedaserverperilplug-inLiveReloadpermolteplicibrowser.Perutilizzarloconl’app,ènecessarioincludereunulterioretagscriptnellapagina:

<scriptsrc=”http://localhost:35729/livereload.js”></script>

Inalternativaesisteun’estensioneperChrome,FirefoxeSafari,chepuòesserescaricatadahttp://livereload.com/.Dopoaverlainstallata,nelbrowsersaràpossibileeffettuareilpingdelserverLiveReloadognivoltachesiverificanodellemodifiche.

Page 174: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ImpostareGruntpereseguireilpingdelnuovoplug-indelbrowserèmoltofacile;èsufficienteimpostarelaproprietàlivereloadsutrueinunoggettooptions.Aggiungiamolarapidamentealtargetless:

less:{

files:[

‘assets/less/*.less’

],

tasks:[‘less:dev’],

options:{

livereload:true

}

}

SeapriteilbrowsereattivateLiveReload,vedretechelapaginasiricaricaogniqualvoltasieffettuanodellemodificheaifileless.Ottimo,manonsarebbepreferibilesesiaggiornassesoloilCSSenonl’interapagina?Secambiaunfile,Gruntricaricheràl’interapagina.Perottenerequestorisultato,èpossibileaggiungereunsecondotargetallaconfigurazionecheverificalapresenzadimodifichenelfilebootstrap.css:

css:{

files:[

‘assets/css/bootstrap.css’

],

options:{

livereload:true

}

}

SedisattiviamoLiveReloadneltargetless,ilbrowserriceveràunnuovofileCSSenonricaricheràpiùlapagina.

CompilarecongulpOraesaminiamol’altrotaskrunner:gulp.PropriocomeGrunt,gulputilizzaun

altroplug-inperconsentirelacompilazionediLess.Sarànecessarioincludereunsecondoplug-inperLiveReload,poichénonègiàinclusoinGrunt.

Installiamoeconfiguriamoilplug-inless.Possiamofarlodarigadicomandoeseguendo:

npminstallgulp-less--save-dev

Cosìloinstalleremonelprogettoeloincluderemoanchenelfilepackage.jsonperunusofuturo.Perutilizzarlonelgulpfile,ricorreremoalmetodorequirediNodeperincludereilpacchetto.Inseriteloall’iniziodelgulpfile:

varless=require(‘gulp-less’);

Page 175: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Creiamounanuovaattivitàchiamatalesspergestiretuttalacompilazione,servendocidelplug-incheabbiamoappenaincluso:

gulp.task(‘less’,function(){

});

ComeabbiamofattoconJavaScript,utilizzeremoilmetodosrcdigulpcondueoperatoripipeperottenereilrisultatodesiderato.Consideriamol’attivitàcompletaedesaminiamolaneldettaglio:

gulp.task(‘less’,function(){

gulp.src(‘assets/less/bootstrap.less’)

.pipe(less({

filename:‘bootstrap.css’

}))

.pipe(gulp.dest(‘assets/css’));

});

Inquestocasoabbiamoinclusounsolofile;glialtrisonoinclusitramite@import.Ilplug-inLessaccettaqualsiasiparametroaccettatodalcompilatoreLessufficiale.Inquestaconfigurazioneimpostiamounnomefile,maperimpostazionepredefinitautilizzeràilnomefiledelsorgente.

Infineciserviremodelmetodogulp.destperesportareilfilecompilatonelladirectoryCSS.Questipiperappresentanoipassichel’attivitàesegueinordineedèpossibileaggiungernefacilmentealtrioriordinarliinfuturosefossenecessario.

OraGulpèconfiguratoperutilizzareilplug-inLessedèprontopercompilareglistilimedianteilcomandolessdigulp.

ImpostareWatcheLiveReload

Page 176: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Ovviamentemancheremmol’obiettivodell’automazionesedovessimoeseguirequestocomandomanualmente.Abbiamogiàscopertochewatchèintegratoingulp;includerelessnell’attualeconfigurazioneconsistenell’aggiungeresoloun’altrarigadicodice:

gulp.task(‘watch’,function(){

gulp.watch(paths.js,[‘uglify’]);

gulp.watch(paths.less,[‘less’])

});

Facciamoriferimentoaunanuovaproprietàall’internodell’oggettopaths.Aggiungiamolaaffinchégulpsappiadovesitrovanoifilechestiamoconsiderando:

less:‘assets/less/*.less’

UtilizziamoilcarattereasteriscoperfareriferimentoaognisingolofileLess;cosìgulppuòvedereesattamentequandoqualcosaècambiato.

ImpostareLiveReloadrichiedepiùlavoroperchécomportal’installazionediunaltroplug-in.RecuperiamolodaNPMconilseguentecomando:

npminstall--save-devgulp-livereload

Dopoaverloinstallato,fateriferimentoalplug-inall’iniziodelgulpfile:

varlivereload=require(‘gulp-livereload’);

LafunzionerestituitaèilservizioLiveReloadelopossiamoutilizzareperindicareall’estensionedelbrowserqualifilesonocambiati.Perconfigurarlocorrettamenteènecessariosvolgeredueoperazioninell’attivitàwatch.InnanzituttofacciamoriferimentoalserverLiveReloadacuipossiamopassareifilechangedauneventoattivatodalmetodogulp.watch:

gulp.task(‘watch’,function(){

varserver=livereload();

gulp.watch(paths.js,[‘uglify’]);

gulp.watch(paths.less,[‘less’]).on(‘change’,function(file){

server.changed(file.path);

});

});

Abbiamoassegnatolafunzionelivereload()allavariabileservereaggiuntounlistenerperl’eventochangealwatcher.Dopochel’eventoverificaunoggettofile,èpossibilepassareilpercorsodelfilealserver.

ComeconGrunt,ènecessarioaffrontarelaquestionedelricaricamentodelbrowserquandocambiaunfilenonCSS.Possiamorisolverlaaggiungendounterzowatcher.Diseguitol’attivitàcompletataconquestaintegrazione:

Page 177: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

gulp.task(‘watch’,function(){

varserver=livereload();

gulp.watch(paths.js,[‘uglify’]);

gulp.watch(paths.less,[‘less’]);

gulp.watch(‘assets/css/bootstrap.css’).on(‘change’,

function(file){

server.changed(file.path);

});

});

NOTA

Non dimenticate di sostituire nel file index.html, il file CSS minificato con quello appenacompilato.

Page 178: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

LessPercomprenderemegliociòcheoffreLess,introduciamoneifondamentiper

capirnelanaturaelasintassiallabasedelpreprocessore.

Osserveremoquattrotralesueprincipalicaratteristiche:importazione,mixin,regoleannidateevariabili.Unalistacompletaèdisponibilesulsitohttp://lesscss.org/features/.

IlvantaggiodiLessèchesenonvoleteutilizzarenessunasintassiofunzionenuova,nonsaretecostrettiafarlo.QualsiasiCSSvalidoèancheLessvalido.

ImportazionedifileComeperCSS,inLesspossiamoincludereunfileall’internodiunaltro.Inoltre

seguelastessasintassidiCSS:

@import“file.less”

Tuttavia,adifferenzadiCSS,cheeffettuaun’ulteriorerichiestaHTTPperilfilealqualesifariferimento,Lessuniràilfilequandoècompilato.Seapritebootstrap.less,vedretetuttiifileLessnecessariaiqualivienefattoriferimento.

NOTA

ConleversionipiùrecentidiLesspotetetralasciare.lessquandoincludeteifileecompilate.

VariabiliBootstraputilizzalevariabiliLessperconsentircidimodificareicolorieifont

deglielementivariable.Possiamocambiarlirapidamenteaprendoilfilevariables.less.Unavariabilevienedefinitadalsimbolo@seguitodalsuonome,peresempio:

@brand-primary:#428bca;

Sitrattadisempliciriferimentidautilizzareneglistili.Possiamochiamarelavariabilefacendoviriferimentoall’internodelleproprietà:

color:@brand-primary;

Durantelacompilazione,Lesssostituiràaquestiriferimentiilcoloredefinitoinprecedenza.Bootstraputilizzaquestevariabiliintuttiisuoielementi;pertantoèpossibilemodificarerapidamentecoloriefontinquestofile.

Page 179: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RegoleannidateForseunodeipatternpiùosticidiCSSèl’assegnazionedeglistiliaglielementi

figlio.Invecediannidarel’elementofiglioall’internodell’elementogenitore,ènecessarioscrivereunaregolaseparata.Eccounesempio:

div{

background:#ccc;

}

diva{

color:#000;

}

diva:hover{

color:#fff;

}

ConLess,possiamoannidarequesteregoleperteneretuttopiùinordine:

div{

background:#ccc;

a{

color:#000;

&:hover{

color:#fff;

}

}

}

Comepotetenotarenell’esempioprecedente,èpossibileannidarepseudoclassiutilizzandolasintassi&.Sitrattadiunriferimentoallaregolariguardanteilgenitore.Nellostessomodoèpossibileanchedefinireunaclassesecondaria.Peresempio,eccounpulsanteconduestilipericoloriarancioneeblu:

button{

color:#fff;

&.orange{

background:orange;

}

&.blue{

background:blue;

}

}

MixinUnmixinconsentediincludereglistilidaun’altraregola.Accettaancheargomenti

cheèpossibilepassareperotteneremaggioreflessibilità.Vediamounesempio:

.border-radius(@radius:5px){

border-radius:@radius;

}

Possiamoutilizzarequestomixinneglistili:

button{

.border-radius;

Page 180: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

}

Ilvalorepredefinitocheabbiamoimpostatoverràutilizzatoautomaticamente.Tuttaviapossiamoscavalcarlofacilmenteracchiudendolotraparentesi:

button{

.border-radius(15px);

}

Page 181: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

PersonalizzareglistilidiBootstrapPoichéutilizziamoilsorgentediBootstrap,possiamoanalizzareepersonalizzare

qualsiasifile.LessestendeCSSecioffrenuovefunzionisfruttatedaBootstrap.

CaratteritipograficiBootstraputilizzaHelvetica,forseilfontpiùpopolarealmondo.Perdare

all’applicazioneunpo’dicarattere,vediamocomeèpossibilesostituireaquestounaltrofontprovenientedallalibreriaGoogleFonts,visitabileall’indirizzohttps://www.google.com/fonts.Dateun’occhiataetrovatequellochepiùvipiace.PerorautilizzeremoRoboto,uncaratterebastone.

AggiungeteilfontallaraccoltaeselezionateglistiliLight,NormaleBold,comenellafigurariportataallapaginasuccessiva.

Copiatelariga@importeincludetelaall’iniziodelfilebootstrap.less,cosìavreteaccessoallafamigliadifontRobotoneivostristili.CercateTypographynelfilevariables.less.Lasezioneiniziaall’incircaariga38.Modificheremolavariabile@font-family-sans-serifcheBootstraputilizzaperimpostazionepredefinitacomebase:

@font-family-sans-serif:Roboto,“HelveticaNeue”,Helvetica,

Arial,sans-serif;

Potremmoanchecambiareladimensionedelcarattere,maperoranoneffettuiamoalcunamodifica;cisembratuttograziosoedequilibrato.

Page 182: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

navbarCercatenavbarinvariables.less;lasezionedovrebbeiniziareall’incircaariga324.

Effettueremoalcunemodificheperrenderlomenoanonimo.Iniziamoacambiareilgrigioscialboinuncolorepiùstimolante,comeunbelblumetallizzato:

@navbar-default-bg:#667591;

Cambieremoancheilcoloredeltestoedeilinkaffinchésiintoninoconilcolorepiùscurodellosfondo:

@navbar-default-color:#fff;

@navbar-default-link-color:#fff;

@navbar-default-link-hover-color:#ccc;

@navbar-default-link-active-color:#fff;

Perquantoriguardalabarradinavigazionemobile,ènecessariomodificareancheilcoloredelpulsanteinterruttore:

@navbar-default-toggle-hover-bg:darken(@navbar-default-

bg,15%);

@navbar-default-toggle-icon-bar-bg:#fff;

@navbar-default-toggle-border-color:#fff;

Lessincludediversefunzionihelpercheèpossibileutilizzarepermodificareicolori,tracuisaturate,desaturateefade.LeduefunzionidiBootstrappiùutilizzatesonodarkenelighten.Schiarisconooscurisconopercentualmenteuncolore;sono

Page 183: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

idealiperglistatihover.Inquestocasoabbiamooptatoperlavariabiledarkenel’abbiamopassataperlosfondodellabarradinavigazione.

Infinemodifichiamol’altezzaedeliminiamol’arrotondamentodegliangoliperottenereunaspettopiùordinato:

@navbar-height:60px;

@navbar-border-radius:0;

FormIformdiBootstrapsonoforseglielementipiùriconoscibili.Effettuiamoalcune

modificheperrenderlileggermentediversi.Modificheremovariables.lesseunpaiodialtrifile.Innanzituttoinvariables.lesseliminiamol’arrotondamentodegliangolidagliinput:

@input-border-radius:0;

Possiamoanchemodificareilcoloredelbordoel’ombradelfocus:

@input-border-focus:#667591;

Forsel’ombraèunpo’eccessiva,mapossiamoeliminarlafacilmentemodificandounmixindiBootstrap.Inpassatotuttiimixindelframeworkeranocontenutinell’unicofile:mixins.less,maquestaimpostazioneèrecentementecambiataeimixinsonostatisuddivisiinfileseparati.

Nelladirectorymixins,apriteforms.lessecercate.form-control-focus.Èilmixincheassegnaglistilialfocusperglielementidelform;poteteosservarlonellerighedicodiceseguenti:

.form-control-focus(@color:@input-border-focus){

@color-rgba:rgba(red(@color),green(@color),blue(@color),.6);

&:focus{

border-color:@color;

outline:0;

.box-shadow(~”inset01px1pxrgba(0,0,0,.075),008px

@{color-rgba}”);

}

}

Ilmixinmodificailcoloredelbordo,eliminailcontornopredefinitodelbrowsereaggiungeilboxconombra.Perilmomentotrasformiamoquest’ultimoinuncommento:

//.box-shadow(~”inset01px1pxrgba(0,0,0,.075),008px@{color-

rgba}”);

Page 184: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Lessciconsentediutilizzareicommenti//neifoglidistile,chenonsarannoriprodottinell’output.Seinvecericorriamoaicommenti(/**/)CSSstandard,sirifletterannonell’output.

NellavistaAddContactutilizzeremoancheunwell,cheavràunaspettostranovistocheicampidiinputdell’utenteorasonoprividiangoliarrotondati.Potremmorimuoverel’arrotondamentodatuttiglielementiimpostandosu0lavariabile@border-radius-base,maperoraapriamoilfilewells.less.Nellaclassewellbase,impostiamosu0border-radiuspereliminaregliangoliarrotondati.

PulsantiBootstrapincludemolticoloriedimensioniperipulsanti.Possiamoeffettuarele

modifichenelfilevariables.TroveretelasezionecercandoButtons;dovrebbeessereall’incircaallariga140.Bootstraputilizzaglistessicoloripermoltisuoicomponenti;lasezioneriguardanteicoloriiniziaintornoallariga6.

@brand-primary:#428bca;

@brand-success:#5cb85c;

@brand-info:#5bc0de;

@brand-warning:#f0ad4e;

@brand-danger:#d9534f;

Modifichiamobrand-primaryaffinchésiintoniallosfondodellabarradinavigazione:

@brand-primary:#667591;

Bootstraputilizzalafunzionedarkenperapplicareilcoloredelbordodelpulsanteeicoloridellostatohover.

Èpossibilepersonalizzareogniaspettodeglistili,maperilmomentononcambieremonulla.IlContactsManagerapparemenoanonimoesciattograzieainuovicoloriecaratteripiùvivaci.Alterminedellapersonalizzazione,l’applicazionedovrebbeavereilseguenteaspetto.

Page 185: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap
Page 186: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ItemidiBootstrapUncambiamentorilevantediBootstrap3èstatal’eliminazionedituttiglistili

visivi.InfattiBootstrapintendeessereunframeworksucuisviluppareenonsemplicementedautilizzareconl’aspettopredefinito.

Tuttaviaglistiliesistonoancora:sonostatispostatiinunfileseparato,inclusonelsorgente.Ilfiletheme.lessreintroducelesfumaturepresentiinBootstrap2;èsufficienteimportarlonelfileLessprincipale.

Apritebootstrap.lesseaggiungetequantosegueallafinedelfileperincludereiltema:

@import“theme.less”;

Pervedereunesempiorelativoall’utilizzodeltemadiBootstrap,dateun’occhiataagetbootstrap.com/examples/theme.

Page 187: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

DovetrovarealtritemidiBootstrapEsistonoalcunisitiwebchepropongonotemidiBootstrap.Offronounsistema

rapidoeveloceperaggiungereunpo’dicarattereall’aspettostandarddelframework.Consultateisitiseguentisedesideratesperimentareunodiquestitemi:

http://www.blacktie.co/

https://wrapbootstrap.com/

http://startbootstrap.com/

http://bootswatch.com/

Page 188: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. QualisonoalcunedellecaratteristicheprincipalicheaggiungeLess?2. Inchemodoèpossibilefareriferimentoaunapseudoclasseinunaregola

annidata?3. Comeèpossibilemodificareilfont?4. Acosaserveilfiletheme.less?

Page 189: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoNelCapitolo9abbiamoesaminatoitaskrunnerperconcatenareeminificareifile

JavaScriptinununicofile.InquestocapitoloabbiamoosservatocomeèpossibileestenderlialsorgenteLessdiBootstrapecompilarlonelCSS.

Ciòconsentedipersonalizzarel’aspettodiBootstraputilizzandol’estensionediLessnelCSS:regoleannidate,variabiliemixin.L’applicazionehaacquisitouncertocarattereeabbiamoanchevistocomeèpossibilereintrodurreunpo’dellostilevisivoprovenientedaBootstrap2.

NelprossimocapitolodescriveremolavalidazioneinAngularJSelasuaintegrazionenell’app.

Page 190: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo11

Page 191: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Validazione

Tuttofunzionabeneehaunbell’aspetto,maalmomentononesistealcuntipodivalidazioneperiformoglierrorichepotrebberoessererinviatidalserver.InquestocapitoloesamineremocomeoperalavalidazioneinAngularJSecomeèpossibilecombinarlaconglistilidiBootstrapperfornireunfeedbackall’utente.

Osserveremoinoltrecomeèpossibileespandereleregoleintegratecreandounvalidatorpersonalizzatosullabasedeiconcetticheabbiamoappresoneicapitoliprecedenti.

Page 192: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ValidazionedeiformUnadellecaratteristichenascostediAngularJSèlavalidazionenativa.Sono

disponibiliunavalidazionedibasedeitipidiinputHTML5piùcomuni,oltreadirettivepersonalizzatecomerequired,patterneminlength,solopercitarnealcune.Vedremocomeaggiungerleall’applicazioneedestenderelavalidazioneintegrataconunvalidatorpersonalizzato.

PerutilizzarelavalidazionediAngularJS,ènecessarioaggiungerequalcosaaltagdiaperturaform:

<formname=”addForm”novalidateclass=”form-horizontal”ng-

submit=”submit()”>

Larigadicodiceprecedentecontieneiltagformpresentenelpartialadd.html.Abbiamoaggiuntonameoltreaunattributonovalidate.L’attributonameassegnaunoggettoalloscopecorrente;pertantopossiamoaccedervidallavistaedalcontroller.L’attributonovalidatedisattivalavalidazionenativadelbrowser.L’abbiamofattoperchélagestiremonoieintendiamoevitarechel’impostazionepredefinitarappresentiunostacoloogeneririsultatinonvoluti.

Angularvalideràautomaticamentel’inputdell’indirizzoe-mail,efaràlostessosecambiamoilcampodelsitowebdatestoaURL.Possiamoaggiungererapidamentel’attributonecessarioaqualsiasiinputcheconsideriamoobbligatorio:

<inputtype=”text”id=”name”class=”form-control”ng-

model=”contact.name”required>

Inalternativapossiamoutilizzareng-required.Imposteràsutruel’attributorichiestodelbrowserseanchel’espressionediAngularJSètrue.Peresempio,almomentodelpagamento,potrestevoleraggiungereunacaselladicontrolloperpermettereall’utentedidigitareunindirizzodiversoperlaspedizioneelafatturazione.Neicasiincuilacasellaèselezionata,èpossibileimpostareicampisurequirednelmodoseguente:

<label><inputtype=”checkbox”ng-model=”shippingAddress”>Sendthisto

anotheraddress</label>

<divng-show=”shippingAddress”>

<inputtype=”text”ng-required=”shippingAddress”>

</div>

Siccomenonabbiamobisognodinessunacondizionenell’applicazione,manteniamol’attributorequiredpredefinito.Aggiungiamolorapidamentealnome,alnumeroditelefonoeall’indirizzoe-mailpoichésonoquestiicampidelcontattorichiestipiùfrequentemente.

Page 193: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Oraènecessarioimpedirealformdiinviareidatiquandononècompletamentevalidato.Possiamofarloall’internodelcontrolleroppuredisattivandoilpulsantesubmit.

Aggiungendounnomealform,AngularJShacreatounnuovomodello,checioffrel’accessodirettoaessoall’internodellavista.Èleggermentediversodaquellochecreeremmodisolitoperchéracchiudemolteproprietàperverificarelavaliditànonsolodelform,maanchedieventualielementispecificidanoiindicati.Vediamorapidamentecomedisattivareilpulsantesubmit:

<inputtype=”submit”class=”btnbtn-primary”value=”AddContact”

ng-disabled=”addForm.$invalid”>

Possiamoutilizzareilnuovomodelloinunadirettiva.Inquestocasositrattading-disabledecomunichiamoadAngularJSdidisattivareilpulsanteseilformnonèvalido.Inalternativaavremmopotutoverificarelapresenzadierrori:

<inputtype=”submit”class=”btnbtn-primary”value=”AddContact”

ng-disabled=”addForm.$error.required||addForm.$error.email”>

Laproprietà$errordelmodelloèunhashconidiversitipidierrorigeneratidalform.Possonoessereerroridivalidazionedegliindirizzie-mail,dicorrispondenzadeipatternodicampimancanti.Ovviamentelaverificadiognitipocomportamaggioripossibilitàdisbagliareerichiedemoltopiùcodice.Tuttaviaèpiùprolissoequestotalvoltafavoriscelachiarezza.

Inoltreabbiamoaccessoa$dirtyea$pristine.Questidueflagriconosconosel’utentehadigitatoqualcosanelformepossonoessereutilizzatipervarieoperazioni,tracuiaggiungeredelleclassi.

Poichéquestoèsemplicementeunmodello,potremmoancheverificareseilformèvalidodall’internodellafunzionesubmitinaddCtl:

$scope.submit=function(){

if(!$scope.addForm.$valid){

returnwindow.alert(‘Error!’);

}

$scope.contact.$save();

$scope.contact=contacts.create();

alert.show();

};

Secancelliamol’attributong-disabledefacciamoclicsulpulsante,vedremocomparireunafinestradiavvisodelbrowser.Èunottimorisultato,mapotremmoimpostarloancoramegliofacendolosembrarepartedell’applicazione.AbbiamogiàdefinitounmessaggiodiavvisodiBootstrap;aggiungiamolorapidamentepericasiincuisiverifichiunerroredivalidazione.

Page 194: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Sostituiamolavariabilealertall’iniziodelfileadd.jsconunnuovooggettocontenentelefinestrediavvisoconmessaggidisuccessoedierrore:

varalerts={

success:$alert({

title:‘Success!’,

content:‘Thecontactwasaddedsuccessfully.’,

type:‘success’,

container:‘#alertContainer’,

show:false

}),

error:$alert({

title:‘Error!’,

content:‘Therearesomevalidationerrors.’,

type:‘danger’,

container:‘#alertContainer’,

show:false

})

}

Orapossiamosostituirelavecchiachiamataalertelafinestradiavvisodelbrowsernelmetodosubmitdelcontroller:

$scope.submit=function(){

if(!$scope.addForm.$valid){

returnalerts.error.show();

}

$scope.contact.$save();

$scope.contact=contacts.create();

alerts.success.show();

};

Sericaricatel’applicazioneefateclicsulpulsantesubmit,vedretecomparireunmessaggiodiavvisodiBootstrapcheviinformadellapresenzadialcunierroridivalidazione.

Page 195: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Sarebbemoltoutilesaperediqualierrorisitratta.FortunatamenteAngularJSconsentediscoprirequalimodelligeneranoerroriedefinirediconseguenzaerroriostili.

Possiamoaccedereaogniinputdelform,ancheseènecessariospecificareunnomeperciascunoalfinediriuscireavalidarlo.Peresempio,sepossiamoaggiungereunnomeperiltelefononelcamporiservatoalnumerotelefonico,possiamovalidareilcampoaccedendoaessotramiteilform:

addForm.phone.$valid

Èpossibileutilizzareladirettivang-classneigruppidiformperverificarelavaliditàdell’inputeaggiungerelaclassehas-errornelcasoincuinonfossevalido:

<divclass=”form-group”ng-class=”{‘has-error’:

!addForm.phone.$valid}”>

NOTA

AngularJS aggiunge proprie classi agli elementi del form basate sulla validità, ma poichéintendiamoutilizzarelaclassehas-errordiBootstrap,abbiamooptatoperng-class.

Purtroppoquestocodiceaggiungerà,perimpostazionepredefinita,laclasseerror,eprobabilmentenonèquestoilnostroobiettivo.

Page 196: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Lasoluzioneconsistenell’impostareunsecondomodellosutruenelcasoincuiilformnonsiavalidoquandoloinviamo.

$scope.submit=function(){

$scope.formErrors=false;

if(!$scope.addForm.$valid){

$scope.formErrors=true;

returnalerts.error.show();

}

$scope.contact.$save();

$scope.contact=contacts.create();

alerts.success.show();

};

Abbiamoimpostato,all’inizio,formErrorssufalsepereliminareleclassierrornelcasoincuiilformsiavalidatocorrettamente.Possiamomodificareladirettivang-classpervederesialevalidazionisiailnuovomodello:

<divclass=”form-group”ng-class=”{‘has-error’:formErrors&&

!addForm.phone.$valid}”>

SeentrambigliinputnonsonovalidieilmodelloformErrorsèimpostatosutrue,verràaggiuntalaclasse.Aggiungiamoladirettivang-classatuttiigruppidiforminattesadivalidazione.Nondimenticatedicambiareilmodelloalqualefateriferimentoinquellocheaveteinseritocomeattributoname.

ValidazionedeipatternAbbiamoimpostatounavalidazionedibasema,comesappiamo,Angularoffre

altredirettiveperrenderlapiùrigorosa.Peresempio,orapossiamodigitaretuttociò

Page 197: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

chedesideriamonelcampo,esaràaggiuntotutto.Maquestanonèunasoluzioneidealepoichéilnostroscopoèottenereunnumeroditelefonoperognicontatto.

Ladirettivang-patternconsentedidefinireunpatternREGEX(espressioneregolare)concuiconfrontarel’input.Perilnumeroditelefonoaccetteremolecifre,maancheilsegnopiùperinumeriinternazionalieleparentesiperinumeriopzionaliequellistatunitensi.Consentiremoancheglispazielelineettepersuddividereinumeri.

Aggiungiamoladirettivang-patternall’inputriguardanteilnumerotelefonicoelimitiamoloperoraainumeriinteri:

<inputtype=”tel”name=”phone”id=”phone”class=”form-control”ng-

model=”contact.phone”required=”true”ng-pattern=”/^[0-9]/”>

Quandodigiteremodeltestonelcampoeinvieremoilform,vedremocheAngularJSgenereràunerroredivalidazione.

Soloquandodigiteremounnumero,ilformpotràessereinviato.Dobbiamoancoraconsentireicaratteritalvoltapresentiinunnumerotelefonico.Sitrattadiaggiungereicaratteriammessitraparentesiquadre.Eccol’espressioneregolarecompleta:

/^[0-9+()-]/

Page 198: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Potremmoancheestenderlaeforzareunadeterminatastrutturaolunghezzamassima,maperoraquestoèilrisultatochestavamocercando.

Utilizzareminlength,maxlength,minemaxLealtrequattrodirettiveoffertedaAngularJSperlavalidazionenonsonocosì

interessanti,masipossonorivelarepreziose.Peresempio,ladirettivaminlengthèidealepergarantirelasicurezzadellapasswordemin/maxsidimostranoutilineicasiincuièpresenteuncarrello,consentendosoltantounminimodiunoeunmassimodiunadeterminataquantitàdiarticoli.

Lequattrodirettivevengonoutilizzatenellostessomodoeaccettanounnumerocomevalore.Siang-minlengthsiang-maxlengthconsideranolalunghezzadell’input,mentreng-mineng-maxconsideranol’effettivovalorenumerico.

Eccoleinazione.Comepertutteledirettive,èpossibileutilizzareunacombinazioneperottenereleregoledesiderate.

<inputtype=”number”ng-min=”1”ng-max=”5”>

<inputtype=”password”ng-minlength=”8”ng-maxlength=”255”>

CreareunvalidatorpersonalizzatoAngularJSgestisceinmodoefficacelamaggioranzadeitipidiinputedeicasidi

utilizzo.Tuttavia,talvoltaavretenecessitàdiavereuncontrollomaggiore.Fortunatamenteèpossibilecreareproprievalidazionipersonalizzate.Ivalidatorpersonalizzatisonodirettiveconunrequisitospeciale.Perrenderleoperativeènecessarioimpostareng-modelsull’elemento.

Siccomelanostraapplicazionenonhauneffettivobisognodiunvalidatorpersonalizzato,vediamocomeèpossibilecrearneunoperverificarechel’inputnonsiapresenteinunalistapredefinita.Puòessereutileperfarsìcheunnomeutentesiaunivoco.

ChiamiamoquestadirettivauniqueListeinseriamolanelfilecontactsMgr.directives.js.Lalimiteremosoloadattributeeutilizzeremoilmetodolink.Perunriepilogoveloce,rileggeteilCapitolo6incuiabbiamodescrittolacreazionedidirettivepersonalizzate.

Possiamoinserireuncontrollercomeilquartoparametrodellafunzionelink.Angularsaqualecontrollerintendiamoutilizzareosservandolaproprietàrequiredella

Page 199: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

direttiva.L’abbiamoimpostatasungModel,peravereunaccessodirettoaun’APIperladirettivang-model:

.directive(‘uniqueList’,function(){

return{

restrict:‘A’,

require:‘ngModel’,

link:function(scope,elem,attrs,ctrl){

}

};

});

LadocumentazionediAngularJSillustratuttiicontrollerdibase.LeinformazionisungModelControllersonoreperibiliall’indirizzohttps://docs.angularjs.org/api/ng/type/ngModel.NgModelController.

All’internositrovaunmetodochiavechepossiamosfruttare:$setValidity.Ciconsentedidefinireseunmodelloèvalidoomeno.Loutilizzeremoinsiemeconscope.$watchperverificarelavaliditàqualorailmodellocambi.

Impostiamoinnanzituttoscope.$watchnelmetodolinkdelladirettiva.Possiamorecuperareilnomedelmodellodall’oggettoattrs:

.directive(‘uniqueList’,function(){

return{

restrict:‘A’,

require:‘ngModel’,

link:function(scope,elem,attrs,ctrl){

scope.$watch(attrs.ngModel,function(value){

});

}

};

});

Comesappiamo,èpossibileaccederealnuovoeunicovaloredaunwatcher.Perquestoesempiociservesoltantoilnuovovalore.Loconfronteremoconunalistadinomiutente.PotrebbeessereunarichiestaHTTPalserver,maperilmomentosaràditipohard-codesuunarrayodeinomi:

.directive(‘uniqueList’,function(){

varusernames=[

‘bob’,

‘john’,

‘paul’

];

return{

restrict:‘A’,

require:‘ngModel’,

link:function(scope,elem,attrs,ctrl){

scope.$watch(atts.ngModel,function(value){

});

}

};

});

Page 200: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Lavaliditàdelmodelloconsisteinunasempliceverificapercontrollareseilvaloresitrovanell’array:

varvalid=(usernames.indexOf(value)>-1)?false:true;

Ilmetodo$setValiditysulcontrollerngModelèmoltosempliceecontienesoltantodueparametri.Ilprimoèlachiaveerrormentreilsecondoèunbooleanonelcasoincuisiavalidoomeno.Impostiamolonelmodoseguente:

varvalid=(usernames.indexOf(value)>-1)?false:true;

ctrl.$setValidity(‘uniqueList’,valid);

Orachetuttoèdefinito,esaminiamoladirettivacompletaeilsuoutilizzo:

.directive(‘uniqueList’,function(){

varusernames=[

‘bob’,

‘john’,

‘paul’

];

return{

restrict:‘A’,

require:‘ngModel’,

link:function(scope,elem,attrs,ctrl){

scope.$watch(atts.ngModel,function(value){

varvalid=(usernames.indexOf(value)>-1)?false:

true;

ctrl.$setValidity(‘uniqueList’,valid);

});

}

};

});

Perusarla,èsufficienteassociarlaall’inputtramiteunattributo:

<inputtype=”text”ng-model=”contact.name”unique-list>

Page 201: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. Indicatetredirettivecheèpossibileutilizzareperlavalidazione.2. Inchemodoverifichiamolavaliditàdelform?3. ComepossiamoaccederealcontrollerngModeldurantelacreazionediun

validatorpersonalizzato?4. Inchemodoverifichiamol’inputsullabasediun’espressioneregolare?

Page 202: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoAbbiamovistocomefunzionalavalidazioneinAngularJSecomeèpossibile

combinarlaconglistilidiBootstrapperrenderel’apppiùuserfriendly.LavalidazionedeiformèstatasemplificataconledirettiveintegrateinAngularJSelavalidazioneautomaticadegliinputHTML5,comeemailetel.

Siamoriuscitiaverificarelavaliditàdelformnellafasediinvioeavisualizzaremessaggidierroreeavvertimentiappropriatinelcasoincuiquestaoperazionenonabbiasuccesso.Ancheseivalidatorintegratisonoottimiperlamaggiorpartedeicasi,abbiamoprovatoasvilupparneunotramiteunadirettiva.

Orachel’applicazioneècompleta,nelprossimocapitolovedremoalcunistrumentisviluppatidallacommunitychecisemplificanolavitaquandooperiamoconAngularJS.

Page 203: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo12

Page 204: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Strumentidellacommunity

Lanostraappdigestionedeicontattièterminata.Siamopassatidaunapaginavuotaaun’applicazioneCRUDsingle-pagecompletachesiconnettealserveredèinteramentevalida.QuestocapitoloillustreràduestrumentidellacommunitymoltoefficacieutilichevisemplificherannolavitaquandoutilizzereteAngularJS.

ImposteremoBatarangeng-annotateperilnostroprogetto.Ilprimomigliorerà,tral’altro,l’aspettodelloscope,mentreilsecondociconsentiràdiminificaremoltopiùfacilmenteifileJavaScript.Inquestocapitoloaffronteremoiseguentiargomenti.

Batarangeng-annotate.InstallareBatarangeng-annotate.Verificareloscope.Monitorarelaperformancedell’app.Utilizzareng-annotateconGruntegulp.

Page 205: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

BatarangBatarangèun’estensionediChrome(cispiacepergliutentidiFirefoxeSafari,ma

infindeicontiAngularJSèunprogettodiGoogle)cheoffreunaschedaaggiuntivaneglistrumentideglisviluppatoriperconsentircidicreareunprofiloedeffettuareildebuggingdelleappdiAngularJS.

InstallareBatarangÈfacileinstallareBatarangpoichéèun’estensionediChrome.Visitiamoilsito

https://chrome.google.com/webstore/ecerchiamoBatarangnellacasellainaltoasinistradellapagina.Dovrebbeesserel’unicorisultatonellasezionedelleestensioni,comemostralaseguenteschermata.

Fateclicsulpulsanteperinstallarloevedretecomparireunanuovaschedanelwebinspector,comemostralaseguenteschermata.

Page 206: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap
Page 207: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

VerificareloscopeeleproprietàForselafunzionepiùutilediBatarangèlacapacitàdiverificareidiversiscope

presentinell’applicazione.L’estensioneaggiungeunanuovaschedaalwebinspector;esaminiamola.

Batarangècostituitodacinqueschede:Models,Performance,Dependencies,OptionseHelp.PerutilizzareBatarangnell’applicazione,ènecessarioselezionarelacasellaEnable.Inquestomodolapaginasiaggiorneràel’estensioneinizieràaraccogliereleinformazioninecessarie.

EsistonotresistemiperverificareloscopeeleproprietàmedianteBatarang.QuellopiùovvioèfareclicsullaschedaModels,dovevedreteunalistadituttigliscopeannidati.

Page 208: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

AllasinistradellaschedaModelsèvisibileunalistadituttigliscopedellapagina.Selezionandoli,comparirannoadestraimodellicontenutinelloscope.Siaggiornanoautomaticamentequandocambiaunvaloresullapagina,consentendodivedereconestremafacilitàciòcheaccadeallorointerno.

Batarangaggiungeancheun’altraschedaquandoispezionaglielementi.SichiamaAngularJSPropertiesemostratuttociòcheAngularassociaaunelemento:rilevaseèpari,l’indicedell’iteminunng-repeatoseunelementodelformèvalidoomeno,comemostralaseguenteschermata.

L’ultimoeutilestrumentocheoffreBatarangperlaverificaèquellopresentenellaconsole.

DopoaverattivatoBatarang,potretedigitare$scopenellaconsolepervedereloscopedell’ultimoelementoselezionato,comemostralafigura.

MonitorarelaperformanceLaschedaPerformanceriportaun’utilelistadituttociòchevieneverificatoalla

ricercadieventualicambiamentidapartediAngular,oltreaunelencodiespressioniconladuratadiesecuzione.

Page 209: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Valelapenatenered’occhiolaperformancementrel’appsisviluppa.Forsescopriretediaveresageratoconlefunzioni$scope.$watchochel’esecuzionediunfiltroimpiegamoltotempo.

QuellachesegueèlaschermatacheraffiguralaschedaPerformancedellapaginaAddContactdell’applicazione.AsinistracomparelasezioneWatchTree.Èunalistadituttiiwatchersullapaginaemostrainqualescopesitrovano.Adestraèvisibileun’analisidelleespressionicheimpieganopiùtempo.

VisualizzareledipendenzeLaschedapiùinteressantediBatarangèsicuramenteDependencies.Contieneun

graficointerattivochemostratuttociòsucuisibasanoiservizidell’applicazione.

Quandopassateconilmousesoprailnomediunservizio,inomideiservizichesibasanosudiessovengonoevidenziatiinverde,mentreiservizichedipendonoda

Page 210: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

essovengonoevidenziatiinrosso.

Nellaschermataseguente,siamopassaticonilmousesopra$resource,chehaevidenziato$httpe$qinrossoecontactsinverde:

Probabilmenteavretenotatochenellaschermataprecedentecisonoalcuniservizichenondipendonodanullaedaessinondipendenulla.Accadeabbastanzaspesso,mapuòanchesignificarechenonvengonoutilizzatidall’applicazioneequindièopportunotenerlid’occhio.

OpzionidiBatarangNellaschedaOptionssonopresentitreutilicaselledicontrollo,cheevidenziano

conunbordocoloratoleapplicazioni,ibindingegliscopesullapagina.

Leapplicazionipresentanounbordoverde,ibindingunbordoblumentregliscopeunorosso.Sitrattadiunaraffigurazioneefficacepercapireseunaparte

Page 211: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

dell’appsitrovainundeterminatoscopeosesistaveramenteverificandounbinding.

Eccocomeapparel’appdopoaverattivatotutto:

Page 212: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ng-annotateng-annotateèunprogettoopensourcediOlovLassustesoaeliminarele

conseguenzepiùfrustrantiderivantidall’utilizzodiAngularJS.Ricorderetechequandoabbiamominificatoilcodice,abbiamoracchiusoledipendenzeinunarraypertenereinordineinomi.Ilprogettorendesuperfluoquestorequisitoosservandoilcodiceeracchiudendoloalpostonostro.Insintesilostrumentoèunpre-minificatoreedovremmousarloperpreparareilcodiceperl’attivitàuglify.

InpassatoabbiamoutilizzatongMindiBrianFordperottenerelostessorisultato.Questoprogettoèstatodeprecatoinfavoreding-annotate.

Installareng-annotateLostrumentong-annotateèunpacchettonpmepuòessereinstallatotramiterigadi

comando.EsistonoaltripacchettichefunzionanoconleinstallazionidiGruntegulp,maperilmomentoesaminiamocomeèpossibileeseguiremanualmenteilprogetto.

1.Apriteilterminaleedeseguiteilprossimocomandoperinstallareglobalmenteilpacchettosulcomputer:

npminstall–gng-annotate

NOTA

Ricordatecheserestituisceunerrorelegatoaipermessi,dovreteeseguirlocomeamministratore.Potete farlocon ilcomandosudo inunsistemabasatosu*nixoppureeseguendo ilpromptdeicomandicomeamministratoresuWindows.

Viforniràunnuovocomandodautilizzarenelterminale.Seeseguiteng-annotate,dovrebbecomparireilfilehelpperlostrumento.Èfacileutilizzareng-annotateinunfile:èsufficienteavvalersidelcomandong-annotateseguitodalleopzioniedalnomedelfilecheintendiamoelaborare.

2.Nelladirectoryjsdelprogettoeseguite

ng-annotate-rcontrollers/app.js

Dovrebberestituireilcontenutodelcontrollerdell’appmaconunapiccolavariazione:vedretechetutteleannotazioniesistentiattornoalledipendenzesonostatecancellate.Infattiabbiamocomunicatoang-annotatedieliminarleconl’opzione-r.

3.Possiamoanchefarsìcheng-annotateleaggiunganuovamentemediante-a.Questedueopzionipossonoessereutilizzateinsiemeodasole:

Page 213: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ng-annotate-racontrollers/app.js

4.Questavoltavienerestituitoilcontrollerconleannotazioni.Possiamonotarecheng-annotatehaoperatolasuamagiaperchélevirgolettesingolecheracchiudonoledipendenzesonostatesostituitedavirgolettedoppie.

Orang-annotatefunziona,maèinutileseènecessarioeseguirlomanualmente.Inchemodoèpossibileinserirloneitaskrunner?Scopriamolo.

Utilizzareng-annotateconGruntPerutilizzareng-annotateconGrunt,dobbiamoinstallareunaltropacchettonpm.

Questavoltanonèglobale,maènecessarioinstallarlonelprogetto.Seguitequestipassi.

1.Passateallacartelladelprogettonelterminale:

cd~/path/to/contacts-manager

2.OrainstallateilmoduloGruntsalvandolonelledipendenzedevdelprogettoinmododapoterlosempreinstallarenuovamenteinseguito;inoltreunaltrosviluppatorechelavoreràalprogettopotràinstallarecosìtuttoilnecessario:

npminstallgrunt-ng-annotate--save-dev

3.PrimadieffettuarequalsiasimodificanelGruntfile,nondimenticatedicaricareleattivitàdalpacchettoappenainstallato:

grunt.loadNpmTasks(‘grunt-ng-annotate’);

Configurarel’attività

Noncirestacheconfigurarel’attivitàngAnnotatenelGruntfileedeffettuareduepiccolemodifichenell’attivitàwatch.Eccocomeprocederemo.

1.Aggiungiamolanell’attivitàlessall’internodell’oggettogrunt.initConfig.

ngAnnotate:{

}

2.ComelamaggiorpartedelleattivitàdiGrunt,ngAnnotateaccettaunhashoptionsoltreapiùtarget.Impostiamoprimaoptions:

ngAnnotate:{

options:{

remove:true,

add:true,

singleQuotes:true

Page 214: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

}

}

Abbiamodefinitotreopzioni.Abbiamosceltodieliminarequalsiasiannotazionepreesistenteperaggiungernedinuoveconng-annotateeutilizzarevirgolettesingoleenondoppie.Èanchepossibiledefinireun’espressioneregolareseintendiamooperareinunasezionespecifica.

3.Iltargetguarderàtuttiifilenelladirectoryjselisalveràconl’estensione.annotated.js.Inquestomodoèpossibileimpostarel’attivitàwatchpereseguireng-annotateepoil’attivitàuglifyaffinchécerchiifilecheterminanocon.annotated.js.

4.Gliunicifileaiqualidobbiamoprestareattenzionesonoinostri.Tuttonelladirectoryvendorsaràpreannotato,ononsaràlegatoadAngular.PossiamoconfigurareGruntaffinchéconsiderituttotrannelecartellevendorebuild:

ngAnnotate:{

options:{

remove:true,

add:true,

singleQuotes:true

},

app:{

src:[

‘assets/js/**/*.js’,

‘!assets/js/vendor/*.js’,

‘!assets/js/build/*.js’

]

}

}

5.Ilprimopercorsonell’arraysrcincludetuttiifileJSnelladirectoryjsdelprogetto.Comeabbiamoprevisto,ènecessarioignorarelecartellevendorebuild.Idueitemcheseguononell’arrayfannoproprioquesto.IlpuntoesclamativoprimadelpercorsoindicaaGruntcheintendiamoescluderetuttiifileJSinquestecartelle.

6.Dopoaverspecificatoilsorgente,ènecessariocomunicareang-annotateciòchevogliamofareconifiledopochesonostatielaborati.Intendiamorinominareilfileperincluderel’estensione.annotate.jsesalvarlinellostessoposto:

ngAnnotate:{

options:{

remove:true,

add:true,

singleQuotes:true

},

app:{

src:[

‘assets/js/**/*.js’,

‘!assets/js/vendor/*.js’,

‘!assets/js/build/*.js’

],

expand:true,

ext:‘.annotated.js’,

extDot:‘last’

}

}

Page 215: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

7.Nelcodiceprecedenteabbiamoaggiuntotrenuoveproprietàperiltarget:expand,extedextDot.Laproprietàexpanddivideilpercorsoeciconsentedicambiarel’estensione.Laproprietàextmodifical’estensionementrelaproprietàextDotcomunicaaGruntqualepuntonelnomefileguardare.Nelnostrocasoèl’ultimoequestocitutelanelcasodovessimoutilizzarepiùpuntineinomifile.

8.Orasiamoprontiaeseguirel’attivitànelterminale.Eseguiamolaconilflag--verboseevediamociòcheaccade:

gruntngAnnotate--verbose

9.Tuttosembrafunzionareallaperfezionemacreandoinuovifile.annotated.js,avremodeiproblemiquandoeseguiremol’attivitàunasecondavolta.Otterremoquestooutputquandoeseguiremonuovamenteilcomandoprecedente:

Writingassets/js/modules/contactsMgr.services.annotated.

annotated.js

10.L’attivitàhapresoinconsiderazionenonsoloifile.jsnelledirectorymaancheifile.annotated.js.CiòaccadeperchéGruntnonconosceladifferenza.Siccomeprendel’ultimopuntoperdeterminarel’estensione,èsufficienteaggiungereun’altraesclusioneall’arraysrcpercompletarel’attività:

ngAnnotate:{

options:{

remove:true,

add:true,

singleQuotes:true

},

app:{

src:[

‘assets/js/**/*.js’,

‘!assets/js/**/*.annotated.js’,

‘!assets/js/vendor/*.js’,

‘!assets/js/build/*.js’

],

expand:true,

ext:‘.annotated.js’,

extDot:‘last’

}

}

1. Cancellateglialtrifile.annotated.annotated.jsnelladirectoryjsedeseguitel’attivitàun’ultimavolta.

Impostarel’attivitàwatch

Orachel’attivitàngAnnotatefunzionacomeprevisto,èpossibileeffettuarealcunemodifichenelleattivitàwatcheuglifypereseguirlaautomaticamenteeminificareifileJavaScript,nelmodoseguente.

Page 216: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

1.Innanzituttoènecessariomodificareiltargetjsnell’attivitàwatchpereseguirengAnnotateinvecediuglify:

js:{

files:[

‘assets/js/**/*.js’

],

tasks:[‘ngAnnotate’]

},

2.Aggiungiamoanchedueesclusioninell’arrayfiles.Nondobbiamoosservareladirectorybuild,edènecessariocomunicareaGruntdiignoraretuttiifilecheterminanocon.annotated.js:

js:{

files:[

‘assets/js/**/*.js’,

‘!assets/js/build/*.js’,

‘!assets/js/modules/**/*.annotated.js’,

‘!assets/js/controllers/**/*.annotated.js’

],

tasks:[‘ngAnnotate’]

},

3.Verifichiamorapidamentesefunzionatutto.Nelterminaleavviamol’attivitàwatch:

gruntwatch

4.OrasesalvateunfileJS,comeilcontrollerdell’app,GruntdovrebberilevareunamodificaeattivarengAnnotate:

Running“watch”task

Waiting…OK

>>File“assets/js/controllers/app.js”changed.

Running“ngAnnotate:app”(ngAnnotate)task

>>8filessuccessfullygenerated.

Done,withouterrors.

5.Sembrafunzionarebene.Possiamocreareunnuovotargetchecontrolliifileannotatiallaricercadellemodificheedesegual’attivitàuglify:

annotated:{

files:[

‘assets/js/**/*.annotated.js’,

],

tasks:[‘uglify’]

},

6.Èfacile,ecercalemodificheneifileconestensione.annotated.js.Infinedobbiamoeffettuareduemodifichenell’arraysrcall’internodeltargetdibuilddiuglify:

src:[

‘assets/js/vendor/jquery.js’,

‘assets/js/vendor/bootstrap.js’,

Page 217: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

‘assets/js/vendor/angular.js’,

‘assets/js/vendor/angular-animate.js’,

‘assets/js/vendor/angular-resource.js’,

‘assets/js/vendor/angular-route.js’,

‘assets/js/vendor/angular-sanitize.js’,

‘assets/js/vendor/angular-strap.js’,

‘assets/js/vendor/angular-strap.tpl.js’,

‘assets/js/modules/*.annotated.js’,

‘assets/js/controllers/*.annotated.js’

],

7.Abbiamoeffettuatoduemodificheagliultimidueitemnell’arrayperguardareifilegeneratiinvecedeiloroomologhinonannotati.Eseguiamonuovamentel’attivitàwatchdiGrunterisalviamounfileJSpervederecosasuccede:

Running“watch”task

Waiting…OK

>>File“assets/js/controllers/app.js”changed.

Running“ngAnnotate:app”(ngAnnotate)task

>>8filessuccessfullygenerated.

Done,withouterrors.

Running“uglify:build”(uglify)task

File“assets/js/build/ContactsMgr.js”created.

Done,withouterrors.

8.Quandoabbiamosalvatoilfileapp.js,Gruntharilevatounamodificaehaeseguitol’attivitàngAnnotategenerandoottofile.L’attivitàwatchharilevatolapresenzadimodificheneifileannotatiappenageneratiehacreatoilfileContactsMgr.jseseguendol’attivitàuglify.Dopotuttiquesticambiamenti,eccocomeappareGruntfile.js:

module.exports=function(grunt){

grunt.initConfig({

pkg:grunt.file.readJSON(‘package.json’),

watch:{

js:{

files:[

‘assets/js/**/*.js’,

‘!assets/js/build/*.js’,

‘!assets/js/**/*.annotated.js’

],

tasks:[‘ngAnnotate’]

},

annotated:{

files:[

‘assets/js/**/*.annotated.js’,

],

tasks:[‘uglify’]

},

less:{

files:[

‘assets/less/*.less’

],

tasks:[‘less:dev’]

},

css:{

files:[

‘assets/css/bootstrap.css’

],

options:{

livereload:true

Page 218: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

}

}

},

uglify:{

options:{

banner:‘/*!<%=pkg.name%><%=

grunt.template.today(“yyyy-mm-dd”)%>*/\n’

},

build:{

src:[

‘assets/js/vendor/jquery.js’,

‘assets/js/vendor/bootstrap.js’,

‘assets/js/vendor/angular.js’,

‘assets/js/vendor/angular-animate.js’,

‘assets/js/vendor/angular-resource.js’,

‘assets/js/vendor/angular-route.js’,

‘assets/js/vendor/angular-sanitize.js’,

‘assets/js/vendor/angular-strap.js’,

‘assets/js/vendor/angular-strap.tpl.js’,

‘assets/js/modules/**/*.annotated.js’,

‘assets/js/controllers/**/*.annotated.js’

],

dest:‘assets/js/build/<%=pkg.name%>.js’

}

},

less:{

dev:{

files:{

‘assets/css/bootstrap.css’:

‘assets/less/bootstrap.less’

}

},

production:{

options:{

cleancss:true

},

files:{

‘assets/css/bootstrap.css’:

‘assets/less/bootstrap.less’

}

}

},

ngAnnotate:{

options:{

remove:true,

add:true,

singleQuotes:true

},

app:{

src:[

‘assets/js/**/*.js’,

‘!assets/js/**/*.annotated.js’,

‘!assets/js/vendor/*.js’,

‘!assets/js/build/*.js’

],

expand:true,

ext:‘.annotated.js’,

extDot:‘last’

}

}

});

grunt.loadNpmTasks(‘grunt-contrib-uglify’)

grunt.loadNpmTasks(‘grunt-contrib-watch’);

grunt.loadNpmTasks(‘grunt-contrib-less’);

grunt.loadNpmTasks(‘grunt-ng-annotate’);

grunt.registerTask(‘default’,[‘ngAnnotate’,‘uglify’]);

};

Utilizzareng-annotatecongulp

Page 219: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Propriocomeperqualsiasicosaabbiamovistofinora,esisteancheunaversionegulpding-annotatecheciconsentiràdiutilizzarequestotaskrunneralternativo,seèquellocheabbiamoscelto.Studiamocomeèpossibileimpostarloaffinchéopericongulpfilepreesistente.

1.Recuperiamoilpacchettodanpm:

npminstallgulp-ng-annotate--save-dev

2.Apriamogulpfile.jseinseriamoilpacchettoappenainstallato:

varngAnnotate=require(‘gulp-ng-annotate’);

3.Inquestomodoavremounanuovafunzionedautilizzareconglioperatoripipedigulp.Èincredibilelamaggiorerapiditàdiinstallazionedigulpperutilizzareng-annotaterispettoaGrunt.Èsufficienteaggiungereunnuovopipeall’attivitàuglify:

gulp.task(‘uglify’,function(){

gulp.src(paths.js)

.pipe(concat(pkg.name+’.js’))

.pipe(ngAnnotate())

.pipe(uglify())

.pipe(gulp.dest(‘assets/js/build’));

});

4.IlpipeconlafunzionengAnnotatepuòessereinseritoprimadelpipeuglify.L’attivitàwatchègiàimpostatapereseguirel’attivitàuglifyognivoltachecambiaunfileJS;pertantoquestoètuttociòchedobbiamofareingulpfile.

5.Orapossiamoricorrereauglifydigulppereseguiremanualmenteng-annotateeminificareilJavaScript,oppureutilizzarewatchdigulpperrilevareautomaticamenteicambiamenti.Dopoquesteduepiccolemodifiche,eccocomeappareilfilegulpfile.js:

vargulp=require(‘gulp’);

varuglify=require(‘gulp-uglify’);

varconcat=require(‘gulp-concat’);

varpkg=require(‘./package.json’);

varless=require(‘gulp-less’);

varlivereload=require(‘gulp-livereload’);

varngAnnotate=require(‘gulp-ng-annotate’);

varpaths={

js:[

‘assets/js/vendor/jquery.js’,

‘assets/js/vendor/bootstrap.js’,

‘assets/js/vendor/angular.js’,

‘assets/js/vendor/angular-animate.js’,

‘assets/js/vendor/angular-resource.js’,

‘assets/js/vendor/angular-route.js’,

‘assets/js/vendor/angular-sanitize.js’,

‘assets/js/vendor/angular-strap.js’,

‘assets/js/vendor/angular-strap.tpl.js’,

‘assets/js/modules/**/*.js’,

‘assets/js/controllers/**/*.js’

],

less:‘assets/less/**/*.less’

Page 220: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

};

gulp.task(‘uglify’,function(){

gulp.src(paths.js)

.pipe(concat(pkg.name+’.js’))

.pipe(ngAnnotate())

.pipe(uglify())

.pipe(gulp.dest(‘assets/js/build’));

});

gulp.task(‘watch’,function(){

varserver=livereload();

gulp.watch(paths.js,[‘uglify’]);

gulp.watch(paths.less,[‘less’]);

gulp.watch(‘assets/css/bootstrap.css’).on(‘change’,

function(file){

server.changed(file.path);

});

});

gulp.task(‘less’,function(){

gulp.src(‘assets/less/bootstrap.less’)

.pipe(less({

filename:‘bootstrap.css’

}))

.pipe(gulp.dest(‘assets/css’));

});

gulp.task(‘default’,[‘uglify’]);

Page 221: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Quiz1. Checos’èBatarang?2. IndicatetrestrumenticheoffreBatarang.3. Qualisonoiduesistemiperverificareloscope?4. Checosaabbiamoutilizzatoprimading-annotate?5. Qualiopzionioffreng-annotate?6. Qualeproblemarisolveng-annotate?

Page 222: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

RiepilogoInquestocapitoloabbiamotrattatoduestrumentidellacommunityefficaciemolto

affidabilieutilizzati.BatarangrappresentailcoltellinosvizzerodeglistrumentididebuggingcheaiutaasvilupparefantastichewebappconAngular;ng-annotatecisollevadall’irritanteincombenzadelleannotazionidurantelaminificazionedeifile.

QuestiduestrumentisonofacoltativienonsononecessariquandosiutilizzaAngular,maentrambiviaiuterannolungoilcamminoelisfruttereteregolarmente.SonosoltantoduedeglistrumenticreatidallasorprendentecommunitydiAngularJS.Esplorateescopritechecos’altrooffreperfacilitarvilavita.Esenonriusciteproprioatrovareciòchestatecercando,sviluppatelovoieproponeteloallacommunity!

Page 223: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

AppendiceA

Page 224: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Personeeprogetti

SiaAngularJSsiaBootstrapvantanounnutritoseguitoedueenormicommunity,adimostrazionecheiprogettibasatisuentrambiiframeworksononumerosi.Dietroogniprogettooperanosviluppatoriscrupolosi.Scopriamoalloraalcunepersoneeprogettidegnidinota.

Page 225: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ProgettiepersonedietroBootstrapAttualmenteBootstrapègiuntoallaterzaversione;ciòsignificacheesistono

numeroseestensioniestrumentiutilichevipossonoaiutaredurantelosviluppo.

IlteamprincipaleBootstrapènatoall’internodiTwitteredèlacreaturadidueingegneri

dell’azienda:MarkOtto(@mdo)eJacobThornton(@fat).Tuttieduehannoinseguitolasciatoquestacompagnia,macontinuanoacontribuirealprogetto.

Attualmentesicontanoquasi600collaboratoriaBootstrap,ilchesottolinealaforzadiunsoftwareopensource.

EntrambiicreatorioriginarihannoabbandonatoTwitter,maMarkcontinuaaessereilcollaboratoreegestorepiùattivodiBootstrap.

URL:http://www.getbootstrap.comTwitter:@twbootstrapPersone:MarkOtto(@mdo),JacobThornton(@fat)ealtri.

BootstrapExpoQuandoparliamoconchiconosceunpo’Bootstrapmanonl’haancora

sperimentato,scopriamocheèconvintocheilframeworksiaunostilefisso.Buonapartedellasuacattivafamaderivadaiprimiprogettibasatisudiesso.Inpassatoognipaginadeiplug-injQueryvenivasviluppataconBootstrapprivodistili.

Comesappiamo,Bootstrapèmoltopiùdiquesto;èunframeworkfront-endatuttotondo.Persfatarequestaconvinzioneerrata,uncreatorediBootstraphaapertoilblogBootstrapExpoincuiillustragliutilizzipiùstimolantidiBootstrapnelWeb.

URL:http://expo.getbootstrap.comPersone:MarkOtto(@mdo)

BootSnippBootSnippèunarisorsaincredibileperchiunqueopericonBootstrap.Nellasua

versionepiùsemplice,èunaraccoltadicomponentiprecodificaticheèpossibile

Page 226: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

copiareeincollarenelprogetto.Èpossibiletrovarestrumentiperlanavigazione,immaginiscorrevoliefinestremodaliaccompagnateconunostile.

MaBootSnippnonèsoloquesto.PoteteeffettuareunaricercainbasealleversionidiBootstrap,esaminarelealtreprezioserisorseeutilizzaregliutilicostruttoridiformepulsantineiqualièsufficientetrascinareglielementidesideratiecopiarel’HTML.

URL:http://www.bootsnipp.comTwitter:@BootSnippPersone:MaksimSurguy(@msurguy)

Lineeguidasulcodicedi@mdoQuandoilprogettosiamplierà,dovreteseguirealcunistandardperquantoriguarda

HTMLeCSS.Ovviamentequandolavorereteaunprogettoconaltrepersone,lasituazionesipuòcomplicareelanecessitàdiunaguidasuglistilirisulteràpiùevidente.

MarkOtto,unodeico-creatoridiBootstrap,haideatounaguidaesaurientesuglistandardcheutilizzaneisuoiprogetti.Valelapenadareun’occhiata,ancheseunabuonapartedipendedallepreferenzepersonaliedalleesigenzevostreedelvostroteam.Servitevenecomepuntodipartenzaperdefinireisetdistandardediregole.

URL:http://codeguide.co/Persone:MarkOtto(@mdo)

RootsRootsèunostarterthemeopensourcediWordPresscheaccompagnaBootstrap,

GrunteBoilerplateHTML5persvilupparefantasticitemiWordPress.Anchesenonabbiamoaffrontatoquestoargomentonelcorsodellibro,vorremmosegnalarvilapossibilitàcheBootstrapoffreperrealizzarequalsiasicosa.Èunapiattaformamoltoversatileesolidasucuicreareiprogetti.

URL:http://roots.io/Persone:BenWord(@retlehs)

Page 227: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ShoelaceSeavetedelledifficoltàasviluppareovisualizzarelegriglieconBootstrap,valela

penadareun’occhiataaShoelace.ÈunpraticostrumentocheconsentedisviluppareinmodointerattivolagrigliadelleapplicazioniegeneraretuttoilmarkupdicuiabbiamobisognoinHTML,JadeoEDN.

Èpossibilesalvareecondividerelegriglieeverificareilloroaspettosudispositivididiversedimensioni.Sipossonoaggiungerealtreclassiallerigheeallecolonne,ancheseperimpostazionepredefinitaèpossibileutilizzaresoltantolecolonneneidispositividipiccoledimensioni.Ovviamentepotretesostituirleinseguito,sefossenecessario.

URL:http://www.shoelace.ioPersone:ErikFlowers(@Erik_UX)eShaunGilchrist

SnippetdiBootstrap3perSublimeTextSublimeText2e3sonoeditorditestomoltopopolaritraglisviluppatorienon

sorprendecheesistaunplug-incheincludeinnumerevolisnippetperilvostroframeworkfront-endpreferito.

Ilplug-inviconsentediinserirerapidamentequalsiasicomponentediBootstrapsemplificandonemoltol’utilizzo.PuòessereinstallatotramitePackageControlcercandoBootstrap3Snippets,oppurepoteteprocurarvelodaGitHub.

URL:https://github.com/JasonMortonNZ/bs3-sublime-pluginPersone:JasonMorton(@JasonMortonNZ)

FontAwesomeIlprogettohapresoilviapersostituireleiconediimmaginediBootstrap2con

alcuneequivalenti.SièsviluppatofinoadiventareunadelleprincipaliraccoltedifontdiiconechepuòessereutilizzataconosenzaBootstrap.

SedesiderateestenderelagammadiiconegiàriccadiBootstrap,provateFontAwesome.

URL:http://fortawesome.github.io/Font-Awesome/

Page 228: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Persone:DaveGandy(@davegandy)

BootstrapIconsBootstrapcomprendegiàunafantasticacollezionediiconeesipuòfacilmente

estendereconFontAwesome.BootstrapIconsèstatocreatopercercarerapidamentetraleiconeerecuperarelaclassenecessaria.

Èmoltopiùfaciletrovarequiciòcheviserverispettoalladocumentazioneufficiale,perchéogniiconaèstatataggataconpiùparolechiave.Digitateciòchecercatenellacaselladiricercaeilsitolotroverà.

URL:http://bootstrapicons.com/Persone:BrentSwisher(@BrentSwisher)

Page 229: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

ProgettiepersonedietroAngularJSAlcuniprogettidellacommunitydiAngularJSpossonodiventarepartedelflusso

dilavoroquotidiano.Neabbiamogiàesaminatialcuninellibro,maoranedescriveremoaltridiunacertaimportanza.

IlteamprincipaleComesapete,AngularJSèunprogettoGooglee,cometale,ilsuoteamprincipale

ècostituitodadipendentidiquestaazienda.ForsenonsapeteperòcheilframeworkfucreatoinBratTechLLCdaMiškoHeveryeAdamAbronspersupportareunserviziodiarchiviazioneJSONchiamatohttp://getangular.com/.InseguitoabbandonaronoilservizioereseroopensourceilframeworkAngularJscheabbiamoimparatoaconoscereeapprezzare.

MiškocontinuaagestireilprogettocomedipendenteGooglecollaborandocondiversialtriingegneri.Insiemel’hannoampliato,rilasciatoun’infinitàdimoduliaggiuntiviecreatolapopolareestensioneperChromeBatarang.

URL:https://angularjs.org/Persone:MiškoHevery(@mhevery),AdamAbrons(@abrons),BrianFord(@briantford),BradGreen(@bradlygreen),IgorMinar(@IgorMinar),VotjaJína(@vojtajina)ealtri.

RestAngularAbbiamogiàillustratoiduesistemiconcuiAngularconsentediconnettersia

un’API:$httpengResource.EsisteancheunprogettodellacommunitymoltopopolarechiamatoRestAngularchesegueunapprocciodiverso.

LadifferenzaprincipalerispettoangResourceconsistenelfattocheutilizzalepromise,mentre$resourceesegueautomaticamenteillorounwrapping.Asecondadicomefunzionailvostroprogetto,puòessereunsistemaefficacepoichépotreterisolvereidatidellaroutemediante$routeProvider.resolve.

SeoperateconunaRESTfulAPInelprogettoengResourcenonviconvincedeltutto,dateun’occhiataaRestAngular.

URL:https://github.com/mgonto/restangular

Page 230: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Persone:MarinGonto(@mgonto)

AngularStrapeAngularMotionAbbiamogiàstudiatoeutilizzatoAngularStrapnelnostroprogetto.Offreuna

raccoltafantasticadituttiiprincipaliplug-indiBootstrapperledirettivenativediAngularJS.SeutilizzateBootstrapinsiemeconAngularJS(comeabbiamofattonellibro),èunmoduloimperdibile.

AngularMotionèprogettatopervenireutilizzatoconAngularStrap,anchesenonèstrettamentenecessario.SitrattadianimazionigiàprontechefunzionanonativamenteconngAnimateeaggiungonountoccoinpiùalprogetto.Sipossonoutilizzareconng-showeng-hideecondirettivecomeng-repeatperanimarel’aggiuntaolacancellazionedegliitem.

URL:http://mgcrea.github.io/angular-strap/ehttp://mgcrea.github.io/angular-motionPersone:OlivierLouvignes(@olouv)

AngularUIIlprogettoAngularUIèprobabilmenteilpiùgrandecheèsortodallacommunity

diAngularJS.SidivideindiversimodulitracuiUI-Utils,UI-ModuleseUI-Router.

IlmoduloUI-Utilsvienedescrittocomeil“coltellinosvizzero”deglistrumenti,edeffettivamenteloè.Consenteoperazionicomeevidenziaredeltesto,verificarelepressioniditastiorendereunelementofissoalloscroll.

GliUI-ModulessonomoduliAngularJScondipendenzeesterneperGoogleMapsoplug-injQuery.Quitroveretealcunistrumentiefficaci,epersonalmentehoutilizzatoilmoduloSelect2indiverseoccasioni.

ForseilprogettopiùpopolareèilmoduloUI-Router.OffreunveroroutingannidatoperAngular.Consentedisuddividerelapaginainstati;peresempiopotresteavereunostatoperlabarralateraleeunaltroperilcontenutoprincipale.Possonoavereentrambiunpartial;inoltrepermettedisviluppareinmodopiùsemplicegrandipagineowebapp.

EsisteperfinounmoduloperBootstrapsimileadAngularStrap,chevalelapenaconsiderare.

Page 231: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

URL:http://angular-ui.github.io/Twitter:@angularuiPersone:NateAbele(@nateabele),TasosBekos(@tbekos),AndrewJoslin(@andrewtjoslin),PawelKozlowski(@pkozlowski_os),DeanSofer(@Unfolio),DouglasDuteil(@douglasduteil)ealtri.

MobileAngularUIAdifferenzadelprogettoAngularUI,questohaloscopodisviluppare

un’interfacciautente.SitrattadiunsempliceframeworkmobilecheutilizzasiaAngularJSsiaBootstrap3.Glielementiappaionoabbastanzanativi,anchesealcuneparticomelabarradinavigazionelateralepotrebberoesseremigliorate.Èancoraaisuoialbori,mahaunseriopotenzialeevalelapenaseguirelasuaevoluzione.

URL:http://mobileangularui.com/Twitter:@mobileangularuiPersone:mcasimir

IonicIonicèincredibile.Loèdavvero.RiuniscetuttociòcheèefficaceinAngularJSe

Cordova/Phonegapperconsentirvidisvilupparestraordinarieappibrideconilinguaggiwebchegiàconoscete.

Tuttosembranativoedèfacilissimoiniziareanchesenonavetemaisviluppatoun’app.UtilizzaAngularJSel’estensioneUI-Routerinsiemeconillorocodice.L’aspettomiglioreècheèinteramenteopensourceechiunquepuòcontribuirvisuGitHub.

ÈstatoancherealizzatoilmodulongCordova,riccodidirettivecheèpossibilesfruttareperinterfacciarsifacilmenteconnumerosiplug-inCordova.

URL:http://ionicframework.com/Twitter:@ionicframeworkPersone:TheDriftyTeam(http://drifty.com/):AndrewJoslin(@ajoslin)ealtri.

AngularGM

Page 232: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

AncheseAngularUIincludeunadirettivaperutilizzareleGoogleMapsall’internodiAngular,preferiamol’approcciopiùsemplicediAngularGM.QuestomoduloconsentelacreazionesemplicedelleGoogleMapsnelprogetto,insiemeconmarker,InfoWindowsepolyline.

Potetepersonalizzarequasituttociòchedesiderate,dallamodificadeicoloriedalleimpostazionidellamappaall’utilizzodiunelementopersonalizzatoperl’InfoWindowol’iconanonstandardperilmarker.

URL:https://github.com/dylanfprice/angular-gmPersone:DylanPrice

Page 233: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Oratoccaavoi…IlnumerodiprogettiopensourceriguardantiBootstrapeAngularJSèincredibile.

Tuttipossonocontribuirvi,perfinovoi!Setrovateunbug,segnalatelo,osesapetecomerisolverlo,inviateunapullrequestediventateuncontributor.

Naturalmentenontuttiiproblemisonostatirisolti.Orachesapetecomeutilizzareentrambiiframework,toccaavoidivertirviasvilupparequalcosadistraordinario.

Page 234: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

AppendiceB

Page 235: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Incasodidubbio

Ancheglisviluppatoripiùespertinonsannotalvoltachepescipigliareenonc’ènulladimalenelchiedereunamano.

EsistonoalcunistrumentispecificiriguardantiBootstrapeAngularJSchepossonoaiutarvi,nelcasoviservisse.

Page 236: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

LadocumentazioneufficialeSeviimbatteteinunproblemaoavetebisognodirinfrescarelamemoria

consultateinnanzituttoladocumentazioneufficiale.

SiaBootstrapsiaAngularJSvantanoun’ottimadocumentazione.InpassatoeranosortedellelamentelesuquelladiAngularJS,ritenutaconfusaeconpochiesempi,manegliultimiannièmiglioratanotevolmente.Perulterioridettagli,visitateisitihttp://www.angularjs.orgehttp://www.getbootstrap.com.

Page 237: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

L’issuetrackerdiGitHubSiaAngularsiaBootstrapsonoospitatisuGitHubedentrambisiavvalgono

dell’issuetrackerdelservizio.Sescopriteunbuginunodeidueframework,segnalateloqui.

Ovviamenteseconoscetelanaturadelproblemaesapetecomerisolverlo,poteteinviareunapullrequestecontribuirealprogetto.Perulterioridettagli,visitatehttp://www.github.com/angular/angular.js/issuesehttp://www.github.com/twbs/bootstrap/issues.

Page 238: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

StackOverflowForsepensavatecheneavremmoparlato.StackOverflowèunarisorsaeccezionale

eunottimostrumentodautilizzareseaveteunadomandaspecifica.Ilpiùdellevoltetroveretequalcunaltrochehapostolostessoquesitoepotreteleggerelerisposte.Altrimentiponeteunanuovadomandaetaggatelacome“AngularJS”o“TwitterBootstrap”.Perulterioridettaglivisitatehttp://www.stackoverflow.com.

Page 239: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

IlgruppoGoogleAngularJSManmanocheutilizzateAngularJS,vipossiamogarantirechedopoalcune

ricerchesuGoogle,viritrovereteinquestogruppo.Sitrattadelgruppo/forumufficialediAngularJSedèmoltoattivo.

Contienepiùdi11.000argomentievalelapenaeffettuarequiunaricercaprimadiporreunanuovadomanda.Perulterioridettaglivisitatehttps://groups.google.com/forum/#!forum/angular.

Page 240: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Egghead.ioSecercatedeitutorialvideosuAngularJS,Egghead.ioèprobabilmentelarisorsa

migliore.Offreunserviziodiabbonamentoapagamento,masipuòconsultaregratuitamentebuonapartedellasualibreria.Sevoletedisporredialtromaterialevideoinformativo,visitatehttps://egghead.io/tags/free.

Page 241: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

TwitterPuòsembrareunasegnalazionebizzarracomerisorsadisupporto,masuTwittersi

trovanopersonemoltoutili.Forsenonèilluogomiglioreperporredomandecomplesse,maperpiccoledrittepuòessereprezioso.

Quisiincontranoappassionatidientrambiiframeworkedèpossibilepartecipareallerispettivecommunity.IdueframeworkhannoaccountTwitterufficiali:@angularjse@twbootstrap.

Aproposito,sevoletemandarmiuntweet,iosono@steve228uk.

Sicuramente,conoscendopiùafondoAngularJSeBootstrap,fareteriferimentoalladocumentazioneechiederetesempremenoaiuto.Abbiamoimparatocheèmoltoimportantetrasmettereciòchesiconosce.

Forsechiedereteunamanopersviluppareunadirettivamoltospecifica,maciònonsignificachenonsapreteaiutareanchevoiglialtri.Quandoaveteunpo’ditempo,accedeteaStackOverfloweprovatearispondereadalcunedomande;scommettocheriusciretearispondereamoltepiùdomandediquellecheavrestemaiimmaginato!

Page 242: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

AppendiceC

Page 243: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Risposteaiquiz

Capitolo11. Utilizzandol’attributong-app.2. Lasintassichecomprendedoppieparentesigraffe:{{model}}.3. ModelViewController.4. CreiamouncontrollerutilizzandouncostruttoreJSstandardel’attributong-

controller.5. Jumbotron.

Page 244: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo21. Unabarradinavigazione(navbar)diBootstrap.2. 12colonne.3. Èunafunzionechiamatadaunattributoounelementopersonalizzato.4. ng-repeat.

Page 245: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo31. Conilsimbolopipeinunmodello:{{modelName|filter}}.2. Coniduepunti:{{modelName|filter:arg1:arg2}}.3. Ilfiltrochiamatofilter.4. Utilizziamoilservizio$filterinserendoilfiltrocomeservizioseguendoil

patternfilternameFilter.5. UnmoduloAngularJS.

Page 246: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo41. ngRoute.2. Ilmetodoconfignelmodulo.3. Ilservizio$routeProvider.4. Conilmetodo$routeProvider.when.5. Ilmetodo$routeProvider.otherwise.6. Utilizzandohtml5Mode.

Page 247: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo51. Perchéèinclusonellavistadellaradice.2. Diverseclassi:table-bordered,table-striped,table-hoveretable-condensed.3. Con<buttonclass=”btnbtn-primarybtn-lg”><button>.4. Nellaclasseform-group.5. Leetichettevengonoallineateallasinistradeglielementi.6. Laclassehelp-block.7. img-circlepercreareun’immaginedallaformacircolare,img-roundedpercrearne

unadaibordiarrotondatieimg-thumbnailperaggiungereunbordodoppio.

Page 248: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo61. Serviziopersonalizzato,$rootScope,controlleralivellodell’applicazione.2. value,serviceefactory.3. IlmodulongSanitize.4. Ilmetodocontrollerconsentealladirettivadicomunicareconlealtredirettive,

mentreilmetodolinkno.5. Ilsegno=significacheèpossibilelegaredirettamenteunmodello;@indicache

ladirettivautilizzeràilvaloreletteraledell’attributo.6. ImpostandolaproprietarestrictsuEM.7. Peraggiungerealcunefunzionihelperallabarradinavigazione.8. Utilizzando$index.

Page 249: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo71. DangAnimate.2. AngularMotion.3. bs-.4. click,hover,focusemanualmente.5. show,hideetoggle.

Page 250: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo81. Unapromise.2. Con$http.get(‘http://localhost:8000’).success(function(data){$scope.contacts=data

});.3. Sicomportacomeunsegnaposto.4. RESTAngularutilizzalepromiseenonènecessariotrascrivereisegnaposto

seguendoilpatternREST.5. Intemporeale.

Page 251: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo91. SuNode.2. PerindicareaNPMdiqualipacchettiabbiamobisogno.3. Uglify.4. Utilizzarelanotazionedegliarray.

Page 252: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo101. Variabili,mixineregoleannidate.2. Utilizzandoilpattern&:beforeoppure&:after.3. Modificandolavariabileinvariables.less.4. UsaglistilidiBootstrapperrenderlosimileaBootstrap2.

Page 253: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo111. Unaqualsiasidelleseguenti:required,ng-required,ng-pattern,ng-minlength,ng-

maxlength,ng-mineng-max.2. Verificandoleproprietà$valido$invalid.3. Chiamandolonellaproprietàrequire.4. Utilizzandong-pattern.

Page 254: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo121. Un’estensionediChromechecipermettediverificareleappdiAngularJS.2. Unodeiseguenti:Models,Performance,Dependencies,Inspector,

evidenziazionedelleapplicazioni,bindingescope.3. NellaschedaModelsdelwebinspectorselezionandoAngularJSProperties.4. ngMin.5. remove,addesingleQuotes.6. Lanecessitàdiannotaremanualmenteledipendenze.

Page 255: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Indice

Page 256: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Introduzione

Gliargomentidellibro

Checosaoccorreperillibro

Achisirivolgeillibro

Convenzioni

Scaricaifiledegliesempi

L’autore

Irevisori

Capitolo1-Hello,{{name}}

Impostazione

InstallazionediAngularJSeBootstrap

Quiz

Riepilogo

Capitolo2-SviluppareconAngularJSeBootstrap

Impostazione

Scaffolding

Quiz

Riepilogo

Capitolo3-Ifiltri

Applicareunfiltrodallavista

ApplicareifiltridaJavaScript

Sviluppareunfiltro

Quiz

Riepilogo

Page 257: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Capitolo4-Routing

InstallarengRoute

Creareroutedibase

Routeconparametri

Routedifallback

RoutinginHTML5oeliminazionedelsimbolo#

Collegareleroute

Quiz

Riepilogo

Capitolo5-Leviste

PopolarelavistaIndex

PopolarelavistaAddContact

PopolarelavistaViewContact

Quiz

Riepilogo

Capitolo6-CRUD

Read

Create

Update

Delete

Quiz

Riepilogo

Capitolo7-AngularStrap

InstallareAngularStrap

UtilizzareAngularStrap

UtilizzareiservizidiAngularStrap

IntegrareAngularStrap

Quiz

Page 258: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Riepilogo

Capitolo8-Connessionealserver

Connettersicon$http

ConnettersiconngResource

Sistemialternatividiconnessione

Quiz

Riepilogo

Capitolo9-Itaskrunner

InstallareNodeeNPM

UtilizzareGrunt

Utilizzaregulp

Riorganizzareilprogetto

Quiz

Riepilogo

Capitolo10-PersonalizzareBootstrap

CompilareLessconGruntogulp

Less

PersonalizzareglistilidiBootstrap

ItemidiBootstrap

DovetrovarealtritemidiBootstrap

Quiz

Riepilogo

Capitolo11-Validazione

Validazionedeiform

Quiz

Riepilogo

Capitolo12-Strumentidellacommunity

Batarang

Page 259: index-of.co.ukindex-of.co.uk/Programming/Stephen Radford - Sviluppare...Gli argomenti del libro Il Capitolo 1, “Hello, {{name}}”, esamina i fondamenti di AngularJS e Bootstrap

Verificareloscopeeleproprietà

ng-annotate

Quiz

Riepilogo

AppendiceA-Personeeprogetti

ProgettiepersonedietroBootstrap

ProgettiepersonedietroAngularJS

Oratoccaavoi…

AppendiceB-Incasodidubbio

Ladocumentazioneufficiale

L’issuetrackerdiGitHub

StackOverflow

IlgruppoGoogleAngularJS

Egghead.io

Twitter

AppendiceC-Risposteaiquiz

Capitolo1

Capitolo2

Capitolo3

Capitolo4

Capitolo5

Capitolo6

Capitolo7

Capitolo8

Capitolo9

Capitolo10

Capitolo11

Capitolo12