Duiken in CanJS deel 2

Dit is deel twee van een driedelige serie die u leert hoe u een applicatie voor contactbeheer in JavaScript bouwt met behulp van CanJS en jQuery. Als je klaar bent met deze tutorial, heb je alles wat je nodig hebt om je eigen JavaScript-applicaties te bouwen met CanJS!

In deel één hebt u de modellen, weergaven en bedieningselementen gemaakt die nodig zijn om contacten en gebruikte fixtures weer te geven om een ​​REST-service te simuleren.

In dit deel, zult u:

  • Maak een controle en weergave om categorieën weer te geven.
  • Luister naar gebeurtenissen met behulp van een besturingselement.
  • Gebruik routing om contacten te filteren.

Je zult vanaf het eerste deel aan de bronbestanden toevoegen, dus als je dat nog niet hebt gedaan, ga je eerst inhalen. Ik ben er als je klaar bent.


Routing instellen

Routing helpt bij het beheren van de browsergeschiedenis en de clientstatus in Javascript-toepassingen met één pagina.

Routing helpt bij het beheren van de browsergeschiedenis en de clientstatus in Javascript-toepassingen met één pagina. De hash in de URL bevat eigenschappen die een toepassing leest en schrijft. Verschillende delen van de app kunnen naar deze wijzigingen luisteren en dienovereenkomstig reageren, meestal delen van de huidige pagina bijwerken zonder een nieuwe te laden.

can.route is een speciale waarneembaar die updates en reageert op veranderingen in window.location.hash. Gebruik can.route om URL's toe te wijzen aan eigenschappen, wat resulteert in mooie URL's zoals #! Filter / all. Als er geen routes zijn gedefinieerd, wordt de hash-waarde gewoon geserialiseerd in URL-gecodeerde notatie zoals #! Categorie = all.

In deze toepassing wordt routering gebruikt om contactpersonen per categorie te filteren. Voeg de volgende code toe aan uw contacts.js het dossier:

 can.route ('filter /: category') can.route (", category: 'all')

De eerste regel maakt een route met een categorie eigenschap die uw toepassing kan lezen en schrijven. De tweede regel maakt een standaardroute, waarmee de categorie eigendom aan allemaal.


Werken met een lijst met modelinstanties

EEN Model.List is een waarneembare reeks modelinstanties. Wanneer u een definieert Model net zoals Contact, een Model.List voor dat type model wordt automatisch gemaakt. We kunnen dit gecreëerd uitbreiden Model.List om helperfuncties toe te voegen die werken op een lijst met modelinstanties.

Contactlijst heeft twee hulpfuncties nodig om een ​​lijst met contacten te filteren en te rapporteren hoeveel contactpersonen er in elke categorie zijn. Voeg dit toe aan contacts.js onmiddellijk na de Contact model:

 Contact.List = can.Model.List (filter: function (category) this.attr ('length'); var contacts = new Contact.List ([]); this.each (function (contact, i)  if (category === 'all' || category === contact.attr ('category')) contacts.push (contact)) terug contacten;, tel: functie (categorie) retourneer dit.filter (categorie) .length;);

De twee hulpfuncties hier zijn:

  • filter() doorloopt elk contact in de lijst en geeft een nieuw antwoord Contactlijst van contacten binnen een categorie. this.attr ( 'lengte') is hier opgenomen, dus EJS zal live-binding instellen wanneer we deze helper gebruiken in een weergave.
  • telling () retourneert het aantal contactpersonen in een categorie met behulp van de filter() helperfunctie. Omdat this.attr ( 'lengte') in filter(), EJS zal live-binding instellen wanneer we deze helper gebruiken in een weergave.

Gebruik als u een helper in EJS gebruikt attr () op een lijst- of instantie-eigenschap om live binding in te stellen.


Contactpersonen filteren

Vervolgens wijzigt u de contactsList.ejs weergave om contacten te filteren op basis van de categorie-eigenschap in de hash. In de contactsList.ejs weergave, wijzigt u de parameter die is doorgegeven aan de lijst() helper aan contacts.filter (can.route.attr ( 'categorie')). Uw EJS-bestand zou er als volgt uit moeten zien:

 
    <% list(contacts.filter(can.route.attr('category')), function(contact) %>
  • el.data ('contact', contact)% >>
    <%== can.view.render('contactView', contact: contact, categories: categories) %>
  • <% ) %>

Op regel twee, filter() wordt aangeroepen met de huidige categorie uit can.route. Omdat je het hebt gebruikt attr () in filter() en verder can.route, EJS stelt Live-binding in om uw gebruikersinterface opnieuw te renderen wanneer een van deze wijzigingen wordt gewijzigd.

Inmiddels zou duidelijk moeten zijn hoe krachtig live-binding is. Met een kleine aanpassing aan uw mening, wordt de gebruikersinterface van de app nu volledig gesynchroniseerd met niet alleen de lijst met contacten, maar ook met de categorie-eigenschap die in de route is gedefinieerd.


Categorieën weergeven

Contacten worden gefilterd wanneer de categorie-eigenschap in de hash wordt gewijzigd. Nu heb je een manier nodig om alle beschikbare categorieën op te sommen en de hash te veranderen.

Maak eerst een nieuwe weergave om een ​​lijst met categorieën weer te geven. Sla deze code op als filterView.ejs in uw keer bekeken map:

 
  • Categorieën
  • Allemaal (<%= contacts.count('all') %>)
  • <% $.each(categories, function(i, category) %>
  • "><%= category.name %> (<%= contacts.count(category.data) %>)
  • <% ) %>

Laten we een paar regels uit deze code bekijken en zien wat ze doen:

 <% $.each(categories, function(i, category) %>

$ .each doorloopt de categorieën en voert een callback uit voor elke categorie.

 "><%= category.name %> (<%= contacts.count(category.data) %>

Elke link heeft een data-categorie attribuut dat in het data-object van jQuery zal worden getrokken. Later is deze waarde toegankelijk via .data ( 'categorie') op de label. De naam en het aantal contacten van de categorie worden gebruikt als de koppelingstest. Live binding is ingesteld op het aantal contacten omdat telling () calls filter() welke bevat this.attr ( 'lengte').


Luisteren naar gebeurtenissen met can.Control

Control bindt automatisch methoden die eruitzien als gebeurtenishandlers wanneer een instantie wordt gemaakt. Het eerste deel van de gebeurtenishandler is de selector en het tweede deel is de gebeurtenis waarnaar u wilt luisteren. De selector kan elke geldige CSS-selector zijn en de gebeurtenis kan elke willekeurige DOM-gebeurtenis of aangepaste gebeurtenis zijn. Dus een functie zoals 'een klik' zal luisteren naar een klik op een willekeurige tag binnen het element van de controle.

Controle maakt gebruik van delegatie van gebeurtenissen, zodat u zich geen zorgen hoeft te maken over het opnieuw koppelen van gebeurtenishandlers wanneer de DOM verandert.


Categorieën weergeven

Maak de besturing waarmee categorieën worden beheerd door deze code toe te voegen aan contacts.js direct na de Contacten Controle:

 Filter = can.Control (init: function () var category = can.route.attr ('category') || "all"; this.element.html (can.view ('filterView', contacts: this .options.contacts, categories: this.options.categories)); this.element.find ('[data-categorie = "' + categorie + '"]') parent (). addClass ('actief'); , '[data-categorie] klik': functie (el, ev) this.element.find ('[data-categorie]'). parent (). removeClass ('active'); el.parent (). addClass ('actief'); can.route.attr ('categorie', el.data ('categorie')););

Laten we de code bekijken van het 'Filter' besturingselement dat u zojuist hebt gemaakt:

 this.element.html (can.view ('filterView', contacts: this.options.contacts, categories: this.options.categories));

Zoals in de Contacten Controle, in het() toepassingen kan zien() om categorieën en weer te geven html () om het in te voegen in het element van de Control.

 this.element.find ('[data-categorie = "' + categorie + '"]') parent (). addClass ('actief');

Zoekt de koppeling die overeenkomt met de huidige categorie en voegt een klasse van 'actief' toe aan het bovenliggende element.

 '[data-categorie] klik': functie (el, ev) 

Luistert naar a Klik gebeurtenis op elk element dat overeenkomt met de selector [Data-categorie].

 . This.element.find ([data-categorie]) ouder () removeClass ( 'actief').; . El.parent () addClass ( 'actief');

Verwijdert de 'actieve' klasse uit alle links en voegt een klasse van 'actief' toe aan de link waarop is geklikt.

 can.route.attr ('categorie', el.data ('categorie'));

Hiermee wordt de categorie-eigenschap bijgewerkt in can.route de waarde uit het data-object van jQuery gebruiken voor de waarop is geklikt.


Initialiseren van het filterbeheer

Net als de Contacten Controle in deel een, je moet een nieuw exemplaar van de Filter Controle. Werk uw documentklare functie bij om er als volgt uit te zien:

 $ (document) .ready (function () $ .when (Category.findAll (), Contact.findAll ()). then (function (categoryResponse, contactResponse) var categories = categoryResponse [0], contacts = contactResponse [0 ]; nieuwe Contacten ('# contacten', contacten: contacten, categorieën: categorieën); nieuw Filter ('# filter', contacten: contacten, categorieën: categorieën););)

Met deze wijziging wordt een instantie van de Filter Controle zal worden gemaakt op de #filter element. Het wordt de lijst met contactpersonen en categorieën doorgegeven.

Wanneer u nu uw toepassing in een browser uitvoert, kunt u contactpersonen filteren door op de categorieën aan de rechterkant te klikken:


Afsluiten

Dat is alles voor deel twee! Dit is wat we hebben bereikt:

  • Creëerde een controle die naar gebeurtenissen luistert en categorieën beheert
  • Stel routing in om contacten per categorie te filteren
  • Tweemaal uw weergaven aangepast, zodat live-binding uw gehele gebruikersinterface synchroniseert met uw gegevenslaag

In deel drie, zult u uw bestaande besturingselementen bijwerken zodat contacten kunnen worden bewerkt en verwijderd. Je zult ook een nieuwe controle en weergave maken waarmee je nieuwe contacten kunt toevoegen.

Kan niet wachten om meer te leren? Deel drie van de serie is hier geplaatst!