Velkommen til del tre av serien vår som fokuserer på å bygge applikasjoner ved hjelp av Backbone. Hvis du ikke har lest deler ett og to, anbefaler jeg på det sterkeste at du gjør det - bare slik at du vet hvor vi er og hva vi har dekket så langt.
I første del tok vi et grunnleggende utseende og modeller, synspunkter og samlinger. I del to så vi på rutere, hendelser og historikkmodulene. I denne delen skal vi se nærmere på samspill og se hvordan vi kan legge til eller fjerne modeller fra en samling.
Hvis du gjemmer deg tilbake til første del, husker du hvordan vi har lagt til alle våre modeller i samlingen når samlingen ble initialisert. Men hvordan kan vi legge til individuelle modeller i en samling etter at samlingen allerede er initialisert? Det er faktisk veldig enkelt.
Vi legger til muligheten for nye kontakter å bli lagt til som vil innebære en oppdatering til den underliggende HTML og vår hovedvisning. Først, HTML; legg til følgende mark-up i kontaktbeholderen:
Denne enkle skjemaet gjør det mulig for brukere å legge til en ny kontakt. Hovedpoenget er at id
attributter av elementene samsvarer med attributtnavnene som brukes av våre modeller, noe som gjør det lettere å få dataene i det formatet vi ønsker.
Deretter kan vi legge til en hendelsesbehandler i vårt hovedvisning slik at dataene i skjemaet kan høstes; legg til følgende kode etter den eksisterende nøkkelen: verdi par i arrangementer
gjenstand:
"klikk #add": "addContact"
Ikke glem å legge til kommende komma til slutten av den eksisterende bindingen! Denne gangen angir vi klikk
hendelsen utløst av elementet med en id
av Legg til
, som er knappen på skjemaet vårt. Handler vi er bindende til denne hendelsen er Legg til kontakt
, som vi kan legge til neste. Legg til følgende kode etter filterByType ()
metode fra del to:
addContact: funksjon (e) e.preventDefault (); var newModel = ; $ ("# addContact"). barn ("input"). hver (funksjon (i, el) if ($ (el) .val ()! == "") newModel [el.id] = $ el) .val ();); contacts.push (formData); hvis (_.indexOf (this.getTypes (), formData.type) === -1) this.collection.add (ny kontakt (formData)); dette $ el.find ( "# filter") finne ( "select") fjern () end () føyer (this.createSelect ()).....; ellers this.collection.add (ny kontakt (formData));
Siden dette er en hendelseshåndterer, mottar den automatisk begivenhet
objekt, som vi kan bruke for å forhindre standard oppførsel av element når det klikkes (som ville være å sende skjemaet og laste siden på nytt - ikke det vi vil). Vi lager deretter en ny tom objekt, og bruker jQuery's
Hver()
metode for å iterere over hver element i vår
Legg til kontakt
skjema.
I tilbakeringingsfunksjonen som leveres til Hver()
, Vi kontrollerer først at feltet har fått tekst inn i det, og i så tilfelle legger vi til en ny egenskap i objektet med en nøkkel som er lik den id
av det nåværende elementet, og en verdi som er lik den aktuelle verdi
. Hvis feltet er tomt, vil eiendommen ikke bli satt, og den nye modellen vil arve noen standardverdier som kan ha blitt angitt.
Deretter kan vi oppdatere vår lokale datalager med den nye kontakten. Det er her vi sannsynligvis vil lagre de nye dataene til serveren - hvis vi hadde en server på plass for å motta slike forespørsler. På dette tidspunktet gjør vi det ikke, så vi oppdaterer bare den opprinnelige gruppen for nå, slik at hvis visningen blir filtrert, går de nye dataene ikke tapt. Alt vi trenger å gjøre er å bruke samlingen er Legg til()
metode for å legge til de nye dataene i samlingen. Vi kan lage den nye modellen for å passere inn i samlingen innen samtalen til Legg til()
.
Til slutt må vi oppdatere element slik at hvis den nye kontakten har en annen type, er den typen tilgjengelig for filtrering. Vi vil imidlertid bare gjenta
hvis en ny type er lagt til. Vi kan bruke Underscore's
oversikt over()
metode for å søke gjennom en matrise for en bestemt verdi. Som den innfødte JavaScript oversikt over()
Metode for strenger, denne metoden kommer tilbake -1
hvis verdien ikke er funnet. Vi sender matrisen for å søke som det første argumentet til oversikt over()
, og verdien å se etter som den andre.
Hvis verdien ikke er funnet, må den oppgitte typen være ny, slik at vi finner den eksisterende valgboksen og fjerner den før du legger til en ny generert av vår createSelect ()
metode. Hvis typen er funnet, kan vi bare legge til den nye modellen uten å måtte gjenta valget.
Nå som vi har lagt til en ny modell i samlingen, bør vi gjøre det på siden. For å gjøre dette kan vi binde en annen handler, denne gangen for å lytte etter Legg til
begivenhet. Legg til følgende linje med kode til initialize ()
metode for samlingen:
this.collection.on ("add", this.renderContact, dette);
Vi bruker på()
metode igjen for å knytte hendelseslytteren og som vi allerede har en metode som lager og viser individuelle visninger, angir vi bare den funksjonen som handler. Vi stiller også hovedvisningen som dette objektet i handleren som vi gjorde med tidligere håndtere. På dette tidspunktet bør vi nå kunne fylle ut skjemaet, og få den nye kontakten gjengitt til siden:
En ting å merke seg er at hvis Legg til kontakt
Skjemafeltene blir helt tomme, den resulterende modellen vil nesten ikke være helt uten egenskaper, noe som vil føre til problemer når vi prøver å manipulere modellen senere. En måte å unngå dette på er å angi standard for de fleste modellattributter, akkurat som vi ga standard bilde
Egenskap. Hvis det ikke finnes noen fornuftige standardverdier som vi kan bruke, som for eksempel et navn til en kontakt, kan vi bare levere en tom streng. Oppdater mislighold
objekt i Ta kontakt med
klasse for å inkludere standardverdier for våre andre attributter:
navn: "", adresse: "", tlf: "", epost: "", skriv: ""
Nå som vi vet hvordan å legge til modeller i samlingen, bør vi se på hvordan de også kan fjernes. En måte at vi kunne aktivere sletting av individuelle modeller, er ved å legge til en sletteknapp for hver kontakt, så dette er hva vi skal gjøre; Først må vi oppdatere malen for hver enkelt visning slik at den inneholder en sletteknapp. Legg til en ny knapp til slutten av malen:
Det er alt vi trenger for dette eksemplet. Logikken for å fjerne en individuell modell kan legges til visningsklassen som representerer en individuell kontakt, siden visningseksemplet vil være knyttet til en bestemt modelleksempel. Vi må legge til en hendelsesbinding og en hendelseshåndterer for å fjerne modellen når knappen klikkes. legg til følgende kode til slutten av ContactView
klasse:
hendelser: "click button.delete": "deleteContact", deleteContact: function () var removedType = this.model.get ("type"). toLowerCase (); this.model.destroy (); this.remove (); hvis (_.indexOf (directory.getTypes (), removedType) === -1) katalog. $ el.find ("# filter select"). barn ("[value = '" + removedType + "']" ).fjerne();
Vi bruker arrangementer
motsette seg å spesifisere vår hendelse bindende, som vi gjorde før med vår mestervisning. Denne gangen lytter vi etter klikk
hendelser utløst av a som har klassenavnet
slette
. Handler bundet til denne hendelsen er deleteContact
, som vi legger til etter arrangementer
gjenstand.
Først lagrer vi typen kontakt som vi nettopp slettet. Vi bør gjøre denne verdien små bokstaver som vi gjorde før for å sikre at det ikke er noen tilfelleproblemer når kontaktviseren er i bruk.
Vi kaller da ødelegge()
metode på modellen assosiert med dette
, forekomsten av visningen. Vi kan også fjerne HTML-representasjonen for visningen fra siden ved å ringe til jQuery's fjerne()
metode, som har den ekstra bonusen til å rydde opp eventuelle hendelseshåndterere som er knyttet til visningen.
Til slutt får vi alle typer modellene i katalogsamlingen og kontrollerer for å se om typen av kontakten som nettopp ble fjernet, fremdeles finnes i den resulterende matrisen. Hvis det ikke er det, er det ikke flere kontakter av den typen, og vi bør derfor fjerne dette alternativet fra valget.
Vi velger elementet som skal fjernes ved først å finne markeringsboksen, og deretter bruke en attributtvelger for å velge med en verdiattributt som samsvarer med
removedType
variabel som vi lagret ved starten av metoden. Hvis vi fjerner alle kontaktene til en bestemt type, og deretter sjekker du element, bør vi finne at typen ikke lenger er i rullegardinmenyen:
Ok, den underposisjonen er litt misvisende; Det jeg mener er det så vel som å fjerne modellen og visningen, bør vi også fjerne de opprinnelige dataene i vår kontaktgruppe som modellen ble opprinnelig bygget fra. Hvis vi ikke gjør dette, vil modellen som ble fjernet, komme tilbake når den er filtrert. I en virkelig applikasjon er dette sannsynligvis hvor vi skulle synkronisere med en sever for å fortsette dataene.
Funksjonaliteten for å fjerne elementet fra den opprinnelige gruppen kan være innenfor vår hovedvisning; samlingen vil brenne a fjerne
hendelse når noen av modellene er fjernet fra samlingen, så vi kan bare binde en handler for denne hendelsen til samlingen i hovedvisningen. Legg til følgende linje av kode direkte etter eksisterende bindinger:
this.collection.on ("remove", this.removeKontakt, dette);
Du bør være ganske kjent med denne utsagnet nå, men som en påminnelse, det første argumentet til på()
Metoden er hendelsen vi lytter etter, den andre er håndtereren som skal utføres når hendelsen oppstår, og den tredje er konteksten som skal brukes som dette når håndteringen utføres. Deretter kan vi legge til fjern Kontakt()
metode; etter Legg til kontakt()
metode legg til følgende kode:
removeContact: funksjon (removedModel) var fjernet = fjernetModel.attributes; hvis (removed.photo === "/img/placeholder.png") delete removed.photo; _.each (kontakter, funksjon (kontakt) hvis (_.isEqual (kontakt, fjernet)) contacts.splice (_. indexOf (kontakter, kontakt), 1););
Backbone passerer passivt vår håndterer modellen som nettopp er fjernet fra samlingen. Vi lagrer en referanse til samlingen av attributter, slik at vi kan sammenligne modellen som har blitt fjernet med elementene i vår originale kontaktarray. De originale elementene i kontaktlisten har ikke definert bildeegenskapen, men da dette er angitt som en standardegenskap, vil alle våre modeller arve eiendommen og vil derfor mislykkes noen sammenligning med objektene i kontaktlisten.
I dette eksemplet må vi sjekke om bilde
Egenskapen til modellen er den samme som standardverdien, og hvis den er, fjerner vi bilde
eiendom.
Når dette er gjort kan vi iterere over hvert element i kontakter
array og test det for å se om det er det samme som modellen som ble fjernet fra samlingen. Vi kan sammenligne hvert element med objektet vi lagrer i den fjernede variabelen ved hjelp av Underscore er lik()
metode.
Hvis er lik()
Metoden returnerer sann, vi kaller deretter den innfødte JavaScript spleise ()
metode på kontakter
array, passerer i indeksen for elementet som skal fjernes, og antall elementer som skal fjernes. Indeksen er oppnådd ved hjelp av Underscore's oversikt over()
metode som vi brukte tidligere på.
Nå når en sletteknapp klikkes, blir visningen, modellen og originaldata slettet fra eksistensen. Vi kan også filtrere visningen og deretter gå tilbake til visningen av alle kontakter, og kontakten som ble fjernet, vil fortsatt ikke bli vist.
Så, vi bare dumpet Legg til kontakt
skjema på siden der gjorde vi ikke? For å lukke denne delen av opplæringen, kan vi gjøre noe for å holde det skjult til en link er klikket. Vi kan legge til følgende lenke til element:
Legg til ny kontakt
For å få linken til å vise skjemaet, må vi gjemme det først og deretter bruke en brukerhåndterer til å vise hendelsen. Bindingen kan legges til arrangementer
objekt i DirectoryView
klasse:
"klikk #showForm": "showForm"
Våre showForm ()
Metoden kan være så enkel som følger (selv om du sikkert vil gjøre litt mer med det enn vi gjør her!):
showForm: function () this. $ el.find ("# addContact"). slideToggle ();
I denne opplæringen så vi utelukkende på hvordan nye modeller kan legges til en samling og hvordan modeller kan fjernes fra en samling. Vi så at Backbone-metodene som brukes til å legge til og fjerne modeller, ikke overraskende er Legg til()
og fjerne()
fremgangsmåter.
Vi så også hvordan vi kan binde håndtere til hendelsene som sparkes automatisk når disse metodene brukes for å oppdatere brukergrensesnittet og samlingen etter behov.
Vi så også på noen mer nyttige Underscore verktøyfunksjoner som vi kan bruke til å jobbe med våre data, inkludert _oversikt over()
som returnerer den indeksen for et element i en matrise, og er lik()
som kan brukes til å sammenligne to objekter for å se om de er identiske.
Som i den siste delen av denne opplæringen så vi også hvordan vi kan skrive våre klasser på en slik måte at deres funksjonalitet kan deles og gjenbrukes når det er mulig. Da vi tilførte en ny modell, brukte vi for eksempel den eksisterende renderContact ()
metode definert i vår DirectoryView
klasse for å håndtere gjengivelsen av HTML for den nye kontakten.
Så vi har sett hvordan å legge til modeller og fjerne dem, bli med i neste del av denne serien der vi skal se på hvordan du redigerer eksisterende modelldata.