Partager via


Cet article a fait l'objet d'une traduction automatique.

JavaScript

Liaison de données dans une Application du Windows Store avec JavaScript

Chris Sells
Brandon Satrom

Télécharger l'exemple de code

Dans cet article, nous explorerons la liaison de données dans une application Windows Store construite avec JavaScript.Il s'agit d'un hybride d'autres types d'applications construites pour Windows 8.C'est comme une application de bureau car il est installé sur votre ordinateur, contrairement à un site Web.En revanche, c'est comme un site Web que vous pouvez créer à l'aide d'HTML5, JavaScript et CSS3.Toutefois, au lieu de générer l'interface utilisateur côté serveur, le framework JavaScript pour la création d'applications Windows Store et le Runtime Windows sous-jacent permet à vous créer des applications avec état côté client, stockage hors connexion, commandes, modèles et liaison — ainsi qu'une foule d'autres services.

Liaison de données est la capacité à prendre de la valeur d'une liste de données, tels qu'un ensemble de flux RSS et utilisez-la pour remplir un contrôle, tel qu'un contrôle ListView.Nous pouvons personnaliser quelles données nous avons extrait à l'aide de modèles.Nous allons montrer comment la liaison est encore plus souple que celle, ce qui permet la mise à jour de l'interface utilisateur, comme les modifications des données sous-jacentes, ainsi que le tri, le filtrage et le regroupement.

Quand on utilise la liaison de données, il est souvent dans le cadre d'un contrôle.Nous allons jeter un oeil à la ListView et prenant en charge la liaison de données et modèles.

101 De liaison de données

L'utilisation de liaison vous permet de mettre en place une association entre deux propriétés des deux objets, associant plus souvent la propriété d'un objet avec une propriété sur un élément de modèle d'objet Document HTML (DOM), comme Figure 1 montre.

Binding Between an Attribute on a Destination Element and a Property from a Source ObjectFigure 1 liaison entre un attribut sur un élément de Destination et une propriété d'un objet Source

Le but d'établir une liaison consiste à copier des données entre deux objets impliqués : la source à partir de là entre les données et la destination à laquelle les données sont destinées.Si vous pensez que vous pouvez atteindre cet objectif à l'aide d'une instruction d'assignation simple :

myDestElem.value = mySourceObj.
name;

Fondamentalement, l'assignation est ce que la liaison est. Cependant, liaison n'est pas seulement une simple description de quelles sont les données à copier et à l'endroit où, mais aussi quelle. Le « quand » d'une liaison est généralement une des méthodes suivantes :

  • Liaison à sens unique : Copiez les données à l'élément DOM lorsque l'objet change. C'est la valeur par défaut dans la bibliothèque Windows pour JavaScript (WinJS).
  • Liaison ponctuelle : Copiez les données à l'élément DOM lors de la liaison. Il s'agit de l'équivalent de la cession.
  • Liaison bidirectionnelle : Copiez les données à l'élément DOM lorsque l'objet change et copier les données vers l'objet lors de la modification de l'élément DOM. Ce n'est pas prise en charge par WinJS.

Par défaut, WinJS liaison est une liaison unidirectionnelle, mais unique liaison est prise en charge aussi bien. Bien que WinJS ne prend en charge la liaison bidirectionnelle, il est un bon endroit pour accrocher votre moteur préféré liaison bidirectionnelle, comme celle de jQuery, comme vous le verrez.

Liaison d'objets

Pour commencer, disons que nous voulons bâtir un petit navigateur pour la population dans nos vies, comme le montre Figure 2.

Figure 2 liaison à un objet à un ensemble d'éléments HTML

L'idée est que nous pouvons avoir un certain nombre de personnes à travers lequel nous pouvons naviguer, chacun avec un nom, l'âge et une couleur préférée. Comme nous utilisons les boutons précédents et suivant, nous naviguons à d'autres personnes dans la liste, et si nous appuyer sur le bouton au milieu, l'horloge — nous avons fêter un anniversaire en augmentant l'âge de la personne actuellement affichée. Ce qui suit représente l'ensemble des personnes que nous allons être lèche-vitrine dans notre échantillon :

var people = [
  { name: "John", age: 18, favoriteColor: "red" },
  { name: "Tom", age: 16, favoriteColor: "green" },
  { name: "Chris", age: 42, favoriteColor: "blue" },
];

À partir d'un modèle de projet Application de Navigation dans Visual Studio 2012 offre HTML pour nous de remplir, comme le montre Figure 3.

La figure 3 du formulaire principal

<!DOCTYPE html>
<!-- homePage.html -->
<html>
<head>
  <meta charset="utf-8" />
  <title>homePage</title>
  <!-- WinJS references -->
  <link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet" />
  <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
  <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
  <link href="/css/default.css" rel="stylesheet" />
  <link href="/pages/home/home.css" rel="stylesheet" />
  <script src="/pages/home/home.js"></script>
</head>
<body>
  <!-- The content that will be loaded and displayed.
-->
  <div class="fragment homepage">
    <header aria-label="Header content" role="banner">
      <button class="win-backbutton" aria-label="Back"
        disabled type="button"></button>
      <h1 class="titlearea win-type-ellipsis">
        <span class="pagetitle">Welcome to PeopleBrowser!</span>
      </h1>
    </header>
    <section aria-label="Main content" role="main">
      <!-- display each person -->
      <div id="nameLabel">Name</div>
      <input id="name" readonly="true" type="text" 
        data-win-bind="value: name" />
      <div id="ageLabel">Age</div>
      <input id="age" readonly="true" type="text" 
        data-win-bind="value: age" />
      <div id="colorLabel">Favorite Color</div>
      <div id="color" data-win-bind="style.backgroundColor:
        favoriteColor"></div>
      <div id="buttons">
        <button id="previousButton"></button>
        <button id="birthdayButton"></button>
        <button id="nextButton"></button>
      </div>
    </section>
  </div>
</body>
</html>

La partie intéressante de ce HTML est l'utilisation de l'attribut liez-win, qui utilise le format suivant :

<div data-win-bind="destProp1: sourceProp1; destProp2: sourceProp2;..."></div>

La syntaxe de la victoire-lier les données est une liste délimitée par des points-virgules des expressions de liaison. Chaque expression est la combinaison d'une propriété DOM de l'élément de destination et une propriété de l'objet source. La syntaxe pointée que nous utilisons pour définir la couleur d'arrière-plan sur le style de la balise div couleur préférée — c'est-à-dire, style.backgroundColor—works pour les propriétés de la source et la destination et il perce en sous-objets, comme vous l'imaginez.

Chaque propriété de destination dans une expression de liaison est résolue contre l'élément HTML qui contient l'attribut win-lier les données. La question est : D'où l'objet vient contre laquelle les noms de propriété sont résolus ? Et la réponse est : le contexte de données.

Définition du contexte de données fait partie de l'opération de liaison, qui établit le lien entre l'élément HTML et tout objet est utilisé comme contexte de données, comme indiqué dans Figure 4.

La figure 4 définit le contexte de données

// homePage.js
(function () {
  "use strict";
  WinJS.UI.Pages.define("/pages/home/home.html", {
    ready: function (element, options) {
      var people = [
        { name: "John", age: 18, favoriteColor: "red" },
        { name: "Tom", age: 16, favoriteColor: "green" },
        { name: "Chris", age: 42, favoriteColor: "blue" },
      ];
      // Bind the current person to the HTML elements in the section
      var section = element.querySelector("section[role=main]");
      var current = 0;
      WinJS.Binding.processAll(section, people[current]);
    }
  });
})();

La fonction processAll dans l'espace de noms WinJS.Binding est la fonction qui analyse les attributs de la victoire-liez à une hiérarchie donnée des éléments HTML, la section contenant les éléments input et div dans notre échantillon. L'appel à processAll établit les liaisons entre les éléments HTML et le contexte de données comme décrit dans chaque attribut win-lier les données. Le contexte de données est le deuxième argument de processAll et est utilisé pour résoudre les noms de propriété figurant dans chaque expression de liaison. Les résultats déjà ressemblent à ce que nous sommes après, comme le montre Figure 2.

Par défaut, si nous ne faisons rien d'autre, nous avons établi une connexion à sens unique liaison entre l'objet de contexte de données et l'élément DOM. Cela signifie que sous forme de propriétés sur la source de données objet changent, nous prévoyons la sortie pour changer aussi bien, comme le montre Figure 5.

Figure 5 sous forme de propriétés sur le changement de Source de données, il en va de la sortie

function ready(element, options) {
  var people = [
    { name: "John", age: 18, favoriteColor: "red" },
    { name: "Tom", age: 16, favoriteColor: "green" },
    { name: "Chris", age: 42, favoriteColor: "blue" },
  ];
  var section = element.querySelector("section[role=main]");
  var current = 0;
  WinJS.Binding.processAll(section, people[current]);
  birthdayButton.onclick = function () {
    var person = people[current];
    person.age++; // Changing a bound property doesn't work yet ...
};
}

Notre implémentation du gestionnaire click pour le bouton anniversaire recherche l'élément actuel et modifie une propriété, plus précisément l'âge. Cependant, nous ne sommes pas tout à fait où nous devons faire pour obtenir l'interface utilisateur pour mettre à jour automatiquement.

Le problème est qu'un objet JavaScript standard ne supporte pas n'importe quel protocole de notification pour informer les parties intéressées — par exemple une liaison — que ses données ont changé. Pour ajouter la notification protocol est une question d'appeler l'as méthode à partir de l'espace de noms WinJS.Binding, comme le montre Figure 6.

Figure 6 ajouter le protocole de Notification

WinJS.UI.Pages.define("/pages/home/home.html", {
  ready: function (element, options) {
    var people = [
      // Notify binding listeners when these objects change
      WinJS.Binding.as({ name: "John", age: 18, favoriteColor: "red" }),
      WinJS.Binding.as({ name: "Tom", age: 16, favoriteColor: "green" }),
      WinJS.Binding.as({ name: "Chris", age: 42, favoriteColor: "blue" }),
    ];
    // Bind the current person to the HTML elements in the section
    var section = element.querySelector("section[role=main]");
    var current = 0;
    WinJS.Binding.processAll(section, people[current]);
    birthdayButton.onclick = function () {
      var person = people[current];
      person.age++; // Now this works!
};
  }
});

La méthode « sous » encapsule chaque objet, qui fournit le protocole de notification de liaison pour chaque modification de la propriété avertit tous les écouteurs liaison (tels que nos éléments HTML liés). Avec ce code en place, changement de l'âge de la personne se reflète dans l'interface utilisateur, comme Figure 7 montre.

Changing the Underlying Data Automatically Updates the Bound HTML Elements
Figure 7 modification des données sous-jacentes automatiquement met à jour les éléments HTML lié

Nous avons été liant un objet person unique à l'ensemble des éléments HTML pour l'affichage, mais vous pouvez traiter les expressions de liaison de données dans les attributs de la victoire-liez avec un autre type de contexte de données, comme indiqué dans Figure 8.

La figure 8, les Expressions de liaison de données de traitement

WinJS.UI.Pages.define("/pages/home/home.html", {
  ready: function (element, options) {
    var people = [
      // Notify binding listeners when these objects change
      WinJS.Binding.as({ name: "John", age: 18, favoriteColor: "red" }),
      WinJS.Binding.as({ name: "Tom", age: 16, favoriteColor: "green" }),
      WinJS.Binding.as({ name: "Chris", age: 42, favoriteColor: "blue" }),
    ];
    // Bind the current person to the HTML elements in the section
    var section = element.querySelector("section[role=main]");
    var current = 0;
    var viewModel = WinJS.Binding.as({ person: people[current] });
    WinJS.Binding.processAll(section, viewModel);
    birthdayButton.onclick = function () {
      viewModel.person.age++;
    };
    // Bind to the previous object
    previousButton.onclick = function () {
      current = (people.length + current - 1) % people.length;
      viewModel.person = people[current];
    };
    // Bind to the next object
    nextButton.onclick = function () {
      current = (people.length + current + 1) % people.length;
      viewModel.person = people[current];
    };
  }
});

Voici où nous faisons un décalage entre le passage en un seul morceau de données de « modèle » de notre application (c'est-à-dire l'ensemble des données qui n'ont rien à voir avec l'affichage de lui-même) pour grouper les données qui convient à notre « avis » de ce modèle (dans ce cas, la personne actuelle pour voir). Nous appelons cette variable le modèle « vue » après une technique célèbre et utile pour l'implémentation des interfaces utilisateur appelé Model-View-ViewModel (MVVM). Une fois que nous avons construit notre modèle vue comme un objet pouvant être lié, comme les propriétés sous-jacentes change (la personne, dans notre cas) l'affichage est mis à jour. Nous avons ensuite lier notre point de vue pour le modèle d'affichage afin que, dans notre prochaine et dos touche des gestionnaires — comme nous changeons dont personne nous aimerions Découvre — Avis est notifié. Pour ce faire, nous devrons mettre à jour le code HTML pour utiliser le modèle d'affichage au lieu de la personne directement, comme le montre Figure 9.

La figure 9 mise à jour de code HTML pour utiliser le modèle d'affichage

 

<section aria-label="Main content" role="main">
  <!-- display each person -->
  <div id="nameLabel">Name</div>
  <input id="name" readonly="true" type="text" 
    data-win-bind="value: person.
name" />
  <div id="ageLabel">Age</div>
  <input id="age" readonly="true" type="text" 
    data-win-bind="value: person.age" />
  <div id="colorLabel">Favorite Color</div>
  <div id="color" 
    data-win-bind="style.backgroundColor: person.favoriteColor"></div>
  <div id="buttons">
    <button id="previousButton"></button>
    <button id="birthdayButton"></button>
    <button id="nextButton"></button>
  </div>
</section>

La Figure 10 illustre le résultat.

You Can Rebind Different Objects to the Same Set of HTML Elements
La figure 10 vous pouvez relier des objets différents pour le même ensemble d'éléments HTML

En plus de la liaison d'objets à des éléments, liaison vous permet également d'écouter simplement une valeur à modifier. Par exemple, maintenant que nous modifions l'indice à la valeur actuelle lorsque l'utilisateur clique sur les boutons précédents ou suivant, il faut n'oubliez pas d'écrire le code pour modifier champ de personne du modèle d'affichage pour correspondre à. Cependant, vous pouvez utiliser la liaison elle-même aider ici, comme le montre Figure 11.

Figure 11 Expressions de liaison de retraitement

WinJS.UI.Pages.define("/pages/home/home.html", {
  ready: function (element, options) {
    var people = [
      // Notify binding listeners when these objects change
      WinJS.Binding.as({ name: "John", age: 18, favoriteColor: "red" }),
      WinJS.Binding.as({ name: "Tom", age: 16, favoriteColor: "green" }),
      WinJS.Binding.as({ name: "Chris", age: 42, favoriteColor: "blue" }),
    ];
    // Bind the current person to the HTML elements in the section
    var section = element.querySelector("section[role=main]");
    // Listen for the current index to change and update the HTML
    var viewModel = WinJS.Binding.as({ current: 0, person: null });
    WinJS.Binding.processAll(section, viewModel);
    viewModel.bind("current", function (newValue, oldValue) {
      viewModel.person = people[newValue];
    });
    birthdayButton.onclick = function () {
      viewModel.person.age++;
    };
    // Bind to the previous object
    previousButton.onclick = function () {
      // Set the current index and let the binding do the work
      viewModel.current = (people.length + 
        viewModel.current - 1) % people.length;
    };
    // Bind to the next object
    nextButton.onclick = function () {
      // Set the current index and let the binding do the work
      viewModel.current = (people.length + 
        viewModel.current + 1) % people.length;
    };
  }
});

Au lieu d'une simple variable qui doit contenir l'index à la personne actuellement affichée, nous ajoutons l'index à la personne actuellement affichée à notre modèle de vue pouvant être liée. Tous les objets pouvant être liés sont une méthode de liaison, qui nous permet d'écouter les modifications apportées aux propriétés de l'objet (la propriété current dans cet exemple). Lorsque l'utilisateur clique sur les boutons précédents ou suivant, nous simplement modifier l'index de la personne actuelle de montré et de laisser le processus de gestionnaire de lier les attributs liez-victoire pour le code HTML qui affiche la personne actuelle.

Si vous souhaitez arrêter l'écoute pour lier les événements, vous pouvez appeler la méthode unbind.

Maintenant, comme nous l'avons mentionné, tout ce que vous avez vu travaille contre la valeur par défaut : liaison unidirectionnelle. Toutefois, si vous souhaitez configurer d'autres types de liaison ou de participer au processus de liaison lui-même, vous pouvez le faire avec un initialiseur de liaison.

Initialiseurs

Un initialiseur est le troisième paramètre optionnel pour une expression de liaison qui spécifie une fonction à appeler lorsque la liaison est établie :

<div data-win-bind="destProp: sourceProp init" ...></div>

Vous fournissez un initialiseur dans le cadre d'une expression de liaison Si vous souhaitez participer ou même remplacer le comportement de liaison existant — par exemple, pour effectuer une conversion de données ou même accrocher une liaison bidirectionnelle jQuery. Un initialiseur de liaison est une fonction qui se charge de la liaison unidirectionnelle par défaut et possède la signature suivante :

function myInit(source, sourceProperties,
  dest, destProperties) {...}

Les détails d'implémentation d'un initialiseur personnalisé dépassent la portée de cet article, mais WinJS a intégré plusieurs initialiseurs, dont vous pouvez tirer profit. Par exemple, si vous souhaitez faire une seule fois au lieu d'une liaison unidirectionnelle, vous pouvez utiliser la fonction unique de l'espace de noms WinJS.Binding :

<input data-win-bind=
  "value: person.
name WinJS.Binding.oneTime"></input>

Sur l'autre extrémité du spectre, lorsque vous effectuez une liaison unidirectionnelle, il est souvent utile d'effectuer la conversion de données (appelé aussi transformation de données). Par exemple, imaginons que nous voulions préciser l'âge des personnes dans notre vie :

function getWordsFromNumber(i) {...}
// Convert ages to words
window.ageToWords =
  WinJS.Binding.converter(function (value) { 
    return getWordsFromNumber(value); 
  });

La fonction de convertisseur sur l'espace de noms WinJS.Binding fournit la partie dure de la mise en œuvre de l'initialiseur ; tout ce que vous devez faire est de fournir une fonction pour effectuer la conversion réelle et il sera appelé comme les changements de valeur source. L'utiliser dans le code HTML, on dirait que vous attendez :

<input data-win-bind="value: person.age ageToWords"></input>

Vous pouvez voir les résultats dans Figure12.

Translating a Numeric Age into Words via Data Conversion
La figure 12, traduisant un âge numérique en mots par l'intermédiaire de Conversion de données

Liaison des valeurs un à la fois est utile, mais encore plus utile — en particulier pour les applications Windows Store — lie tout à la fois des collections de valeurs. Pour cela, nous avons la liste de liaison.

Une liste de liaison

Imaginez un exemple simple de l'utilisation d'un contrôle ListView avec une collection de valeurs :

<div data-win-control="WinJS.UI.ListView"
  data-win-options="{itemDataSource: items.dataSource}">
</div>

Ici nous créons un contrôle ListView déclarative dans le code HTML qui est lié à la propriété dataSource d'un objet éléments globaux. Dans notre JavaScript, il est facile de créer et de remplir l'objet items sous forme d'une liste de liaison :

// A global binding list of items
window.items = new WinJS.Binding.List();
[0, 1, 2].forEach(function (i) {
  WinJS.Promise.timeout(500 * (i+1)).done(function () {
    // Add an item to the binding list, updating the ListView
    items.push(i);
  });
});

Dans ce code, nous créons une liste de liaison (une instance de type de liste de l'espace de noms WinJS.Binding) et nous boucle sur un tableau de valeurs, à l'aide de chacun pour créer un délai, qui est une promesse qui se déclenche à un certain moment dans l'avenir, selon l'argument que vous passez (millisecondes). Lorsque chaque délai d'attente se termine, nous allons voir le ListView obtenir une valeur supplémentaire, comme Figure 13 montre.

The ListView Updating as the Underlying Binding List Updates
Figure 13 la ListView mise à jour dans la liste sous-jacente de liaison met à jour

Le code HTML ne fournit pas un ID pour le ListView, ni le JavaScript interagit-il avec ListView en quelque sorte. Au lieu de cela, le HTML et le JavaScript, les deux rendez-vous sur les éléments de liste de liaison. C'est la liste de liaison qui implémente la collection liaison API (appelé IListDataSource). Au lieu de décisions vous programmez directement sur IListDataSource, il n'est pas particulièrement conviviales pour les programmeurs — la liste liaison expose sa mise en œuvre IListDataSource par l'intermédiaire de la propriété dataSource.

Pour fournir une API qui est aussi familier que possible pour les programmeurs JavaScript, la liste de liaison implémente une API similaire et une sémantique similaire comme le tableau intégré prend en charge — par exemple, pousser, pop, couper en tranches, épisser et ainsi de suite. A titre de comparaison, Voici comment fonctionne le tableau JavaScript intégré :

// Using the built-in array
var array = [];
array.push("one");
array.push("two");
array.push("three");
var x = array[0]; // x = "one"
var y = array[1]; // y = "two"
array[2] = "THREE";
var z = array[2]; // z = "THREE";

La liste de liaison se comporte de la même façon sauf qu'au lieu d'utiliser un indexeur — c'est-à-dire, crochets, il expose des éléments via setAt et getAt :

// Using the WinJS binding list
var list = new WinJS.Binding.List();
list.push("one");
list.push("two");
list.push("three");
var x = list.getAt(0); // x = "one"
var y = list.getAt(1); // y = "two"
list.setAt(2, "THREE");
var z = list.getAt(2); // z = "THREE";

Tri et filtrage

En plus de l'API familière, la liste de liaison a été construite avec app Store Windows besoins en tenant compte de la construction. Vous avez déjà vu comment la propriété dataSource vous permet de connecter au contrôle ListView. En outre, vous pourriez être intéressé de tri et de filtrage de vos données. Par exemple, Voici notre liste de personnes à nouveau, cette fois enveloppé dans une liste de liaison :

var people = new WinJS.Binding.List([
  { name: "Tom", age: 16 },
  { name: "John", age: 17 },
  { name: "Chris", age: 42 },
]);
// Sort by name
window.sortedPeople = people.
createSorted(function (lhs, rhs) { 
    return lhs.
name.localeCompare(rhs.
name); 
  });
// Filter by age (adults only)
window.filteredPeople = people.
createFiltered(function (p) { return p.age > 17; });

Nous pouvons trier une liste de liaison en appelant la méthode createSorted, en passant dans une fonction de classement, ou de la filtrer en appelant la méthode createFiltered, en passant dans une fonction de filtrage. Créer du résultat d'un appel de ces méthodes est une vue sur les données qui ressemble et agit comme une autre instance de la liste de liaison, et nous pouvons lier à un ListView, comme Figure 14 montre.

Filtering a Binding List
La figure 14, filtrage d'une liste de liaison

Au lieu de fournir une copie des données sous-jacentes, les méthodes createSorted et createFiltered renvoient une vue direct sur les données existantes. Cela signifie que toutes les modifications aux données sous-jacentes sont répercutées dans les points de vue et seront affichées dans des contrôles liés. Par exemple, nous pourrions ajouter un mineur à la liste sous-jacente :

// Changes to the underlying data are reflected in the live views
var person = { name: "Pete", age: 17, favoriteColor: "black" };
people.push(person);

Même si nous modifions les données sous-jacentes, mettra à jour la vue triée et ListView est avisé du changement, comme Figure 15 montre.

Sorting a Binding List
Figure 15 tri d'une liste de liaison

Aussi, parce que la vue depuis les méthodes create ressemble et se sent comme une liste de liaison, vous pouvez également trier ou filtrer la vue de manière empilée :

// Filterd by age (minors) and sorted by name
window.filteredSortedPeople = people.
createFiltered(function (p) { return p.age < 18; }).
createSorted(function (lhs, rhs) { 
    return lhs.
name.localeCompare(rhs.
name); 
  });

Les résultats de la liaison à l'affichage filtré et trié qui en résulte ne doit pas être une surprise (voir Figure 16).

Sorting and Filtering a Binding List
Figure 16 tri et filtrage d'une liste de liaison

Soyez prudent lorsque vous empilez des que vous le faites dans le bon ordre. Dans le cas de filtrage, si vous triez ou groupe d'abord et puis filtrez, vous faites plus de travail qu'il faut. En outre, chaque couche vue est allégées, alors vous aurez envie de s'assurer que vous les empilez seulement aussi profond que nécessaire.

Regroupement

En plus de tri et de filtrage sur la liaison de données de liste, vous pouvez également grouper il par certains critères des données. Par exemple, adultes et mineurs fonctionnerait bien pour les données de notre exemple :

// Group by age
window.groupedPeople = people.
createGrouped(function (p) { return p.age < 18 ? "
minor" : "adult" });

La valeur de retour de la fonction grouping est une valeur de chaîne qui identifie de façon unique le groupe — dans notre cas, la chaîne « mineure » ou la chaîne « adulte ». Liaison à la vue groupée des données montre les données organisées par groupe — autrement dit, tous les éléments de chaque groupe avant de passer au groupe suivant, comme Figure 17 montre.

Grouping a Binding List
La figure 17, regroupant une liste de liaison

Cet exemple montre que deux groupes, mais vous pouvez avoir n'importe quel nombre de groupes. En outre, comme createSorted et createFiltered, la méthode createGrouped retourne une vue de données en direct, donc les modifications apportées aux données sous-jacentes se refléteront dans les destinations de lier.

Cependant, alors que c'est clair pour nous, les développeurs, que nous allons trier les groupes — première les adultes et les mineurs, il n'est pas clair pour les utilisateurs de notre programme, car il n'y a aucun indicateur visuel du groupement. Pour poser le ListView pour fournir un regroupement visuel indicateur, ListView vous permet de spécifier deux jeux de données : la liste d'éléments groupés et les groupes eux-mêmes. Configurer ListView avec les deux ensembles de données ressemble à ceci :

<div data-win-control="WinJS.UI.ListView"
  data-win-options="{itemDataSource: groupedPeople.dataSource,
                     groupDataSource: groupedPeople.groups.dataSource}">
</div>

Une fois que nous avons créé la vue groupée de la liste de liaison, la propriété groups expose une liste de ces groupes afin que ListView peut les emprunter. Toutefois, avant que nous puissions faire fonctionner, nous devons aussi revenir à notre utilisation de la fonction createGrouped :

// Group by age
function groupKeySelector(p) { return p.age < 18 ? "
minor" : "adult"; };
function groupDataSelector(p) { return p.age < 18 ? "
minor" : "adult"; };
window.groupedPeople = people.createGrouped(groupKeySelector, groupDataSelector);

Précédemment, nous avons regrouper, nous devions juste fournir une fonction que pourrait faire le regroupement basé sur un identificateur de groupe unique. Cependant, si nous voulons réellement afficher les groupes de l'utilisateur, nous devons une autre méthode qui permet d'extraire les groupes eux-mêmes (si vous voulez choisir l'ordre des groupes, vous pouvez fournir une troisième méthode à la méthode createGroup qui effectue le tri). Dans les deux cas, nous fournissons une chaîne pour représenter le groupe aussi bien quant à générer la liste des groupes, qui fonctionne très bien, comme vous pouvez le voir dans Figure 18.

Grouping a Binding List with ListView Headers
La figure 18, regroupant une liste liaison avec en-têtes de ListView

Comme Figure 18 montre, le groupe est effectivement utilisé pour décorer les données groupées, rendant très facile de voir quelles données entrent dans quel groupe. Malheureusement, même avec cette indication visuelle du regroupement, nos objets au format JSON pas vraiment l'interface utilisateur, nous voulons montrer à nos utilisateurs. Pour que cela fonctionne de la façon dont nous voulons exige que les modèles.

Modèles

Un modèle est une hiérarchie des éléments HTML avec option « trous » pour combler dans dynamic data seule racine. L'attribut win-lier les données sur la div définit les trous à l'aide d'attributs liez-win. Par exemple, nous pourrions créer un modèle pour notre personne objets comme suit :

<div id="itemTemplate" data-win-control="WinJS.Binding.Template">
  <span data-win-bind="style.color: favoriteColor">
    <span data-win-bind="textContent: name"></span>
    <span> is </span>
    <span data-win-bind="textContent: age"></span>
    <span> years old</span>
  </span>
</div>

Ce qui rend ce morceau de HTML, un modèle est l'attribut win-contrôle de données définie sur le type de contrôle WinJS.Binding.Template. Une fois que nous avons notre modèle, vous devez le rendre pour remplir les trous avec les données :

// Manual template rendering
var person = { name: "Pete", age: 17, favoriteColor: "black" };
var template = itemTemplate.winControl;
template.render(person).
done(function (element) { peteDiv.appendChild(element); });

Parce que le modèle est juste un autre contrôle (bien qu'un contrôle qui cache lui-même jusqu'à restitution manuellement), nous pouvons atteindre dans la balise div qui le définit et parviennent à accéder à ses fonctionnalités via une propriété bien connue appelée winControl. La fonctionnalité à que nous voulons accéder est la méthode de rendu du modèle qui prend un contexte de données devant servir à lier les attributs de la victoire-lier les données et produit un élément HTML entièrement formé pour nous de faire ce que nous voulons avec.

Si vous fournissez un modèle à ListView, il restituera chaque élément dans ListView avec ce modèle. En fait, ListView peut avoir des modèles pour restituer les éléments et les en-têtes de groupe. Que voir en action, nous allons 1ére mise à jour les groupes d'objets, comme il est plus typique :

// Fancy group by age
var groups = [{ key: 1, name: "Minor" }, { key: 2, name: "Adult" }];
function groupDataSelector(p) { 
  return p.age < 18 ?
groups[0] : groups[1]; 
};
function groupKeySelector(p) { return groupDataSelector(p).key; };
window.fancyGroupedPeople = 
  people.createGrouped(groupKeySelector, groupDataSelector);

Dans ce code, nous avons deux objets de groupe, chacun avec une clé et un nom, et nous avons obtenu des données distinctes et les fonctions de sélecteur de clé qui renvoient au groupe lui-même ou clé du groupe, respectivement. Avec nos données Groupe faites un peu plus réel-monde-comme un modèle pour l'en-tête de groupe est créé, comme indiqué dans Figure 19.

19 Figure modèle pour l'en-tête de groupe

<div id="headerTemplate" data-win-control="WinJS.Binding.Template">
  <span data-win-bind="textContent: name"></span>
</div>
<div id="itemTemplate" data-win-control="WinJS.Binding.Template">
  <span data-win-bind="style.color: favoriteColor">
    <span data-win-bind="textContent: name"></span>
    <span> is </span>
    <span data-win-bind="textContent: age"></span>
    <span> years old</span>
  </span>
</div>
<h1>Fancy Grouped</h1>
<div data-win-control="WinJS.UI.ListView"
  data-win-options="{
    groupDataSource: fancyGroupedPeople.groups.dataSource,
    groupHeaderTemplate: select('#headerTemplate'),
    itemDataSource: fancyGroupedPeople.dataSource,
    itemTemplate: select('#itemTemplate')}">
</div>

Le modèle de l'en-tête de groupe est créé comme un modèle d'élément. Les modèles d'en-tête et d'élément de groupe sont passés au contrôle ListView via les propriétés groupHeaderTemplate et itemTemplate dans l'attribut de données-victoire-options. Notre colombophile groupé des données ressemble à Figure 20.

Grouping a Binding List with ListView Headers and Templates
20 Figure une liste liaison avec en-têtes ListView et les modèles de regroupement

OK, nous l'admettons, qui n'est pas très fantaisie, mais la combinaison des groupes et des éléments, notamment les modèles, montre la puissance de la liste de liaison. En fait, la liste de liaison est si utile, c'est au cœur du modèle de données asynchrones exposé depuis le fichier data.js généré par les modèles de projet demande de grille et Split, comme le montre Figure 21.

21 Figure le fichier Data.js généré par l'Application de la grille et le projet d'Application de Split

// data.js
(function () {
  "use strict";
  var list = new WinJS.Binding.List();
  var groupedItems = list.createGrouped(
      function groupKeySelector(item) { return item.group.key; },
      function groupDataSelector(item) { return item.group; }
  );
  // TODO: Replace the data with your real data.
// You can add data from asynchronous sources whenever it becomes available.
generateSampleData().forEach(function (item) {
    list.push(item);
  });
  WinJS.Namespace.define("Data", {
    items: groupedItems,
    groups: groupedItems.groups,
    getItemsFromGroup: getItemsFromGroup,
    ...
});
  ...
// This function returns a WinJS.Binding.List containing only the items
  // that belong to the provided group.
function getItemsFromGroup(group) {
    return list.createFiltered(function (item) {
    return item.group.key === group.key; });
  }
  ...
});
})();

Vous pouvez voir la création de la liste liaison vide, la création d'une version groupée de cette liste en utilisant les fonctions clés d'et la sélection de données sur les groupes, une petite boucle forEach qui ajoute que les éléments à la liste de liaison et enfin, un programme d'assistance qui fonctionnent de filtrage.

Où en sommes-nous ?

Nous avons commencé cet article en creusant dans la liaison, la possibilité d'associer une propriété sur un objet à un attribut sur un élément HTML. Hors de la boîte, WinJS prend en charge les initialiseurs de liaison à sens unique, unique et personnalisé, mais une liaison bidirectionnelle pas. Liaison est prise en charge sur simples objets pouvant être liés ainsi que des listes d'objets qui implémentent l'interface IListDataSource. Le meilleur endroit pour obtenir une implémentation de l'interface IListDataSource est par l'intermédiaire de l'objet binding liste (WinJS.Binding.List), qui tient compte de tri, de filtrage et de regroupement. Nous avons également vu comment des modèles utiles sont lorsque combinée avec la liaison et l'utilité des modèles et la liaison sont quand il s'agit de contrôles qui prennent en charge la liaison de liste, tels que ListView.

Chris Sells est le vice-président de la Division des outils développeur Telerik. Il est coauteur de « Building Windows 8 Apps avec JavaScript"(Addison-Wesley Professional, 2012), de laquelle cet article a été adapté. Plus d'informations sur vend et ses différents projets, sont disponibles à sellsbrothers.com.

Brandon Satrom est un gestionnaire de programme dans la Division de l'interface utilisateur de Kendo de Telerik. Il est coauteur de « Building Windows 8 Apps avec JavaScript"(Addison-Wesley Professional, 2012), de laquelle cet article a été adapté. Vous pouvez le suivre sur Twitter à adresse twitter.com/BrandonSatrom.

Merci aux experts techniques suivants d'avoir relu cet article : Chris Anderson, Jonathan Antoine, Michael Weinhardt, Shawn Wildermuth et Josh Williams