Comment personnaliser des données de modèle Visual Studio (HTML)

[ Cet article est destiné aux développeurs de Windows 8.x et Windows Phone 8.x qui créent des applications Windows Runtime. Si vous développez une application pour Windows 10, voir la Documentation ]

Dans les modèles Hub/Pivot, Hub, Pivot, Grille et Fractionner, le code qui obtient les données requises pour l’application se trouve dans le fichier data.js. Ce fichier représente l’exemple de source de données de l’application. Le fichier data.js comprend des données statiques que vous devez généralement remplacer par des données dynamiques. Par exemple, si votre application effectue une seule demande xhr pour obtenir des données RSS ou JSON, il est préférable d’inclure ce code dans data.js. En y incluant le code, vous pouvez facilement utiliser vos propres données sans modifier le modèle de données présent dans les modèles.

Astuce  Les modèles Hub/Pivot, Hub et Pivot permet également de récupérer des données statiques dans des fichiers .resjson qui prennent en charge la globalisation. Pour plus d’informations, voir Exemple de liaison de données à l’interface utilisateur dans les modèles Hub/Pivot, Hub et Pivot.

 

Lorsque vous ajoutez vos propres données à une application, vous devez tenir compte des points suivants :

  • Les groupes et les éléments sont liés intrinsèquement. L’application s’attend à ce que les données d’élément soient organisées en groupes. Vous pouvez dissocier les deux dans votre propre implémentation, mais vous devez modifier le code pour que cette implémentation fonctionne. Cette rubrique décrit l’utilisation des groupes dans le modèle de données du modèle.
  • Lorsque vous implémentez des données personnalisées pour une application dans data.js, vous devez vous assurer que les noms de propriétés inhérents à vos données personnalisées sont mappés aux noms de propriétés utilisés par le modèle. Vous pouvez modifier les noms utilisés par le modèle, mais cela demande des révisions de code supplémentaires. Cette rubrique contient quelques exemples illustrant la procédure à suivre.

Éléments et groupes

Les données du modèle sont stockées dans un WinJS.Binding.List. Ce code montre la déclaration d’une liste dans le fichier data.js.

var list = new WinJS.Binding.List();

Un tableau de données d’éléments (sampleItems dans cet exemple) est passé à WinJS.Binding.List par la fonction push, comme illustré ici :

generateSampleData.forEach(function (item) {
    list.push(item);
});

WinJS.Binding.List inclut la logique interne pour gérer le groupement de données. Le tableau sampleItems inclut une propriété group qui identifie le groupe auquel l’élément appartient (dans l’exemple de données, les groupes sont spécifiés dans le tableau sampleGroups). Voici le tableau de données d’éléments dans la fonction generateSampleData :

function generateSampleData() {
    // . . .
    var sampleGroups = [
        { key: "group1", title: "Group Title: 1", // . . .
        // . . .
    ];

    var sampleItems = [
        { group: sampleGroups[0], title: "Item Title: 1", // . . .
        // . . .
    ];

    return sampleItems;
}

Lorsque vous modifiez l’application pour vos données personnalisées, vous pouvez suivre le même modèle pour regrouper vos données. Pour des ensembles de données plus petits, nous vous recommandons d’utiliser WinJS.Binding.List pour ListView. Si vous ne regroupez pas vos éléments, vous pouvez toujours utiliser WinJS.Binding.List, mais vous devez modifier le code du modèle partout où le modèle s’attend à trouver des données basées sur des groupes.

Astuce  WinJS.Binding.List est une source de données synchrone qui utilise un tableau JavaScript. Pour des ensembles de données très importants, qui peuvent comprendre quelques milliers d’éléments, vous aurez peut-être besoin d’utiliser une source de données asynchrone. Pour plus d’informations, voir Utilisation de ListView.

 

La fonction createGrouped de WinJS.Binding.List spécifie comment regrouper les éléments à l’aide d’une clé de groupe et d’une valeur de groupe d’éléments. Cette fonction est appelée dans data.js. key et group sont des noms de propriété qui sont spécifiés dans les tableaux de données d’exemple.

var groupedItems = list.createGrouped(
    function groupKeySelector(item) { return item.group.key; },
    function groupDataSelector(item) { return item.group; }
);

Lorsque l’application de modèle a besoin d’une liste d’éléments, elle appelle getItemsFromGroup qui retourne WinJS.Binding.List contenant uniquement les éléments qui appartiennent au groupe spécifié.

function getItemsFromGroup(group) {
    return list.createFiltered(function (item) {
        return item.group.key === group.key;
    });
}

Astuce  Les fonctions telles que getItemsFromGroup, qui appellent createFiltered, créent une projection de WinJS.Binding.List. Vous devrez peut-être supprimer l’objet retourné si vous quittez une page. Pour supprimer l’objet, appelez la méthode WinJS.Binding.List.dispose.

 

La fonction define de la bibliothèque Windows pour JavaScript expose les données à utiliser dans l’application en spécifiant un espace de noms nommé Data ainsi qu’un ensemble de fonctions membres publiques.

WinJS.Namespace.define("Data", {
    items: groupedItems,
    groups: groupedItems.groups,
    getItemReference: getItemReference,
    getItemsFromGroup: getItemsFromGroup,
    resolveGroupReference: resolveGroupReference,
    resolveItemReference: resolveItemReference
});

Si vous voulez définir une source de données différente pour chaque page de votre application, ou un modèle de données différent, vous devez remplacer tous les appels à ces membres dans le code JavaScript.

Liaisons de données de groupe et d’élément à l’interface utilisateur

Le code suivant présente un exemple de balisage pour le contrôle ListView. La source de données pour le ListView est spécifiée dans la propriété itemDataSource, illustrée ci-après. Cet exemple est tiré de split.html dans le modèle Fractionner.


<div class="itemlist win-selectionstylefilled" aria-label="List of this group's items" data-win-control="WinJS.UI.ListView" data-win-options="{
    layout: {type: WinJS.UI.ListLayout},
    currentItem: {type: WinJS.UI.ObjectType.item, index: 0, hasFocus: true},
    selectionMode: 'single',
    swipeBehavior: 'none',
    tapBehavior: 'toggleSelect',
    itemDataSource: select('.pagecontrol').winControl.itemDataSource,
    itemTemplate: select('.itemtemplate'),
    onselectionchanged: select('.pagecontrol').winControl.selectionChanged
    }">
</div>

Dans le code précédent, une propriété itemDataSource associée à la page est affectée à la propriété itemDataSource du contrôle ListView.

Dans les modèles, les données sont généralement liées à l’interface utilisateur dans la fonction init ou ready définie dans le fichier .js associé à chaque page HTML. Le code suivant est contenu dans la fonction init pour split.html. Dans ce code, l’application obtient une référence de groupe, puis appelle getItemsFromGroup, qui est implémenté dans data.js. Comme indiqué précédemment, getItemsFromGroup retourne un objet WinJS.Binding.List qui contient uniquement les éléments dans le groupe spécifié.

this._group = Data.resolveGroupReference(options.groupKey);
this._items = Data.getItemsFromGroup(this._group);

Nous devons ensuite lier la liste retournée par getItemsFromGroup à la propriété itemDataSource de la page, qui lie les données au ListView, ainsi que spécifier le gestionnaire pour la sélection d’éléments (_selectionChanged).


this.itemDataSource = this._items.dataSource;
this.selectionChanged = ui.eventHandler(this._selectionChanged.bind(this));

Pour afficher chaque élément dans le ListView, l’application associe un modèle au ListView, comme illustré ici. Ce code apparaît dans le balisage du contrôle ListView et utilise la propriété itemTemplate pour spécifier un élément DIV contenant le nom de classe itemtemplate.

itemTemplate: select('.itemtemplate')

Les modèles WinJS, qui sont basés sur WinJS.Binding.Template, sont utilisés pour mettre en forme et afficher plusieurs instances des données. Le modèle le plus couramment utilisé dans les modèles Grille et Fractionner est le modèle d’élément servant à afficher des éléments dans un objet ListView. Comme tout objet de modèle WinJS, vous le déclarez en ajoutant un attribut data-win-control et en affectant à celui-ci la valeur WinJS.Binding.Template. Voici le code HTML pour itemtemplate dans split.html :

<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <div class="item">
        <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
        <div class="item-info">
            <h3 class="item-title win-type-ellipsis" 
                data-win-bind="textContent: title"></h3>
            <h6 class="item-subtitle win-type-ellipsis"
                data-win-bind="textContent: author"></h6>
        </div>
    </div>
</div>

itemtemplate est utilisé pour des éléments ListView arbitraires. Selon le contexte, les éléments ListView peuvent être des groupes ou des éléments de données individuels. Dans items.html, par exemple, les éléments ListView sont des groupes.

Important  Les modèles que vous créez à l’aide de WinJS.Binding.Template ne sont pas liés à des modèles de projet et d’élément Visual Studio, tels que Grille et Fractionner.

 

Les modèles de projet s’attendent à la présence de certaines propriétés dans les données, et ces propriétés sont nommées explicitement dans le code HTML. Dans le code HTML précédent pour itemtemplate, vous pouvez constater la présence de propriétés telles que title et subtitle. Si vos données d’application personnalisée n’utilisent pas ces noms de propriétés, vous devez procéder de l’une des façons suivantes :

  • Mappez vos données à ces noms de propriétés (dans data.js en règle générale) ou
  • Corrigez toutes les références du code HTML et .js à ces propriétés dans le code de modèle afin qu’elles correspondent aux noms de propriétés utilisés dans vos données. Parmi les propriétés utilisées dans les modèles, citons :
    • title, subtitle, description, et backgroundImage (propriétés de groupe et d’élément)
    • group et content (propriétés d’élément)
    • key (propriété de groupe)

Selon le même modèle WinJS, le modèle d’application Grille utilise également headerTemplate dans certaines de ses pages HTML.

Exemple de liaison de données à l’interface utilisateur dans les modèles Hub/Pivot, Hub et Pivot

Dans Visual Studio, les modèles de projet Hub/Pivot, Hub et Pivot montrent comment implémenter deux sources de données différentes :

  • Données statiques globalisées stockées dans des fichiers de ressources .resjson. Ces données sont utilisées dans certaines sections de l’application (contrôles PivotItem ou HubSection.
  • Exemple de données dans data.js, qui représentent le modèle de données. Ce fichier est le même que dans les modèles Grille et Fractionner. L’exemple de données est utilisé dans le contrôle ListView dans l’une des sections de l’application.

Des fonctions déclaratives sont utilisées dans le code HTML pour obtenir initialement l’exemple de données, et le modèle de données est synchrone par défaut. La personnalisation des modèles pour utiliser des données dynamiques dans toutes les sections nécessite d’apporter quelques modifications aux fichiers hub.html, hub.js, entre autres. Les exemples d’application suivants montrent comment personnaliser les modèles Hub/Pivot et Hub pour la prise en charge des données asynchrones :

Étant donné que les données globalisées incluses dans le fichier .resjson sont facilement remplacées, les exemples d’application ne modifient pas ce fichier de ressources. Dans les exemples d’application, les données des éléments <img> et du contrôle ListView présentes dans les sections Hub sont récupérées de façon asynchrone.

Pour plus d’informations sur la fourniture de données globalisées dans des fichiers .resjson, voir Démarrage rapide : traduction des ressources de l’interface utilisateur.

Pour prendre en charge la liaison asynchrone des données au contrôle ListView du Hub/Pivot, nous devons d’abord remplacer dans hub.js les variables globales qui appellent le modèle de données :

var section3Group = Data.resolveGroupReference("group4");
var section3Items = Data.getItemsFromGroup(section3Group);

par ces déclarations de variable :


var section3Group = "group2";
var section3Items;

Vous devez également modifier l’implémentation des fonctions déclaratives dans hub.js. Dans l’implémentation de modèle par défaut, ces fonctions reposent sur des données déjà disponibles (comme l’appel de section3Items.dataSource). Remplacez ce code :

section3DataSource: section3Items.dataSource,

section3HeaderNavigate: util.markSupportedForProcessing(function (args) {
    nav.navigate("/pages/section/section.html", { title: args.detail.section.header, 
        groupKey: section3Group.key });
}),

section3ItemNavigate: util.markSupportedForProcessing(function (args) {
    var item = Data.getItemReference(section3Items.getAt(args.detail.itemIndex));
    nav.navigate("/pages/item/item.html", { item: item });
}),

par :


section3DataSource: null,

section3HeaderNavigate: util.markSupportedForProcessing(function (args) {
    nav.navigate("/pages/section/section.html", { title: args.detail.section.header,
        groupKey: section3Group });
}),

section3ItemNavigate: util.markSupportedForProcessing(function (args) {
    var itemSet = section3Items;
    var itemObj = itemSet.getAt(args.detail.itemIndex);
    var item = [itemObj.group.key, itemObj.title, itemObj.backgroundImage];

    nav.navigate("/pages/item/item.html", { item: item });
}),

Ce code affecte la valeur Null à la fonction section3DataSource pour éviter de lier les données avant qu’elles ne soient prêtes. Nous allons définir la source de données plus tard dans une fonction de liaison de données (_bindData ou bindListView, en fonction de l’exemple d’application).

La fonction de liaison de données est appelée une fois que les données sont disponibles. À cette fin, nous ajoutons un écouteur pour l’événement dataReady du modèle de données, lequel est défini dans l’exemple d’application de data.js.


this._observer = Data.getObservable();
this._observer.addEventListener('dataReady', this.onDataCompleted.bind(this));

L’application appelle la fonction de liaison de données à partir du gestionnaire d’événements onDataCompleted (non illustré). Le code de la fonction _bindData de l’exemple de modèle Hub est indiqué ci-après. Dans ce code, nous définissons la propriété itemDataSource de l’objet ListView.


_bindData: function (context, grp1Items, grp2Items) {

    var self = context;

    // . . .

    self._items = grp2Items;
    section3Items = self._items;
    self._section3lv.itemDataSource = self._items.dataSource;

    // . . .   

},

Si le bouton Précédent est utilisé pour accéder à la page, la fonction de liaison de données est directement appelée à partir de la fonction d’initialisation de la page, car il n’est pas nécessaire d’attendre de nouvelles données.

Astuce  Dans le code du modèle Hub, pour interroger le DOM de l’élément ListView (stocké dans _section3lv), l’application appelle une fonction _hubReady à partir du gestionnaire d’événements loadingstatechanged du contrôle Hub. Cet événement n’est activé qu’une fois la page Hub chargée. À l’aide de ce gestionnaire d’événements, nous pouvons interroger le DOM pour obtenir l’élément DIV imbriqué associé au ListView.

 

Pour obtenir le code complet permettant de faire fonctionner les données asynchrones dans les modèles Hub/Pivot et Hub, consultez Lecteur Web JSON qui utilise le modèle Hub/Pivot et Lecteur Web JSON qui utilise le modèle Hub. Outre les personnalisations décrites ici, nous avons apporté les modifications suivantes à l’exemple d’application :

  • Inclusion, dans le modèle de données (data.js), de code permettant de récupérer des données à l’aide d’une demande xhr et d’analyser des données JSON (issues de Flickr).
  • Inclusion, dans le modèle de données, de code permettant de gérer plusieurs demandes de données et d’activer l’événement dataReady quand des données sont retournées.
  • Inclusion, dans l’interface utilisateur, d’une zone d’entrée permettant de demander de nouvelles données.
  • Inclusion d’une barre de progression affichant l’état de la requête de données.
  • Divers ajouts de styles CSS pour la zone d’entrée et la barre de progression.
  • Inclusion de fonctions pour initialiser la page une fois le contrôle Hub entièrement chargé (comme _hubReady ou _hubReadyPhone).
  • Modification des éléments <img> de Hub/Pivot ou Hub pour prendre en charge les événements de clic (les fichiers modifiés sont spécifiques du modèle).
  • Modification de fichiers pour lier des données asynchrones aux éléments <img> de Hub/Pivot ou Hub (les fichiers modifiés sont spécifiques du modèle).
  • Modification de hub.js pour prendre en charge la navigation vers les images des éléments <img> de Hub/Pivot ou Hub (les fichiers modifiés sont spécifiques du modèle).
  • Modification des fichiers item.html et item.js pour prendre en charge l’affichage d’images uniques.

Exemple de liaison de données à l’interface utilisateur (Grille et Fractionner)

Cette section montre comment implémenter votre propre source de données dans les modèles de projet Grille et Fractionner. L’exemple de code donné ici utilise une demande xhr pour générer des données RSS.

Important  Pour implémenter des données asynchrones dans le modèle Hub, voir Liaison de données à l’interface utilisateur dans le modèle Hub.

 

Mise à jour de data.js

  1. Créez un projet dans Visual Studio. Utilisez le modèle de projet d’application Fractionner ou d’application Grille.

  2. Dans data.js, ajoutez les variables suivantes près du début du fichier, après l’instruction use strict :

    var lightGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
    var mediumGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
    
  3. Dans data.js, supprimez la fonction generateSampleData qui contient les tableaux suivants : sampleGroups et sampleItems.

    Nous remplacerons ces données par des données RSS. Nous n’avons pas besoin de la plupart des variables d’espace réservé, telles que groupDescription. Toutefois, nous devrons réutiliser les images d’espace réservé, à savoir lightGray et mediumGray, pour que le nouveau code fonctionne.

  4. À l’emplacement où vous avez supprimé generateSampleData, ajoutez le code suivant à data.js :

    
    function getFeeds() {
        // Create an object for each feed.
        blogs = [
            {
                key: "blog1", url: 
           'https://windowsteamblog.com/windows/b/developers/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            },
            {
                key: "blog2", url: 
           'https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            }]
        // Get the content for each feed in the blog's array.
        blogs.forEach(function (feed) {
            feed.dataPromise = feed.acquireSyndication(feed.url);
            dataPromises.push(feed.dataPromise);
        });
    
        // Return when all asynchronous operations are complete
        return WinJS.Promise.join(dataPromises).then(function () {
            return blogs;
        });
    
    };
    
    function acquireSyndication(url) {
        return WinJS.xhr(
        {
            url: url,
            headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" }               
        });
    }
    
    function getBlogPosts() {
        getFeeds().then(function () {
            // Process each blog.
            blogs.forEach(function (feed) {
                feed.dataPromise.then(function (articlesResponse) {
                    var articleSyndication = articlesResponse.responseXML;
    
                    // Get the blog title and last updated date.
                    if (articleSyndication) {
                        // Get the blog title and last updated date.
                        feed.title = articleSyndication.querySelector(
                            "feed > title").textContent;
                        var ds = articleSyndication.querySelector(
                            "feed > updated").textContent;
                        var date = ds.substring(5, 7) + "-" +
                            ds.substring(8, 10) + "-" + ds.substring(0, 4);
                        feed.updated = "Last updated " + date;
                        // Process the blog posts.
                        getItemsFromXml(articleSyndication, blogPosts, feed);
                    }
                    else {
                        // There was an error loading the blog. 
                        feed.title = "Error loading blog";
                        feed.updated = "Error";
                        blogPosts.push({
                            group: feed,
                            key: "Error loading blog",
                            title: feed.url,
                            author: "Unknown",
                            month: "?",
                            day: "?",
                            year: "?",
                            content: "Unable to load the blog at " + feed.url
                        });
                    }
                });
            });
        });
    
        return blogPosts;
    }
    
    function getItemsFromXml(articleSyndication, blogPosts, feed) {
        var posts = articleSyndication.querySelectorAll("entry");
        // Process each blog post.
        for (var postIndex = 0; postIndex < posts.length; postIndex++) {
            var post = posts[postIndex];
            // Get the title, author, and date published.
            var postTitle = post.querySelector("title").textContent;
            var postAuthor = post.querySelector("author > name").textContent;
            var pds = post.querySelector("published").textContent;
            var postDate = pds.substring(5, 7) + "-" + pds.substring(8, 10)
                + "-" + pds.substring(0, 4);
            // Process the content so that it displays nicely.
            var staticContent = toStaticHTML(post.querySelector(
                "content").textContent);
            // Store the post info we care about in the array.
            blogPosts.push({
                group: feed, key: feed.title, title: postTitle, 
                author: postAuthor, pubDate: postDate, 
                backgroundImage: mediumGray, content: staticContent
            });
        }
    }
    
  5. Dans data.js, remplacez le code suivant :

    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);
    });
    

    par :

    var dataPromises = [];
    var blogs;
    
    var blogPosts = new WinJS.Binding.List();
    
    var list = getBlogPosts();
    var groupedItems = list.createGrouped(
        function groupKeySelector(item) { return item.group.key; },
        function groupDataSelector(item) { return item.group; }
    );
    

    Nous allons réutiliser le code dans createGrouped qui spécifie le regroupement —à savoir les fonctions groupKeySelector et groupDataSelector.

    Étant donné que nous avons modifié certains des noms de propriétés attendus par les modèles, nous devons apporter quelques mises à jour aux pages HTML. Plus spécifiquement, pour chaque propriété subtitle qui référence un élément (et non un groupe), nous devons remplacer subtitle par author. Pour chaque propriété description qui référence un élément, nous devons remplacer description par pubDate.

    Pour implémenter ces modifications dans l’interface utilisateur, voir l’une des sections suivantes :

    • Liaison de données exemples à l’interface utilisateur dans le modèle Fractionner
    • Liaison de données exemples à l’interface utilisateur dans le modèle Grille

Liaison de données exemples à l’interface utilisateur dans le modèle Fractionner

  1. Pour utiliser l’exemple de code dans le modèle Fractionner, ouvrez split.html.

  2. Dans split.html, nous devons modifier des lignes de l’élément DIV dont le nom de classe est itemtemplate. Remplacez cette ligne :

    
    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
    

    par :

    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: author"></h6>
    
  3. Par ailleurs, dans split.html, la section d’article (articlesection) contient des informations d’en-tête que nous devons mettre à jour. Remplacez cette ligne :

    <h4 class="article-subtitle" data-win-bind="textContent: subtitle"></h4>
    

    par :

    <h4 class="article-subtitle" data-win-bind="textContent: author"></h4>
    
  4. Ouvrez items.html.

    Le modèle d’élément WinJS défini dans le code HTML contient des éléments ListView arbitraires. Dans items.html, le modèle est utilisé pour afficher des groupes (blogs). La seule propriété de groupe que nous devons modifier ici est subtitle.

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: subtitle"></h6>
    
  5. Remplacez la propriété subtitle par updated, comme illustré ici :

    <h6 class="item-subtitle win-type-ellipsis"
        data-win-bind="textContent: updated"></h6>
    
  6. Enregistrez le projet, puis appuyez sur F5 pour déboguer l’application.

    Le titre de la page s’affiche immédiatement tandis que la récupération des données de flux prend un peu de temps. Si tout s’est passé comme prévu, vous devez voir chaque blog dans la page d’accueil. Cliquez sur un des blogs pour afficher les publications du blog dans l’affichage maître/détail.

Liaison de données exemples à l’interface utilisateur dans le modèle Grille

Avant de suivre ces étapes, mettez à jour le fichier de projet data.js comme indiqué dans Exemple de liaison de données à l’interface utilisateur.

  1. Pour utiliser le code d’exemple RSS dans le modèle Grille, ouvrez groupDetail.html.

    Cette page affiche un seul groupe (blog) et les éléments individuels (billets de blog) qui font partie du groupe.

  2. Dans groupDetail.html, nous devons modifier des lignes de l’élément DIV dont le nom de classe est item-info. Remplacez ces lignes :

    
    <h6 class="item-subtitle win-type-ellipsis"
        data-win-bind="textContent: subtitle"></h6>
    <h4 class="item-description" 
        data-win-bind="textContent: description"></h4>
    

    par celles-ci :

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: author"></h6>
    <h4 class="item-description" 
        data-win-bind="textContent: pubDate"></h4>
    

    Dans groupDetail.html, le modèle d’en-tête décrit des informations de groupe, et non d’éléments individuels. Nous n’avons donc pas à modifier la propriété subtitle. Voici le modèle d’en-tête :

    
    <div class="headertemplate" data-win-control="WinJS.Binding.Template">
        <h2 class="group-subtitle" data-win-bind="textContent: subtitle"></h2>
        <img class="group-image" src="#" 
            data-win-bind="src: backgroundImage; alt: title" />
        <h4 class="group-description" data-win-bind="innerHTML: description"></h4>
    </div>
    
  3. Toutefois, comme nous n’avons pas de propriété description pour chaque groupe (nous avons cette propriété pour les éléments), nous devons remplacer cette propriété par updated dans le code précédent, comme illustré ici.

    <h4 class="group-description" data-win-bind="innerHTML: updated"></h4>
    
  4. Ouvrez groupedItems.html, qui affiche tous les groupes et leurs billets de blog individuels.

  5. Dans cette page, le modèle d’élément générique WinJS affiche des éléments individuels (publications de blog). Nous devons donc mettre à jour la propriété subtitle. Modifiez ce qui suit :

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: subtitle"></h6>
    

    par :

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: author"></h6>
    
  6. Enregistrez le projet, puis appuyez sur F5 pour déboguer l’application.

    Le titre de la page s’affiche immédiatement tandis que la récupération des données de flux prend un peu de temps. Si les données sont retournées conformément aux prévisions, vous devez voir les éléments dans chaque blog de la page d’accueil. Cliquez sur un en-tête de groupe pour voir la page du groupe ou cliquez sur un élément pour voir un billet de blog individuel.

Ensemble du code pour data.js

Voici le code complet pour le fichier data.js. Le même fichier data.js est utilisé pour les exemples des modèles Grille et Fractionner présentés précédemment. Pour le fichier data.js du modèle Hub/Pivot, voir Lecteur Web JSON qui utilise le modèle Hub/Pivot. Pour le fichier data.js du modèle Hub, voir Lecteur Web JSON qui utilise le modèle Hub.


(function () {
    "use strict";

    
    var lightGray = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
    var mediumGray = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";


    var dataPromises = [];
    var blogs;

    var blogPosts = new WinJS.Binding.List();

    var list = getBlogPosts();
    var groupedItems = list.createGrouped(
        function groupKeySelector(item) { return item.group.key; },
        function groupDataSelector(item) { return item.group; }
    );

    WinJS.Namespace.define("Data", {
        items: groupedItems,
        groups: groupedItems.groups,
        getItemReference: getItemReference,
        getItemsFromGroup: getItemsFromGroup,
        resolveGroupReference: resolveGroupReference,
        resolveItemReference: resolveItemReference
    });

    // Get a reference for an item, using the group key and item title as a
    // unique reference to the item that can be easily serialized.
    function getItemReference(item) {
        return [item.group.key, item.title];
    }

    // 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; });
    }

    // Get the unique group corresponding to the provided group key.
    function resolveGroupReference(key) {
        return groupedItems.groups.getItemFromKey(key).data;
    }

    // Get a unique item from the provided string array, which should contain a
    // group key and an item title.
    function resolveItemReference(reference) {
        for (var i = 0; i < groupedItems.length; i++) {
            var item = groupedItems.getAt(i);
            if (item.group.key === reference[0] && item.title === reference[1]) {
                return item;
            }
        }
    }



    function getFeeds() {
        // Create an object for each feed.
        blogs = [
            {
                key: "blog1", url:
           'https://windowsteamblog.com/windows/b/developers/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            },
            {
                key: "blog2", url:
           'https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx',
                title: 'tbd', subtitle: 'subtitle', updated: 'tbd',
                backgroundImage: lightGray,
                acquireSyndication: acquireSyndication, dataPromise: null
            }]
        // Get the content for each feed in the blog's array.
        blogs.forEach(function (feed) {
            feed.dataPromise = feed.acquireSyndication(feed.url);
            dataPromises.push(feed.dataPromise);
        });

        // Return when all asynchronous operations are complete
        return WinJS.Promise.join(dataPromises).then(function () {
            return blogs;
        });

    };

    function acquireSyndication(url) {
        return WinJS.xhr({
            url: url,
            headers: { "If-Modified-Since": "Mon, 27 Mar 1972 00:00:00 GMT" }
        });
    }

    function getBlogPosts() {
        getFeeds().then(function () {
            // Process each blog.
            blogs.forEach(function (feed) {
                feed.dataPromise.then(function (articlesResponse) {
                    var articleSyndication = articlesResponse.responseXML;

                    if (articleSyndication) {
                        // Get the blog title and last updated date.
                        feed.title = articleSyndication.querySelector(
                            "feed > title").textContent;
                        var ds = articleSyndication.querySelector(
                            "feed > updated").textContent;
                        var date = ds.substring(5, 7) + "-" +
                            ds.substring(8, 10) + "-" + ds.substring(0, 4);
                        feed.updated = "Last updated " + date;
                        // Process the blog posts.
                        getItemsFromXml(articleSyndication, blogPosts, feed);
                    }
                    else {
                        // There was an error loading the blog. 
                        feed.title = "Error loading blog";
                        feed.updated = "Error";
                        blogPosts.push({
                            group: feed,
                            key: "Error loading blog",
                            title: feed.url,
                            author: "Unknown",
                            month: "?",
                            day: "?",
                            year: "?",
                            content: "Unable to load the blog at " + feed.url
                        });
                    }
                });
            });
        });

        return blogPosts;
    }

    function getItemsFromXml(articleSyndication, blogPosts, feed) {
        var posts = articleSyndication.querySelectorAll("entry");
        // Process each blog post.
        for (var postIndex = 0; postIndex < posts.length; postIndex++) {
            var post = posts[postIndex];
            // Get the title, author, and date published.
            var postTitle = post.querySelector("title").textContent;
            var postAuthor = post.querySelector("author > name").textContent;
            var pds = post.querySelector("published").textContent;
            var postDate = pds.substring(5, 7) + "-" + pds.substring(8, 10)
                + "-" + pds.substring(0, 4);
            // Process the content so that it displays nicely.
            var staticContent = toStaticHTML(post.querySelector(
                "content").textContent);
            // Store the post info we care about in the array.
            blogPosts.push({
                group: feed, key: feed.title, title: postTitle,
                author: postAuthor, pubDate: postDate,
                backgroundImage: mediumGray, content: staticContent
            });
        }
    }

})();

Rubriques associées

Modèles de projet JavaScript

Modèles de projet JavaScript

Ajout de données à un modèle de projet (C#, VB et C++)