Welkom bij deel drie van onze serie die zich richt op het bouwen van applicaties met behulp van Backbone. Als je delen één en twee niet hebt gelezen, raad ik je ten zeerste aan om dat te doen - zodat je weet waar we nu zijn en wat we tot nu toe hebben behandeld.
In deel één hebben we een basislook en -modellen, weergaven en collecties gemaakt. In deel twee hebben we gekeken naar routers, evenementen en de history-modules. In dit deel gaan we verder kijken naar interacties en kijken we hoe we modellen uit een verzameling kunnen toevoegen of verwijderen.
Als je terugdenkt aan deel een, weet je nog hoe we al onze modellen aan de verzameling hebben toegevoegd toen de verzameling werd geïnitialiseerd. Maar hoe kunnen we afzonderlijke modellen toevoegen aan een verzameling nadat de verzameling al is geïnitialiseerd? Het is eigenlijk heel gemakkelijk.
We voegen de mogelijkheid toe om nieuwe contacten toe te voegen die een update van de onderliggende HTML en onze hoofdweergave met zich meebrengen. Ten eerste de HTML; voeg de volgende markering toe aan de contactcontainer:
Met dit eenvoudige formulier kunnen gebruikers een nieuw contact toevoegen. Het belangrijkste punt is dat de ID kaart
attributess van de elementen komen overeen met de kenmerknamen die door onze modellen worden gebruikt, waardoor het gemakkelijker wordt om de gegevens in de gewenste indeling te krijgen.
Vervolgens kunnen we een gebeurtenishandler toevoegen aan onze hoofdweergave, zodat de gegevens in het formulier kunnen worden geoogst; voeg de volgende code toe na de bestaande sleutel: waardepaar in de events
voorwerp:
"klik #add": "addContact"
Vergeet niet om de achterliggende komma toe te voegen aan het einde van de bestaande binding! Deze keer specificeren we de Klik
gebeurtenis geactiveerd door het element met een ID kaart
van toevoegen
, welke is de knop op ons formulier. De handler die we binden aan deze gebeurtenis is Cont.persToev
, welke we vervolgens kunnen toevoegen. Voeg de volgende code toe na de filterByType ()
methode van deel twee:
addContact: function (e) e.preventDefault (); var newModel = ; $ ("# addContact"). children ("input"). each (functie (i, el) if ($ (el) .val ()! == "") newModel [el.id] = $ ( el) .val ();); contacts.push (formdata); if (_.indexOf (this.getTypes (), formData.type) === -1) this.collection.add (new Contact (formData)); dit $ el.find ( "# filter") te vinden ( "select") Verwijderen () end () toevoegen (this.createSelect ()).....; else this.collection.add (nieuw Contact (formData));
Omdat dit een gebeurtenishandler is, ontvangt deze automatisch de evenement
object, die we kunnen gebruiken om het standaardgedrag van de element wanneer erop wordt geklikt (wat zou zijn om het formulier in te dienen en de pagina opnieuw te laden - niet wat we willen). Vervolgens maken we een nieuw leeg object en gebruiken we jQuery's
elk()
methode om over elk te itereren element in onze
Cont.persToev
het formulier.
In de callback-functie geleverd aan elk()
, we controleren eerst of er in het veld tekst is ingevoerd en als dat zo is, voegen we een nieuwe eigenschap toe aan het object met een sleutel die gelijk is aan de ID kaart
van het huidige element en een waarde die gelijk is aan de huidige waarde
. Als het veld leeg is, wordt de eigenschap niet ingesteld en neemt het nieuwe model alle standaardwaarden over die zijn opgegeven.
Vervolgens kunnen we onze lokale gegevensopslag bijwerken met de nieuwe contactpersoon. Dit is waar we waarschijnlijk de nieuwe gegevens op de server zouden opslaan - als we een server hadden om zulke verzoeken te ontvangen. Op dit moment doen we dat niet, dus we zullen de originele array nu net bijwerken, zodat als de weergave wordt gefilterd, de nieuwe gegevens niet verloren gaan. Het enige dat we dan moeten doen is gebruik maken van de collectie's toevoegen()
methode om de nieuwe gegevens aan de verzameling toe te voegen. We kunnen het nieuwe model maken om binnen de oproep door te geven aan de verzameling toevoegen()
.
Ten slotte moeten we het element zodat als het nieuwe contact een ander type heeft, dat type beschikbaar is om te filteren. We willen echter alleen het. Opnieuw renderen
als een nieuw type is toegevoegd. We kunnen Underscore's gebruiken
index van()
methode om voor een bepaalde waarde door een array te zoeken. Net als het native JavaScript index van()
methode voor strings, deze methode zal terugkeren -1
als de waarde niet wordt gevonden. We geven de array door om te zoeken als het eerste argument voor index van()
, en de waarde waarnaar moet worden gezocht als de tweede.
Als de waarde niet wordt gevonden, moet het opgegeven type nieuw zijn, zodat we het bestaande selectievak vinden en verwijderen voordat een nieuwe wordt toegevoegd die is gegenereerd door onze createSelect ()
methode. Als het type wordt gevonden, kunnen we het nieuwe model gewoon toevoegen zonder de selectie opnieuw te renderen.
Nu we een nieuw model aan de verzameling hebben toegevoegd, moeten we dit op de pagina weergeven. Om dit te doen kunnen we een andere handler binden, deze keer om te luisteren naar de toevoegen
evenement. Voeg de volgende regel code toe aan de initialiseren ()
methode van de verzameling:
this.collection.on ("add", this.renderContact, this);
Wij gebruiken de op()
methode om de gebeurtenislistener opnieuw te koppelen en omdat we al een methode hebben waarmee we individuele weergaven maken en weergeven, specificeren we die functie als de handler. We stellen ook de hoofdweergave in als dit object binnen de handler, net als bij eerdere handlers. Op dit punt moeten we nu het formulier kunnen invullen en de nieuwe contactpersoon kunnen laten weergeven op de pagina:
Een ding om op te merken is dat als het Cont.persToev
formuliervelden worden volledig leeg gelaten, het resulterende model zal bijna volledig ontdaan zijn van attributen, wat problemen zal veroorzaken wanneer we het model later proberen te manipuleren. Een manier om dit te voorkomen, is standaardwaarden voor de meeste modelattributen te bieden, net zoals we de standaard hebben opgegeven foto
attribuut. Als er geen verstandige standaardwaarden zijn die we kunnen gebruiken, zoals voor de naam van een contact, kunnen we gewoon een lege string leveren. Werk het defaults
object in de Contact
klasse om standaardinstellingen voor onze andere kenmerken op te nemen:
name: "", adres: "", tel: "", email: "", type: ""
Nu we weten hoe we modellen aan de collectie kunnen toevoegen, moeten we kijken hoe ze ook kunnen worden verwijderd. Een manier om afzonderlijke modellen te verwijderen, is door een verwijderknop aan elke contactpersoon toe te voegen, dus dit is wat we zullen doen; eerst moeten we de sjabloon bijwerken voor elke afzonderlijke weergave, zodat deze een verwijderknop bevat. Voeg een nieuwe knop toe aan het einde van de sjabloon:
Dat is alles wat we nodig hebben voor dit voorbeeld. De logica om een afzonderlijk model te verwijderen, kan worden toegevoegd aan de weergaveklasse die een afzonderlijk contact vertegenwoordigt, omdat de view-instantie aan een bepaald modelexemplaar wordt gekoppeld. We moeten een gebeurtenisbinding en een gebeurtenishandler toevoegen om het model te verwijderen wanneer op de knop wordt geklikt; voeg de volgende code toe aan het einde van de ContactView
klasse:
evenementen: "klik button.delete": "deleteContact", deleteContact: function () var removedType = this.model.get ("type"). toLowerCase (); this.model.destroy (); this.remove (); if (_.indexOf (directory.getTypes (), removedType) === -1) directory. $ el.find ("# filter selecteren"). children ("[value = '" + removedType + "']" ).verwijderen();
Wij gebruiken de events
object om onze gebeurtenisbinding te specificeren, zoals we eerder deden met onze hoofdweergave. Deze keer luisteren we naar Klik
evenementen geactiveerd door een dat heeft de klassenaam
verwijderen
. De handler die aan deze gebeurtenis is gebonden, is Verwijder contact
, die we toevoegen na de events
voorwerp.
Eerst slaan we het type contact op dat we zojuist hebben verwijderd. We zouden deze waarde in kleine letters moeten plaatsen zoals we eerder deden om ervoor te zorgen dat er geen probleemgevallen zijn wanneer de contactviewer in gebruik is.
We noemen dan de vernietigen()
methode op het model geassocieerd met deze
, de instantie van het uitzicht. We kunnen ook de HTML-weergave van de weergave van de pagina verwijderen door jQuery's aan te roepen verwijderen()
methode, die de toegevoegde bonus heeft bij het opschonen van eventhandlers die aan de weergave zijn gekoppeld.
Ten slotte krijgen we alle typen modellen in de directoryverzameling en controleren we of het type contact dat zojuist is verwijderd zich nog steeds in de resulterende array bevindt. Als dit niet het geval is, zijn er geen contacten meer van dat type en daarom moeten we die optie uit de selectie verwijderen.
We selecteren het element dat moet worden verwijderd door eerst het selectievak te vinden en vervolgens een attribuutselector te gebruiken om het te selecteren met een waardeattribuut dat overeenkomt met het
removedType
variabele die we hebben opgeslagen aan het begin van de methode. Als we alle contactpersonen van een bepaald type verwijderen en dan de element, moeten we vaststellen dat het type niet langer in de vervolgkeuzelijst staat:
Ok, die subtitel is een beetje misleidend; Wat ik bedoel is dat we naast het verwijderen van het model en de weergave ook de originele gegevens in onze matrix met contactpersonen moeten verwijderen waarvan het model oorspronkelijk is gemaakt. Als we dit niet doen, komt het verwijderde model terug wanneer het wordt gefilterd. In een real-world applicatie is dit waarschijnlijk waar we zouden synchroniseren met een sever om de data aan te houden.
De functionaliteit om het item uit de oorspronkelijke array te verwijderen, kan zich binnen onze hoofdweergave bevinden; de verzameling vuurt een a verwijderen
gebeurtenis wanneer een van de modellen uit de verzameling wordt verwijderd, zodat we eenvoudigweg een handler voor deze gebeurtenis kunnen binden aan de verzameling in de hoofdweergave. Voeg de volgende regel code direct toe na de bestaande bindingen:
this.collection.on ("remove", this.removeContact, this);
Je zou nu behoorlijk bekend moeten zijn met deze verklaring, maar ter herinnering, het eerste argument van de op()
methode is de gebeurtenis waar we naar luisteren, de tweede is de handler die moet worden uitgevoerd wanneer de gebeurtenis plaatsvindt, en de derde is de context die moet worden gebruikt wanneer de handler wordt uitgevoerd. Vervolgens kunnen we de Contact verwijderen()
methode; na de Cont.persToev ()
methode voeg de volgende code toe:
removeContact: function (removedModel) var removed = removedModel.attributes; if (removed.photo === "/img/placeholder.png") delete removed.photo; _.each (contacten, functie (contact) if (_.isEqual (contact, removed)) contacts.splice (_. indexOf (contacten, contact), 1););
Backbone geeft onze handler het model dat zojuist uit de collectie is verwijderd, handig door. We slaan een verwijzing naar de verzameling attributen op, zodat we het model dat is verwijderd kunnen vergelijken met de items in onze oorspronkelijke reeks contacten. De oorspronkelijke items in de matrix met contactpersonen hebben de eigenschap photo niet gedefinieerd, maar omdat dit wordt opgegeven als een standaardeigenschap, nemen al onze modellen de eigenschap over en mislukken daarom elke vergelijking met de objecten in de matrix met contactpersonen.
In dit voorbeeld moeten we controleren of het foto
eigenschap van het model is hetzelfde als de standaardwaarde, en als dit het geval is, verwijderen we de foto
eigendom.
Zodra dit is gebeurd, kunnen we elk item in de contacten
array en test deze om te zien of deze gelijk is aan het model dat uit de verzameling is verwijderd. We kunnen elk item vergelijken met het object dat we in de verwijderde variabele opslaan met behulp van Underscore's is gelijk()
methode.
Als het is gelijk()
methode retourneert waar, we bellen vervolgens het native JavaScript splice ()
methode op de contacten
array, waarbij de index wordt doorgegeven van het item dat moet worden verwijderd en het aantal items dat moet worden verwijderd. De index wordt verkregen met behulp van Underscore's index van()
methode die we eerder hebben gebruikt.
Wanneer nu op een verwijderknop wordt geklikt, worden de weergave, het model en de originele gegevens uit het bestaan gewist. We kunnen ook de weergave filteren en vervolgens teruggaan naar de weergave van alle contacten. Het contact dat werd verwijderd, wordt nog steeds niet weergegeven.
Dus we hebben zojuist de Cont.persToev
vorm op de pagina daar, nietwaar? Om dit deel van de tutorial af te sluiten, kunnen we iets doen om het verborgen te houden totdat op een link wordt geklikt. We kunnen de volgende link toevoegen aan de element:
Voeg nieuw contact toe
Als u wilt dat de koppeling het formulier weergeeft, moeten we dit eerst verbergen en vervolgens een gebruikershandler voor gebruikersinterfaces gebruiken om het weer te geven. De binding kan worden toegevoegd aan de events
object in de DirectoryView
klasse:
"klik op #showForm": "showForm"
Onze showForm ()
methode kan zo simpel zijn als volgt (hoewel je er waarschijnlijk iets meer mee wilt doen dan hier!):
showForm: function () this. $ el.find ("# addContact"). slideToggle ();
In deze zelfstudie hebben we alleen gekeken naar hoe nieuwe modellen kunnen worden toegevoegd aan een verzameling en hoe modellen uit een verzameling kunnen worden verwijderd. We hebben gezien dat de Backbone-methoden die worden gebruikt om modellen toe te voegen en te verwijderen,, niet verwonderlijk, de toevoegen()
en verwijderen()
methoden.
We hebben ook gezien hoe we handlers kunnen koppelen aan gebeurtenissen die automatisch worden geactiveerd wanneer deze methoden worden gebruikt om de gebruikersinterface en verzameling zo nodig bij te werken.
We hebben ook gekeken naar enkele meer nuttige Underscore-hulpprogramma's die we kunnen gebruiken om met onze gegevens te werken, inclusief _index van()
die de index van een item in een array retourneert, en is gelijk()
die kan worden gebruikt om twee objecten diep te vergelijken om te zien of ze identiek zijn.
Net als in het laatste deel van deze tutorial hebben we ook gezien hoe onze klassen zo kunnen schrijven dat hun functionaliteit waar mogelijk kan worden gedeeld en hergebruikt. Toen we bijvoorbeeld een nieuw model toevoegden, hebben we gebruik gemaakt van het bestaande renderContact ()
methode gedefinieerd in onze DirectoryView
klasse om de HTML-weergave voor de nieuwe contactpersoon af te handelen.
Dus we hebben gezien hoe modellen kunnen worden toegevoegd en verwijderd, neem deel aan het volgende deel van deze serie, waarin we kijken hoe bestaande modelgegevens kunnen worden bewerkt.