Compartir a través de


Cómo personalizar los datos de la plantilla de Visual Studio (HTML)

[ Este artículo está destinado a desarrolladores de Windows 8.x y Windows Phone 8.x que escriben aplicaciones de Windows en tiempo de ejecución. Si estás desarrollando para Windows 10, consulta la documentación más reciente

En las plantillas Hub/Dinámica, Hub, Dinámica, Cuadrícula y División, el código que obtiene los datos necesarios para la aplicación se encuentra en el archivo data.js. Este archivo representa la muestra de origen de datos para la aplicación. El archivo data.js incluye datos estáticos que normalmente tienes que reemplazar por datos dinámicos. Por ejemplo, si tu aplicación realiza una sola solicitud xhr para obtener datos RSS o JSON, puede que te convenga incluir este código en data.js. Si incluyes el código aquí, podrás usar fácilmente tus propios datos sin cambiar el modelo de datos de las plantillas.

Sugerencia  Las plantillas Hub/Dinámica, Hub y Dinámica también recuperan datos estáticos de archivos .resjson que admiten globalización. Para obtener más información, consulta Ejemplo de enlace de datos a la interfaz de usuario en la plantilla Hub/Dinámica, Hub y Dinámica.

 

Cuando agregues tus propios datos a una aplicación, debes tener en cuenta una serie de factores:

  • Los grupos y los elementos están vinculados de manera intrínseca. La aplicación espera que los datos de elementos estén organizados en grupos. Puedes desvincularlos en tu propia implementación, pero necesitarás modificar el código para que la implementación funcione. En este tema se muestra el modo en que usan los grupos en el modelo de datos de la plantilla.
  • Cuando implementes datos personalizados para una aplicación en data.js, debes asegurarte de que los nombres de propiedad inherentes a tus datos personalizados están asignados a los nombres de propiedad que usa la plantilla. Puedes cambiar los nombres usados por la plantilla, pero para ello deberás revisar más código. En este tema se muestran algunos ejemplos de cómo hacerlo.

Elementos y grupos

Los datos de plantilla se almacenan en un WinJS.Binding.List. Este código muestra la declaración de la lista en el archivo data.js.

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

Una matriz de datos de elemento (en este ejemplo, sampleItems) se pasa a WinJS.Binding.List por medio de la función push, como se muestra aquí:

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

WinJS.Binding.List incluye la lógica interna para controlar la agrupación de los datos. La matriz sampleItems incluye una propiedad group que identifica el grupo al que pertenece el elemento (en los datos de muestra, los grupos se especifican en la matriz sampleGroups). Esta es la matriz de datos de elemento en la función generateSampleData:

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

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

    return sampleItems;
}

Cuando modifiques la aplicación para los datos personalizados, es posible que quieras seguir el mismo patrón para agrupar los datos. En el caso de los conjuntos de datos más pequeños, te recomendamos que uses WinJS.Binding.List para ListView. Si no agrupas los elementos, aún puedes usar WinJS.Binding.List, pero deberás modificar el código de plantilla donde la plantilla espere encontrar datos basados en grupo.

Sugerencia  WinJS.Binding.List es un origen de datos sincrónico que usa una matriz de JavaScript. En el caso de los conjuntos de datos de gran volumen (que pueden ser miles de elementos), puede que sea necesario usar un origen de datos asincrónico. Para obtener más información, consulta el tema sobre cómo usar ListView.

 

La función createGrouped de WinJS.Binding.List especifica cómo agrupar los elementos mediante una clave de grupo y un valor de grupo de elementos. Se llama a esta función en data.js. key y group son nombres de propiedad que se especifican en las matrices de datos de ejemplo.

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

Cuando la aplicación de plantilla necesita una lista de elementos, llama a getItemsFromGroup, que devuelve una WinJS.Binding.List que contiene solamente los elementos que pertenecen al grupo especificado.

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

Sugerencia  Las funciones tales como getItemsFromGroup, que llaman a createFiltered, crean una nueva proyección de la WinJS.Binding.List, y puede que tengas que deshacerte del objeto devuelto si sales de una página. Para deshacerte del objeto, llama al método WinJS.Binding.List.dispose.

 

La función define de la biblioteca de Windows para JavaScript expone los datos para que los use la aplicación mediante la especificación de un espacio de nombres llamado Data y de un conjunto de funciones de miembro público.

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

Si quieres definir un origen de datos distinto para cada página de la aplicación, o un modelo de datos diferente, tendrás que reemplazar todas las llamadas a estos miembros en el código JavaScript.

Enlace de datos de grupos y elementos a la interfaz de usuario

En el siguiente código se muestra un ejemplo de marcado para el control ListView. El origen de datos para el ListView se especifica en la propiedad itemDataSource, como se muestra aquí. Este ejemplo es de split.html de la plantilla dividida.


<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>

En el código anterior, una propiedad itemDataSource asociada a la página se asigna a la propiedad itemDataSource del control ListView.

En las plantillas, los datos suelen enlazarse a la interfaz de usuario en la función init o en la función ready que se define en el archivo .js asociado a cada página HTML. El código siguiente se incluye en la función init de split.html. En este código, la aplicación obtiene una referencia de grupo y después llama a getItemsFromGroup, que se implementa en data.js. Como ya hemos mencionado, getItemsFromGroup devuelve una WinJS.Binding.List que contiene solamente los elementos del grupo especificado.

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

A continuación enlazamos la lista devuelta de getItemsFromGroup a la propiedad itemDataSource de la página, que enlaza los datos a ListView, y también especificamos el controlador para la selección de elementos (_selectionChanged).


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

Para mostrar cada elemento en ListView, la aplicación asocia una plantilla a ListView, como se muestra aquí. Este código aparece en el marcado para el control ListView, y usa la propiedad itemTemplate para especificar un elemento DIV con un nombre de clase de itemtemplate.

itemTemplate: select('.itemtemplate')

Las plantillas WinJS, que se basan en WinJS.Binding.Template, se usan para dar formato a varias instancias de datos y visualizarlas. La plantilla que se usa con más frecuencia en las plantillas de cuadrícula y dividida es la plantilla de elementos que se usa para mostrar elementos en una ListView. Como cualquier objeto de plantilla WinJS, se declara agregando un atributo data-win-control y estableciendo el atributo en WinJS.Binding.Template. Este es el código HTML para itemtemplate en 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 se usa para un elemento ListView arbitrario. El elemento ListView puede ser un grupo o elemento de datos individual, según el contexto. Por ejemplo, en items.html, los elementos ListView son grupos.

Importante  Las plantillas que crees mediante WinJS.Binding.Template no están relacionadas con las plantillas de elemento y de proyecto de Visual Studio, como Cuadrícula y Dividir.

 

Las plantillas de proyecto esperan que los datos contengan determinadas propiedades y estas propiedades se denominan explícitamente en el código HTML. En el código HTML anterior de itemtemplate, verás propiedades como title y subtitle. Si los datos de la aplicación personalizada no usan estos nombres de propiedad específicos, debes hacer una de las siguientes acciones:

  • Asignar los datos a estos nombres de propiedades (normalmente en data.js), o
  • Corregir todas las referencias de código HTML y .js a estas propiedades en el código de plantilla, para que coincidan con los nombres de propiedades de los datos. Las propiedades usadas en las plantillas son:
    • title, subtitle, description y backgroundImage (propiedades de grupo y elemento)
    • group y content (propiedades de elemento)
    • key (propiedad de grupo)

Siguiendo el mismo patrón de la plantilla WinJS, la plantilla Aplicación de cuadrícula también usa headerTemplate en algunas de sus páginas HTML.

Ejemplo de enlace de datos a la interfaz de usuario en la plantilla Hub/Dinámica, Hub y Dinámica

En Visual Studio, las plantillas de proyecto Hub/Dinámica, Hub y Dinámica muestran cómo implementar dos orígenes de datos distintos:

  • Datos estáticos globalizados almacenados en archivos de recurso .resjson. Estos datos se utilizan en algunas de las secciones de la aplicación (controles PivotItem o HubSection).
  • Datos de muestra de data.js, que representa el modelo de datos. Este archivo es el mismo que en las plantillas Grid y Split. Los datos de muestra se usan en el control ListView en una de las secciones de la aplicación.

Las funciones declarativas del código HTML se usan para obtener inicialmente datos de muestra, y el modelo de datos es sincrónico de manera predeterminada. Para personalizar las plantillas para que usen datos dinámicos en todas las secciones es necesario realizar unos cuantos cambios en hub.html, hub.js y otros archivos. Las siguientes aplicaciones de muestra sirven como modelo de la personalización de las plantillas Hub/Dinámica y Hub para que sean compatibles con los datos asincrónicos:

Dado que los datos globalizados del archivo .resjson se reemplazan fácilmente, las aplicaciones de ejemplo dejan este recurso sin modificar. En las aplicaciones de ejemplo, los datos para los elementos <img> y el control ListView presentes en las secciones de la plantilla Hub/Dinámica se recuperan de manera asincrónica.

Para obtener más información acerca de cómo proporcionar datos globalizados en los archivos .resjson, consulta Inicio rápido: traducir recursos de interfaz de usuario.

Para admitir el enlace de datos asincrónicos en el control ListView de la plantilla Hub/Dinámica, reemplaza primero estas variables globales en hub.js que llaman al modelo de datos:

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

con estas declaraciones de variables:


var section3Group = "group2";
var section3Items;

También tienes que modificar la implementación de las funciones declarativas en hub.js. En la implementación de plantilla predeterminada, estas funciones dependen de los datos que ya están disponibles (por ejemplo, la llamada a section3Items.dataSource). Reemplaza este código:

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

con este:


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

Este código establece la función section3DataSource en nulo para evitar intentar enlazar los datos antes de que esté lista. Estableceremos el origen de datos posteriormente en la función de enlace de datos (_bindData o bindListView, en función de la aplicación de ejemplo).

Se llama a la función de enlace de ejemplo cuando los datos están disponibles. Para hacerlo, agregamos un agente de escucha para el evento dataReady del modelo de datos, definido en data.js de la aplicación de muestra.


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

La aplicación llama a la función de enlace de datos desde el controlador de eventos onDataCompleted (no se muestra). El código para la función _bindData del ejemplo de la plantilla Hub se muestra aquí. En este código, establecemos la propiedad itemDataSource de ListView.


_bindData: function (context, grp1Items, grp2Items) {

    var self = context;

    // . . .

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

    // . . .   

},

Si el botón Atrás se usa para navegar a la página, se llama directamente a la función de enlace de datos desde la función de inicialización de la página, porque no hay necesidad de esperar los nuevos datos.

Sugerencia  En el código de la plantilla Hub, para consultar el elemento ListView al DOM (almacenado en _section3lv), la aplicación llama a la función _hubReady desde el controlador de eventos loadingstatechanged del control de Hub. Este evento se activa solamente cuando la página de concentrador ha terminado de cargarse. Al usar este controlador de eventos, podemos consultar al DOM para que anide el elemento DIV asociado a ListView.

 

En relación con el código completo necesario para que los datos asincrónicos funcionen en las plantillas Hub/Dinámica y Hub, consulta Lector web de JSON que usa la plantilla Hub/Dinámica y Lector web de JSON que usa la plantilla Hub. Además de las personalizaciones que se describen aquí, hemos realizado los siguientes cambios a la aplicación de ejemplo:

  • Hemos incluido código en el modelo de datos (data.js) para recuperar los datos mediante una solicitud xhr y para analizar los datos JSON (de Flickr).
  • Hemos incluido código en el modelo de datos para administrar varias solicitudes de datos y activar el evento dataReady cuando se devuelven los datos.
  • Hemos incluido un cuadro de entrada en la interfaz de usuario para solicitar datos nuevos.
  • Hemos incluido una barra de progreso para mostrar el estado de la solicitud de los datos.
  • Hemos realizado adiciones de estilos CSS para el cuadro de entrada y la barra de progreso.
  • Hemos incluido funciones para inicializar la página después de que el control Hub se cargue por completo (como _hubReady o _hubReadyPhone).
  • Hemos modificado los elementos <img> de Hub/Dinámica o Hub para admitir eventos de clic (los archivos modificados son específicos de la plantilla).
  • Hemos modificado los archivos para enlazar datos asíncronos a los elementos <img> de Hub/Dinámica o Hub (los archivos modificados son específicos de la plantilla).
  • Hemos modificado hub.js para admitir la navegación a las imágenes desde los elementos <img> de Hub (los archivos modificados son específicos de la plantilla).
  • Hemos modificado item.html y item.js para admitir la visualización de imágenes únicas.

Ejemplo de enlace de datos a la interfaz de usuario (cuadrícula y dividida)

Esta sección muestra cómo puedes implementar tu propio origen de datos en las plantillas de proyecto Cuadrícula y Dividir. En este código de ejemplo se usa una solicitud xhr para generar datos RSS.

Importante  Para implementar datos asincrónicos en la plantilla de concentrador, consulta Enlazar datos a la interfaz de usuario en la plantilla de concentrador.

 

Actualización de data.js

  1. Creación de un nuevo proyecto en Visual Studio Usa la plantilla de proyecto Aplicación dividida o Aplicación de cuadrícula.

  2. En data.js, agrega las siguientes variables cerca del comienzo del archivo, después de la instrucción use strict:

    var lightGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY7h4+cp/AAhpA3h+ANDKAAAAAElFTkSuQmCC";
    var mediumGray = "data:image/png;base64,
        iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXY5g8dcZ/AAY/AsAlWFQ+AAAAAElFTkSuQmCC";
    
  3. En data.js, quita la función generateSampleData que contiene estas matrices: sampleGroups y sampleItems.

    Reemplazaremos estos datos con datos RSS. Aunque no usaremos la mayoría de las variables de marcador de posición, como groupDescription, reutilizaremos las imágenes de marcador de posición lightGray y mediumGray para que funcione el nuevo código.

  4. En la misma ubicación en la que hayas quitado generateSampleData, agrega el siguiente código a 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. En data.js, reemplaza este código:

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

    con este:

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

    Reutilizaremos el código en createGrouped que especifica —las funciones groupKeySelector y groupDataSelector de agrupación.

    Como hemos cambiado algunos de los nombres de propiedad usados en las plantillas, deberemos realizar unas cuantas actualizaciones en las páginas HTML. En concreto, para cualquier propiedad subtitle que haga referencia a un elemento (no a un grupo), deberemos cambiar subtitle por author. Para cualquier propiedad description que haga referencia a un elemento, deberemos cambiar description por pubDate.

    Para implementar estos cambios en la interfaz de usuario, consulta una de las siguientes secciones:

    • Enlace de datos de ejemplo a la interfaz de usuario en la plantilla dividida
    • Enlace de datos de ejemplo a la interfaz de usuario en la plantilla de cuadrícula

Enlace de datos de ejemplo a la interfaz de usuario en la plantilla dividida

  1. Para usar el código de ejemplo en la plantilla dividida, abre split.html.

  2. En split.html, deberemos cambiar algunas líneas en el elemento DIV que tiene un nombre de clase itemtemplate. Cambia esta línea:

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

    por este código:

    <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: author"></h6>
    
  3. También en split.html, la sección del artículo (articlesection) contiene información de encabezado que hay que actualizar. Cambia esta línea:

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

    por este código:

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

    La plantilla del elemento WinJS definida en el código HTML contiene elementos ListView arbitrarios. En items.html, la plantilla se usa para mostrar grupos (blogs). La única propiedad de grupo que debemos cambiar aquí es subtitle.

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: subtitle"></h6>
    
  5. Cambia la propiedad subtitle por updated, como se muestra aquí:

    <h6 class="item-subtitle win-type-ellipsis"
        data-win-bind="textContent: updated"></h6>
    
  6. Guarda el proyecto y presiona F5 para depurar la aplicación.

    Verás la página de título de inmediato, aunque hay un breve retraso mientras se recuperan los datos de fuente. Cuando se hayan cumplido todos los compromisos, verás cada blog en la página principal. Haz clic en uno de los blogs para ver las entradas del blog en la vista maestro y detalles.

Enlace de datos de ejemplo a la interfaz de usuario en la plantilla de cuadrícula

Antes de seguir estos pasos, actualiza el archivo de proyecto data.js tal y como se describe en Ejemplo de enlace de datos a la interfaz de usuario.

  1. Para usar el código de ejemplo de RSS en la plantilla Cuadrícula, abre groupDetail.html.

    Esta página muestra un solo grupo (un blog) y los elementos individuales (entradas de blog) que forman parte del grupo.

  2. En groupDetail.html, tenemos que cambiar algunas líneas en el elemento DIV que tiene un nombre de clase item-info. Cambia estas líneas:

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

    a estas:

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

    En groupDetail.html, la plantilla de encabezado describe la información de grupo y no los elementos individuales. Por eso no es necesario que cambiemos la propiedad subtitle. Esta es la plantilla de encabezado:

    
    <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. Sin embargo, no tenemos ninguna propiedad description para cada grupo (tenemos esta propiedad para los elementos), así que tenemos que cambiar esta propiedad por updated en el código anterior, como se muestra aquí:

    <h4 class="group-description" data-win-bind="innerHTML: updated"></h4>
    
  4. Abre groupedItems.html, que muestra todos los grupos y sus entradas de blog individuales.

  5. En esta página, la plantilla de elemento WinJS genérica muestra los elementos individuales (entradas de blog), de modo que debemos actualizar la propiedad subtitle. Cambia esto:

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

    por este código:

    <h6 class="item-subtitle win-type-ellipsis" 
        data-win-bind="textContent: author"></h6>
    
  6. Guarda el proyecto y presiona F5 para depurar la aplicación.

    Verás la página de título de inmediato, aunque hay un breve retraso mientras se recuperan los datos de fuente. Cuando se devuelvan los datos, como esperamos, verás los elementos de cada blog en la página principal. Haz clic en un encabezado de grupo para ver la página de grupo, o en un elemento para ver una entrada de blog individual.

Lista de códigos para data.js

Esta es la lista completa de códigos para data.js. El mismo archivo data.js se usa tanto para los ejemplos de plantilla dividida y de cuadrícula que se muestran anteriormente. Para el archivo data.js para la plantilla Hub/Dinámica, consulta Lector web de JSON que usa la plantilla Hub/Dinámica. Para el archivo data.js para la plantilla Hub, consulta Lector web de JSON que usa la plantilla 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
            });
        }
    }

})();

Temas relacionados

Plantillas de proyecto de JavaScript

Plantillas de elemento de JavaScript

Agregar datos a una plantilla de proyecto (C#, VB y C++)