IndexedDB: Recuperando los datos almacenados

IndexedDB: Recuperando los datos almacenados

IndexedDB: El camino hasta ahora

Este es el tercer artículo sobre IndexedDB, el sistema de almacenamiento local de HTML5. Si acabas de llegar, necesitarás leer los dos primeros para poder entender el funcionamiento de IndexedDB:

  1. IndexedDB: Tu base de datos local en HTML5” Descubre cómo crear una base de datos y cómo agregarle un almacén de objetos a modo de tabla de nuestra base de datos, con unos índices o llaves: primaria, índice y única.
  2. IndexedDB: Agregando objetos al almacén” Empieza a sacar partido a tu base de datos IndexedDB agregando objetos al almacén.

Una  vez hayas leído y comprendido qué estamos haciendo con IndexedDB, puedes adentrarse sin miedo en esta tercera entrega, en la que mostraremos cómo recuperar la información almacenada en nuestro almacén de objetos.

Cómo no, aquí dejo la versión en vídeo del artículo:

La recuperación de datos en IndexedDB

Como es de suponer, no tiene ningún sentido utilizar una base de datos sin poder recuperar la información en ella almacenada. En el caso de IndexedDB, estamos hablando de almacenes de objetos, por lo que la información que retornaremos serán objetos. Pero… ¿qué recuperación de datos tenemos?

Por defecto, con IndexedDB podemos recuperar todos los elementos de un almacén de objetos, ordenados por su clave primaria. Recordemos que al crear un almacén de objetos indicamos qué propiedad de los objetos a almacenar se comportará como si de un índice primario de una BD se tratase.

Eso sí, no sólo recuperamos la información en base a su clave primaria. Cuando definimos los almacenes, también decidimos agregar nuevos índices, por lo que también podremos recuperar los objetos ordenados según cualquiera de los índices, no sólo por el primario.

Por “último”, podemos retornar un único objeto, indicando el valor que tiene en la propiedad que actúa como clave primaria.

Así pues, la recuperación de datos en IndexedDB es más que suficiente para la gran mayoría de lso casos… algo que unido a la posibilidad de hacer búsquedas dentro de los almacenes (de lo que hablaremos en un artículo más adelante) se cubre un amplio espectro (si no todo) de la recuperación de datos.

Cómo vamos a abordar la recuperación de datos en IndexedDB

Para explicar la recuperación de los objetos almacenados en nuestro almacén en IndexedDB, vamos a continuar ampliando el ejemplo de los dos primeros artículos.

En esta ocasión, lo que vamos a hacer es mostrar en una tabla, debajo del formulario, el listado de objetos agregados en nuestra base de datos IndexedDB. La información de cada objeto que se mostrará en la tabla será su DNI y nombre.

Cada vez que se agregue una nueva persona al almacén, el sistema recargará la tabla de personas existentes en nuestro almacén.

Además, permitiremos que los elementos de la tabla se puedan ordenar por nombre, utilizando así el índice by_name que existe en el almacén people.

Por último, podemos ver los detalles de un elemento, de forma que al pinchar en un botón se muestre una alerta con la info del objeto en cuestión.

Bueno, mucho por hacer y poco tiempo así que vamos allá!

Adaptando el HTML para nuestro objetivo

Queremos un listado de objetos, por lo que después de nuestro formulario, debemos colocar código HTML que podamos utilizar para, cuando sea preciso, introducir el listado, así que vamos a crear un div que contenga una tabla “sin elementos”

<hr>
<div id="elements">
    <table>
        <caption>Persons</caption>
        <thead>
            <tr>
                <th>DNI</th>
                <th>Name</th>
                <th> </th>
            </tr>
        </thead>
        <tbody id="elementsList">
            <tr>
                <td colspan="3">Not elements to show</td>
            </tr>
        </tbody>
    </table>
</div>

Cuando recuperemos los objetos de nuestro almacén, incluiremos el HTML dentro del tbody.

El Javascript para listar los objetos de nuestro almacén en la base de datos IndexedDB

Vamos a definir una función que llamaremos loadAll, en cuyo interior tendremos el código para que se carguen todos los elementos del almacén. Esta función será llamada cuando se cargue la web y cuando un elemento se agregue correctamente. Para conseguir esto que queremos, sólo debemos llamar a loadAll dentro de las funciones startDB y add… pero como queremos que sólo se ejecute cuando todo funciona correctamente, en el caso de startDB se llamará a loadAll cuando la apertura de la base de datos se realice correctamente (o sea, en dataBase.onsuccess) y en el caso de la función add, cuando el objeto se agregue sin problemas al almacén (lo que ocurre cuando la transacción finaliza correctamente: en transaction.oncomplete).

Agregando lo indicado a nuestro Javascript, tenemos que el contenido existente dentro de la etiqueta script es:

var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

var dataBase = null;

function startDB() {

    dataBase = indexedDB.open('object', 1);

    dataBase.onupgradeneeded = function (e) {
        var active = dataBase.result;

        var object = active.createObjectStore("people", {keyPath: 'id', autoIncrement: true});
        object.createIndex('by_name', 'name', {unique: false});
        object.createIndex('by_dni', 'dni', {unique: true});
    };

    dataBase.onsuccess = function (e) {
        alert('Database loaded');
        loadAll();
    };
    dataBase.onerror = function (e) {
        alert('Error loading database');
    };
}

function add() {

    var active = dataBase.result;
    var data = active.transaction(["people"], "readwrite");
    var object = data.objectStore("people");

    var request = object.put({
        dni: document.querySelector("#dni").value,
        name: document.querySelector("#name").value,
        surname: document.querySelector("#surname").value
    });

    request.onerror = function (e) {
        alert(request.error.name + '\n\n' + request.error.message);
    };

    data.oncomplete = function (e) {
        document.querySelector('#dni').value = '';
        document.querySelector('#name').value = '';
        document.querySelector('#surname').value = '';
        alert('Object successfully added');
        loadAll();
    };
}

function loadAll() {

}

La lógica de loadAll para recuperar los objetos de nuestra BD IndexedDB

¿Cual ha de ser la lógica dentro de loadAll? Pues al igual que en el caso de add, lo primero que debemos hacer es recuperar la conexión activa a nuestra base de datos object:

var active = dataBase.result;

Con esta conexión disponible en la variable active, debemos iniciar (al igual que en add) una transacción, puesto que vamos a trabajar con datos… pero como en este caso sólo buscamos recuperar información, el modo de la transacción será “readonly” e involucrará al almacén people

var active = dataBase.result;
var data = active.transaction(["people"], "readonly");

Bien! Ya tenemos la transacción iniciada. Una vez iniciada, debemos indicar qué almacén queremos utilizar en la transacción, por lo que nos toca crear nuevamente una variable object que almacene esa info:

var active = dataBase.result;
var data = active.transaction(["people"], "readonly");
var object = data.objectStore("people");

Perfecto! Hasta aquí, hemos seguido los mismos pasos que tuvimos en cuenta a la hora de agregar un objeto al almacén… ahora empezamos a alejarnos.

Vamos a declarar una variable elements que iniciaremos como un array. La idea de esta variable es que vayamos almacenando en su interior cada uno de los objetos recuperados:

var active = dataBase.result;
var data = active.transaction(["people"], "readonly");
var object = data.objectStore("people");

var elements = [];

El siguiente paso es atacar al contenido para recuperar los datos.

Como vamos a recuperar la información en base a la clave primaria del almacén, sólo debemos empezar a recorrer el almacén, puesto que éste ya nos devolverá los objetos ordenados por su clave primaria.

A medida que recorramos el almacén, iremos depositando cada objeto en elements y, una vez finalice la transacción correctamente, generaremos el HTML a incluir en el cuerpo de la tabla.

Recorriendo un almacén de objetos en IndexedDB

Para recorrer un almacén, sólo debemos ejecutar el método openCursor. Con openCursor, hacemos una especie de foreach, de forma que por cada “bucle” obtendremos un objeto.

¿Cómo utilizamos openCursor? Pues de la siguiente manera:

object.openCursor().onsuccess = function (e) {


};

Bueno, podemos ver cómo openCursor() se ejecuta sobre object, lo cual es lógico porque en object tenemos referenciado nuestro almacén people. Pero… ¿por qué onsuccess? Pues porque, al igual que con add y startBD, nosotros queremos llevar a cabo una acción sí y sólo sí se tiene éxito en el recorrido del almacén.

Lo que debemos hacer en su interior es recuperar el objeto:

var result = e.target.result;

y si no es nulo, agregarlo a elements:

if (result === null) {
    return;
}

elements.push(result.value);

Por último, tenemos que indicar que queremos que siga recorriendo el almacén, lo que hacemos con:

result.continue();

Quedando este método de la siguiente manera:

object.openCursor().onsuccess = function (e) {

    var result = e.target.result;

    if (result === null) {
        return;
    }

    elements.push(result.value);
    result.continue();

};

Para finalizar esta función, debemos incorporar el código HTML cuando la transacción finalice correctamente, como es un concepto que ya vimos en el anterior artículo, el resultado sería:

data.oncomplete = function () {

    var outerHTML = '';

    for (var key in elements) {

        outerHTML += '\n\
                        <tr>\n\
                            <td>' + elements[key].dni + '</td>\n\
                            <td>' + elements[key].name + '</td>\n\
                            <td>\n\
                                <button type="button" onclick="load(' + elements[key].id + ')">Details</button>\n\
                            </td>\n\
                        </tr>';

    }

    elements = [];
    document.querySelector("#elementsList").innerHTML = outerHTML;
};

Llegados este punto, el código de nuestro documento debería ser:

<!DOCTYPE html>
<!--
    Author: Rolando Caldas Sanchez
    Blog: http://rolandocaldas.com/
    Google+: https://plus.google.com/+RolandoCaldasSanchez
    Linkedin: http://www.linkedin.com/in/rolandocaldas
    Twitter: https://twitter.com/rolando_caldas
    This file is part of an article:
    http://rolandocaldas.com/html5/indexeddb-recuperando-los-datos-almacenados
-->
<html>
    <head>
        <meta charset="UTF-8">
        <title>IndexedDB: Local Database with HTML5</title>
        <script type="text/javascript">
            var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

            var dataBase = null;

            function startDB() {

                dataBase = indexedDB.open('object', 1);

                dataBase.onupgradeneeded = function (e) {
                    var active = dataBase.result;

                    var object = active.createObjectStore("people", {keyPath: 'id', autoIncrement: true});
                    object.createIndex('by_name', 'name', {unique: false});
                    object.createIndex('by_dni', 'dni', {unique: true});
                };

                dataBase.onsuccess = function (e) {
                    alert('Database loaded');
                    loadAll();
                };
                dataBase.onerror = function (e) {
                    alert('Error loading database');
                };
            }

            function add() {

                var active = dataBase.result;
                var data = active.transaction(["people"], "readwrite");
                var object = data.objectStore("people");

                var request = object.put({
                    dni: document.querySelector("#dni").value,
                    name: document.querySelector("#name").value,
                    surname: document.querySelector("#surname").value
                });

                request.onerror = function (e) {
                    alert(request.error.name + '\n\n' + request.error.message);
                };

                data.oncomplete = function (e) {
                    document.querySelector('#dni').value = '';
                    document.querySelector('#name').value = '';
                    document.querySelector('#surname').value = '';
                    alert('Object successfully added');
                    loadAll();
                };
            }

            function loadAll() {

                var active = dataBase.result;
                var data = active.transaction(["people"], "readonly");
                var object = data.objectStore("people");

                var elements = [];

                object.openCursor().onsuccess = function (e) {

                    var result = e.target.result;

                    if (result === null) {
                        return;
                    }

                    elements.push(result.value);
                    result.continue();

                };

                data.oncomplete = function () {

                    var outerHTML = '';

                    for (var key in elements) {

                        outerHTML += '\n\
                        <tr>\n\
                            <td>' + elements[key].dni + '</td>\n\
                            <td>' + elements[key].name + '</td>\n\
                            <td>\n\
                                <button type="button" onclick="load(' + elements[key].id + ')">Details</button>\n\
                            </td>\n\
                        </tr>';

                    }

                    elements = [];
                    document.querySelector("#elementsList").innerHTML = outerHTML;
                };

            }

        </script>
    </head>
    <body onload="startDB();">
        <input type="text" id="dni" placeholder="Enter dni" />
        <input type="text" id="name" placeholder="Enter name" />
        <input type="text" id="surname" placeholder="Enter surname" />
        <button type="button" onclick="add();">Save</button>
        <hr>
        <div id="elements">
            <table>
                <caption>Persons</caption>
                <thead>
                    <tr>
                        <th>DNI</th>
                        <th>Name</th>
                        <th> </th>
                    </tr>
                </thead>
                <tbody id="elementsList">
                    <tr>
                        <td colspan="3">Not elements to show</td>
                    </tr>
                </tbody>
            </table>
        </div>        
    </body>
</html>

El código ya es funcional, por lo que podemos probarlo y comprobar si hemos hecho todo correctamente o no:

Obteniendo un objeto de nuestro almacén en IndexedDB

Bien! ya tenemos nuestra tabla con el listado. Sin embargo, el botoncito de “Details” aún no funciona. ¿Qué debería hacer? En principio, ese botón ejecutará la función load cuando se clique en él, enviado la propiedad id del objeto como parámetro.

Bueno, lo que debemos hacer es escribir la función JS con el código necesario para que se muestre una alerta con la vista de detalle del objeto almacenado en el almacén people cuyo id sea el enviado por parámetro.

function load(id) {
    var active = dataBase.result;
    var data = active.transaction(["people"], "readonly");
    var object = data.objectStore("people");

}

Lo que tenemos, hasta ahora, es un código que nos resulta ya familiar. Por un lado recuperamos la conexión activa e iniciamos una transacción sobre la cual obtenemos el acceso al almacén people.

Para poder recuperar un objeto, utilizamos la siguiente línea:

var request = object.get(parseInt(id));

Con esa línea, asignamos a request el resultado de solicitar el objeto cuya llave primaria (keyPath) sea id. La búsqueda la realiza sobre la llave primaria puesto que no se especifica ningún índice a utilizar.

Como ya es habitual, sobre el resultado crearemos el método onsuccess, que será ejecutado cuando el objeto se recupera correctamente. Es en este método dónde haremos que salte la alerta con la info de detalle:

request.onsuccess = function () {
    var result = request.result;

    if (result !== undefined) {
        alert("ID: " + result.id + "\n\
               DNI " + result.dni + "\n\
               Name: " + result.name + "\n\
               Surname: " + result.surname);
    }
};

Utilizando un índice para obtener un objeto de nuestro almacén en IndexedDB

Hasta ahora, hemos recuperado objetos de nuestro almacén utilizando la clave primaria (keyPath) como índice. Sin embargo, tenemos una serie de índices declarados para nuestro almacén (by_name y by_dni) que podemos utilizar.

Lo primero que vamos a hacer es alterar nuestra función loadAll para que además del botón “Details” exista un “Details DNI” que nos permita mostrar la vista de detalle de una persona en función de su DNI:

function loadAll() {
    var active = dataBase.result;
    var data = active.transaction(["people"], "readonly");
    var object = data.objectStore("people");

    var elements = [];

    object.openCursor().onsuccess = function (e) {

        var result = e.target.result;

        if (result === null) {
            return;
        }

        elements.push(result.value);
        result.continue();

    };

    data.oncomplete = function () {

        var outerHTML = '';

        for (var key in elements) {

            outerHTML += '\n\
            <tr>\n\
                <td>' + elements[key].dni + '</td>\n\
                <td>' + elements[key].name + '</td>\n\
                <td>\n\
                    <button type="button" onclick="load(' + elements[key].id + ')">Details</button>\n\
                    <button type="button" onclick="loadByDni(' + elements[key].dni + ')">Details DNI</button>\n\
                </td>\n\
            </tr>';

        }

        elements = [];
        document.querySelector("#elementsList").innerHTML = outerHTML;
    };
}

El siguiente paso es duplicar nuestra función load como loadByDni:

function loadByDni(id) {
    var active = dataBase.result;
    var data = active.transaction(["people"], "readonly");
    var object = data.objectStore("people");

    var request = object.get(parseInt(id));

    request.onsuccess = function () {
        var result = request.result;

        if (result !== undefined) {
            alert("ID: " + result.id + "\n\
                   DNI " + result.dni + "\n\
                   Name: " + result.name + "\n\
                   Surname: " + result.surname);
        }
    };
}

Debemos modificar esta función loadByDni para que la búsqueda la haga utilizando el índice by_dni en vez de la clave primaria. Para ello, necesitamos indicar al objeto que contiene el almacén people que debe utilizarse el índice by_name:

var index = object.index("by_dni");

Por último, el método get ya no debemos ejecutarlo sobre object porque entonces no estaríamos utilizando el índice indicado. Debemos aplicarlo sobre index, por lo que la función quedaría de la siguiente manera:

function loadByDni(dni) {
    var active = dataBase.result;
    var data = active.transaction(["people"], "readonly");
    var object = data.objectStore("people");
    var index = object.index("by_dni");
    var request = index.get(String(dni));

    request.onsuccess = function () {
        var result = request.result;

        if (result !== undefined) {
            alert("ID: " + result.id + "\n\
                   DNI " + result.dni + "\n\
                   Name: " + result.name + "\n\
                   Surname: " + result.surname);
        }
    };
}

Ordenando los objetos de nuestro almacén IndexedDB por un índice

Para ir finalizando el artículo, lo último que vamos a hace es incluir un botón para ordenar el listado de objetos por el nombre de las personas, o sea, la propiedad name.

Como siempre, lo primero es tocar nuestro HMTL (en este caso el body) para incorporar el botón que nos permita ordenar el resultado:

<button type="button" onclick="loadAllByName();">Order by name</button>

En el botón, ejecutamos la función loadAllByName tras hacer clic en él. Esta función de Javascript es un duplicado de loadAll, por lo que tendríamos:

function loadAllByName() {
    var active = dataBase.result;
    var data = active.transaction(["people"], "readonly");
    var object = data.objectStore("people");

    var elements = [];

    object.openCursor().onsuccess = function (e) {

        var result = e.target.result;

        if (result === null) {
            return;
        }

        elements.push(result.value);
        result.continue();

    };

    data.oncomplete = function () {

        var outerHTML = '';

        for (var key in elements) {

            outerHTML += '\n\
            <tr>\n\
                <td>' + elements[key].dni + '</td>\n\
                <td>' + elements[key].name + '</td>\n\
                <td>\n\
                    <button type="button" onclick="load(' + elements[key].id + ')">Details</button>\n\
                    <button type="button" onclick="loadByDni(' + elements[key].dni + ')">Details DNI</button>\n\
                </td>\n\
            </tr>';

        }

        elements = [];
        document.querySelector("#elementsList").innerHTML = outerHTML;
    };
}

Al igual que hicimos con loadByDni, necesitamos indicar el índice y realizar  la solicitud sobre la variable que incluye tanto el almacén como el índice a utilizar, por lo que aplicando la misma sintaxis que en loadByDni la función quedaría:

function loadAllByName() {
    var active = dataBase.result;
    var data = active.transaction(["people"], "readonly");
    var object = data.objectStore("people");
    var index = object.index("by_name");

    var elements = [];

    index.openCursor().onsuccess = function (e) {

        var result = e.target.result;

        if (result === null) {
            return;
        }

        elements.push(result.value);
        result.continue();

    };

    data.oncomplete = function () {

        var outerHTML = '';

        for (var key in elements) {

            outerHTML += '\n\
            <tr>\n\
                <td>' + elements[key].dni + '</td>\n\
                <td>' + elements[key].name + '</td>\n\
                <td>\n\
                    <button type="button" onclick="load(' + elements[key].id + ')">Details</button>\n\
                    <button type="button" onclick="loadByDni(' + elements[key].dni + ')">Details DNI</button>\n\
                </td>\n\
            </tr>';

        }

        elements = [];
        document.querySelector("#elementsList").innerHTML = outerHTML;
    };
}

Y con esto, ya tenemos todo listo!!

Listando y ordenando el contenido de un almacén de objetos en IndexedDB: Código final

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>IndexedDB: Local Database with HTML5</title>
        <script type="text/javascript">
            var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
            var dataBase = null;

            function startDB() {

                dataBase = indexedDB.open("object", 1);

                dataBase.onupgradeneeded = function (e) {

                    var active = dataBase.result;
                    var object = active.createObjectStore("people", {keyPath: 'id', autoIncrement: true});
                    object.createIndex('by_name', 'name', {unique: false});
                    object.createIndex('by_dni', 'dni', {unique: true});

                };

                dataBase.onsuccess = function (e) {
                    //    alert('Database loaded');
                    loadAll();
                };

                dataBase.onerror = function (e) {
                    alert('Error loading database');
                };

            }

            function add() {
                var active = dataBase.result;
                var data = active.transaction(["people"], "readwrite");
                var object = data.objectStore("people");

                var request = object.put({
                    dni: document.querySelector("#dni").value,
                    name: document.querySelector("#name").value,
                    surname: document.querySelector("#surname").value
                });

                request.onerror = function (e) {
                    alert(request.error.name + '\n\n' + request.error.message);
                };

                data.oncomplete = function (e) {

                    document.querySelector('#dni').value = '';
                    document.querySelector('#name').value = '';
                    document.querySelector('#surname').value = '';
                    alert('Object successfully added');
                    loadAll();
                };

            }

            function load(id) {
                var active = dataBase.result;
                var data = active.transaction(["people"], "readonly");
                var object = data.objectStore("people");

                var request = object.get(parseInt(id));

                request.onsuccess = function () {
                    var result = request.result;

                    if (result !== undefined) {
                        alert("ID: " + result.id + "\n\
                               DNI " + result.dni + "\n\
                               Name: " + result.name + "\n\
                               Surname: " + result.surname);
                    }
                };
            }

            function loadByDni(dni) {
                var active = dataBase.result;
                var data = active.transaction(["people"], "readonly");
                var object = data.objectStore("people");
                var index = object.index("by_dni");
                var request = index.get(String(dni));

                request.onsuccess = function () {
                    var result = request.result;

                    if (result !== undefined) {
                        alert("ID: " + result.id + "\n\
                               DNI " + result.dni + "\n\
                               Name: " + result.name + "\n\
                               Surname: " + result.surname);
                    }
                };
            }

            function loadAll() {
                var active = dataBase.result;
                var data = active.transaction(["people"], "readonly");
                var object = data.objectStore("people");

                var elements = [];

                object.openCursor().onsuccess = function (e) {

                    var result = e.target.result;

                    if (result === null) {
                        return;
                    }

                    elements.push(result.value);
                    result.continue();

                };

                data.oncomplete = function () {

                    var outerHTML = '';

                    for (var key in elements) {

                        outerHTML += '\n\
                        <tr>\n\
                            <td>' + elements[key].dni + '</td>\n\
                            <td>' + elements[key].name + '</td>\n\
                            <td>\n\
                                <button type="button" onclick="load(' + elements[key].id + ')">Details</button>\n\
                                <button type="button" onclick="loadByDni(' + elements[key].dni + ')">Details DNI</button>\n\
                            </td>\n\
                        </tr>';

                    }

                    elements = [];
                    document.querySelector("#elementsList").innerHTML = outerHTML;
                };
            }
            
            function loadAllByName() {
                var active = dataBase.result;
                var data = active.transaction(["people"], "readonly");
                var object = data.objectStore("people");
                var index = object.index("by_name");
                
                var elements = [];

                index.openCursor().onsuccess = function (e) {

                    var result = e.target.result;

                    if (result === null) {
                        return;
                    }

                    elements.push(result.value);
                    result.continue();

                };

                data.oncomplete = function () {

                    var outerHTML = '';

                    for (var key in elements) {

                        outerHTML += '\n\
                        <tr>\n\
                            <td>' + elements[key].dni + '</td>\n\
                            <td>' + elements[key].name + '</td>\n\
                            <td>\n\
                                <button type="button" onclick="load(' + elements[key].id + ')">Details</button>\n\
                                <button type="button" onclick="loadByDni(' + elements[key].dni + ')">Details DNI</button>\n\
                            </td>\n\
                        </tr>';

                    }

                    elements = [];
                    document.querySelector("#elementsList").innerHTML = outerHTML;
                };
            }

        </script>            
    </head>
    <body onload="startDB();">
        <input type="text" id="dni" placeholder="Enter dni" />
        <input type="text" id="name" placeholder="Enter name" />
        <input type="text" id="surname" placeholder="Enter surname" />
        <button type="button" onclick="add();">Save</button>
        <hr>
        <div id="elements">
            <table>
                <caption>Persons</caption>
                <thead>
                    <tr>
                        <th>DNI</th>
                        <th>Name</th>
                        <th> </th>
                    </tr>
                </thead>
                <tbody id="elementsList">
                    <tr>
                        <td colspan="3">Not elements to show</td>
                    </tr>
                </tbody>
            </table>
        </div>
        <button type="button" onclick="loadAllByName();">Order by name</button>
    </body>
</html>

Recursos

Código en GitHub:
https://github.com/rolando-caldas/IndexedDB/tree/master/src/03-GetObjectStore

Video en mi canal de youtube:
https://youtu.be/RN9CrQFvUws

21 pensamientos en “IndexedDB: Recuperando los datos almacenados

  1. Me encanta esta serie de articulos, me ha ayudado bastante. Me gustaria sabe cuando saldrá el siguiente articulo. Me muero por seguir aprendiendo.

    1. Muchas gracias! Está siendo un inicio de año movidito… en febrero volveré a la carga… a partir del 9 de febrero volveremos a hablar de IndexedDB y Cordova

      saludos!

  2. Buenas tardes. Gracias por estas magníficas clases. Realmente considero que están muy bien explicadas y por supuesto me has ayudado a tope. Tengo un par de preguntas de novato….
    1.- Físicamente, dónde se almacena toda esta información, tanto la de localStorage, como las Bases de Datos.
    2.- No me funciona ni en Mozilla, ni en Iexplore. Sí funciona perfectamente en Chrome. ¿?
    3.- La base de datos es distinta para cada uno de los navegadores…??, me explico, si desarrollo una app que almacene en información en una bbdd, ¿ no comparten la mismas bases de datos y tablas.. ??
    4.- Hay alguna forma de sincronizar esta base de datos con la del lado del servidor MySQL…..

    Bueno, ya no son un par de preguntitas, pero mi ignorancia es proporcional al tiempo que intento aprender.

    De nuevo muchísimas gracias por estos artículos y enhorabuena….!!!!

  3. Hola, estoy intentando hacer una aplicación guardando todo en una base de datos. ¿Hay alguna manera de obtener resultados consultando por más de una columna?. En tu ejemplo, si queremos buscar los datos de alguien por su nombre y apellido en lugar de sólo por el dni. ¿Qué habría que hacer?
    Gracias!

    1. buenas, creando un índice con ambos campos:

      object.createIndex(‘by_name_dni’, ‘[name, dni]’);

      y para buscar

      objectStore.index(‘by_name_dni’).get([‘el nombre’, ‘el dni’]

  4. Me gustaria saber como hago estos mis pagos con varios registros ejemplo:
    nombre, apellidos, edad, sexo , fecha de nacimiento

  5. Hola Rolando,

    Felicidades por estos vídeos de indexedDB son excelentes, bueno estos y los otros que has compartido, me han han servido de aprendizaje, consulta y para aplicarlo.

    Ahora, me gustaría saber cuando será la próxima entrega de esta serie; para ver lo que habías comentado en tu ultimo vídeo (IndexedDB 3ra. entrega), editar un objeto de nuestro almacén, eliminar un objeto del almacén y las búsquedas.

    Bueno, me despido y me mantendré muy atento para ver tu próximo vídeo tutorial.

    Y de antemano gracias por tus aportes.

  6. Comparto las felicitaciones de otros compañeros porque es un tema superinteresante y está muy bien explicado paso a paso y bastante completo como para empezar a hacer pruebas con este estándar (no sé como llamarlo pero entiendo que pretende serlo).

    Un saluo y gracias, seguiré por aquí leyendo sin falta!
    JC

  7. Rolando, buenos días! Estoy siguiendo tus vídeos en YouTube. Lo entiendo casi todo dado que para mí Javascript es un poco el aterrador. Tengo una pregunta, yo he creado el mismo IndexedDB según tu vídeo, pero al revés del DNI yo puse Email, lógicamente cambiando todos los campos donde aparece ‘dni’ para ‘email’. Sin embargo, al pulsar en el botón DETAILS EMAIL el código no funciona. Funciona sí para DETAILS. Crees que el problema pueda estar en ‘parseInt’? Gracias por tus vídeos y tiempo. Un saludo, Rob.

  8. Carlos HIdalgo
    Responder

    Permitame agradecer por sus aportes sobre indexexdb
    y permitame ademas consultarle si podria indicar como funciona por ejemplo consultas con determinados filtros ( ejemplo filtrar los datos por fecha) y como imprimir los datos
    mil gracias por su atencion

    1. Buenas

      sobre la impresión de datos, seria igual que cómo se hace en este artículo. Sobre los filtros, espero retomar pronto el pulso al blog para continuar hablando de indexedDB que tengo ganas y queda mucho por decir.

      saludos!

  9. Carlos HIdalgo
    Responder

    Mil gracias por su atenta comunicacion
    Espero sus articulos considerando que como usted dice “queda mucho por decir”

  10. no se que me da mas asco de todo esto, si tu forma de explicar (al menos a mi me cuesta ‘tela’ entenderte) o la presentacion que haces del codigo, con saltos de linea sin fundamentos y defectos de diseño que matan a cualquiera acostumbrado a ver codigo.

    pero en fin!, te agradezco el rato que he pasado intentando leerte porque lo cierto es que no conocia indexedDB que de HTML5 tiene lo que tengo yo de marciano.

    ahora! te aseguro que no vuelvo por aqui 😀

  11. Hola.
    Antes de nada agradecer que compartas de forma tan didáctica tus conocimientos. No podría estar más en desacuerdo con el comentario de Antonio que me precede.

    La cuestión que quiero plantear es la siguiente: probando tu código, me he dado cuenta de que si en el campo dni introducimos valores numéricos exclusivamente, no hay ningún problema y todo funciona correctamente. Pero si introducimos algún carácter alfabético (como en nuestros NIFs), la función loadByDni() no funciona, y en consola aparece el siguiente error:
    indexedDB.html:1 Uncaught SyntaxError: missing ) after argument list
    apuntando a la primera línea del documento html.

    No entiendo el por qué, sobre todo cuando en la propia función se parsea ese campo dni para convertirlo en string (a pesar de que YA ES UN STRING).

    Alguna idea de por qué sucede esto????

    Gracias y saludos.

  12. Carlos Suarez
    Responder

    Como hago para buscar por dni y que me devuelva los datos correspondientes a ese dni. He tratado pero le da errores. Gracias

  13. Hola Rolando, me gustaron estas lecciones sobre IndexedDB, explicas bastante claro pero me gustaría saber si tienes ya la leccion sobre Modificar-Editar.
    Saludos

  14. Muchas gracias por todo lo que haces por la comunidad.
    ¿alguna codificación para traer los datos de un solo registo, como nombre = “Adolfo ” .and. apellido = “Doring” .and. profesion = “Contador” ?
    Que se habían agregado anteriormente.

Deja un comentario