How to populate a jQuery Mobile ListView with JSON data?

21,411

Solution 1

Solution

Yes. Its possible to have two pages and use one for displaying your data and one to show up the details of the clicked item. I had to pull in some old stuff, a demo I made when jQM was in version 1.1 and change it to modern times. Anyway, considering I have an array like this :

[
    {
        "id": 0,
        "age": 31,
        "name": "Avis Greene",
        "gender": "female",
        "company": "Handshake",
        "email": "[email protected]",
        "phone": "+1 (845) 575-2978",
        "address": "518 Forrest Street, Washington, New York, 3579"
    },
    {
        "id": 1,
        "age": 31,
        "name": "Dunn Haynes",
        "gender": "male",
        "company": "Signity",
        "email": "[email protected]",
        "phone": "+1 (829) 454-3806",
        "address": "293 Dean Street, Dante, Oregon, 5864"
    }
]

I randomly generated stuff and made it upto 100 elements, just like how you seem to have. I have two pages.

<!--first page -->
<div data-role="page" id="info-page">
    <div data-role="header" data-theme="b">
         <h1> Information</h1>

    </div>
    <div data-role="content">
        <ul data-role="listview" id="prof-list" data-divider-theme="a" data-inset="true">
            <li data-role="list-divider" data-theme="b" role="heading">Names</li>
        </ul>
    </div>
</div>
<!--second page -->
<div data-role="page" id="details-page">
    <div data-role="header" data-theme="b"><a href="#" data-rel="back" data-role="button">Go back</a>

         <h1>Employee Details</h1>

    </div>
    <div data-role="content"></div>
</div>

The first page, #info-page is for showing data in a listview. The second page, #details-page is for the info of the clicked item. Thats all you need. Only two pages, not more than that. So every time a click happens, you do the following through JavaScript

  • Get the current value of data from the array. Like if you click on the 4th li in the list, get the 4th object from the array which has all the data.
  • Store it in the data variable of the second page, so that it can be retrieved later. Something like this:

    $("#details-page").data("info", info[this.id]);
    
  • Then, redirect to second page using changePage, like this :

    $.mobile.changePage("#details-page");
    
  • When the second page opens, use the pagebeforeshow event to get the data from the page (which you stored into this page when the tag in the previous page was clicked.

  • Use some HTML layout to populate the data. I used jQM's grids.

That's all folks!

Full code

Ive attached the JS used with the HTML. Its self explanatory. Read the inline comments in the code and you'll be able to understand more. Assume info is the array in picture.

//pageinit event for first page
//triggers only once
//write all your on-load functions and event handlers pertaining to page1
$(document).on("pageinit", "#info-page", function () {


    //set up string for adding <li/>
    var li = "";
    //container for $li to be added
    $.each(info, function (i, name) {
        //add the <li> to "li" variable
        //note the use of += in the variable
        //meaning I'm adding to the existing data. not replacing it.
        //store index value in array as id of the <a> tag
        li += '<li><a href="#" id="' + i + '" class="info-go">' + name.name + '</a></li>';
    });
    //append list to ul
    $("#prof-list").append(li).promise().done(function () {
        //wait for append to finish - thats why you use a promise()
        //done() will run after append is done
        //add the click event for the redirection to happen to #details-page
        $(this).on("click", ".info-go", function (e) {
            e.preventDefault();
            //store the information in the next page's data
            $("#details-page").data("info", info[this.id]);
            //change the page # to second page. 
            //Now the URL in the address bar will read index.html#details-page
            //where #details-page is the "id" of the second page
            //we're gonna redirect to that now using changePage() method
            $.mobile.changePage("#details-page");
        });

        //refresh list to enhance its styling.
        $(this).listview("refresh");
    });
});

//use pagebeforeshow
//DONT USE PAGEINIT! 
//the reason is you want this to happen every single time
//pageinit will happen only once
$(document).on("pagebeforeshow", "#details-page", function () {
    //get from data - you put this here when the "a" wa clicked in the previous page
    var info = $(this).data("info");
    //string to put HTML in
    var info_view = "";
    //use for..in to iterate through object
    for (var key in info) {
        //Im using grid layout here.
        //use any kind of layout you want.
        //key is the key of the property in the object 
        //if obj = {name: 'k'}
        //key = name, value = k
        info_view += '<div class="ui-grid-a"><div class="ui-block-a"><div class="ui-bar field" style="font-weight : bold; text-align: left;">' + key + '</div></div><div class="ui-block-b"><div class="ui-bar value" style="width : 75%">' + info[key] + '</div></div></div>';
    }
    //add this to html
    $(this).find("[data-role=content]").html(info_view);
});

Demo

I've also made a demo where you can read more about this at jsfiddle.net. Here's the link : http://jsfiddle.net/hungerpain/52Haa/

Solution 2

you can try something like this

Updated

Html Page

   <div data-role="page" id="testpage">
        <div data-role="content">    
             <ul data-role="listview" id="listitem" data-divider-theme="a" data-inset="true">
            </ul>
        </div>
    </div>

javascript

  $(document).on("pageinit", "#testpage", function(){
        $.getJSON("example.json", function(data){
            var output = '';
            $.each(data, function(index, value){                   
             output += '<li><a href="#" id="' + data + '">' +data+ '</a></li>';
            });
            $('#listitem').html(output);
        });
    });
Share:
21,411
Admin
Author by

Admin

Updated on July 18, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm developing a webapp here using HTML and jQuery Mobile (JQM), so I'm pretty new at this. What I'm trying to do here is to populate a JQM listview with a list of names. Each of this names will link to a new page with personal data being displayed (Full name, address, date of birth, etc).

    Currently, because of my lack of knowledge, I manually create a new .html file for EACH individual person (e.g. johnDoe.html for a fictional character Mr. John Doe). I then physically link the list elements to this html file via the function.

    Problem is now I have 100 over individuals to populate that list view. I think that there's an easier way to do this rather than manually creating 100+ html files for all these individual persons right?

    I heard of this JSON thing that might do the trick, but coming from a background of ZERO computing knowledge, I don't really understand how it works. Will someone please shed some light on how can I do this?

    Thanks a lot!

    EDIT: I'm using Dreamweaver CS5.5 to do the coding. For this webapp that I'm tasked to develop, I was given a "template" or sorts that uses JQM and Backbone.js. As such, somehow the "multi-page" structure for a single HTML file doesn't seem to work. From what I see in the template, every HTML file has a corresponding JS file that has code that looks like this:

    define(['jquery',
            'underscore',
            'backbone',
            'helper',
            'views/phr/list',
            'text!templates/vpr2.html'
        ],
        function ($,
            _,
            Backbone,
            Helper,
            phrListView,
            tmpVpr2) {
            var view = Backbone.View.extend({
                transition: 'fade',
                reverse: true,
                initialize: function () {
                    this.phrlistview = new phrListView();
                },
                render: function () {
    
                    $(this.el).append(_.template(tmpVpr2, {}));
    
                    console.log("Rendering subelements...");
                    Helper.assign(this, {
                        '#phrListView': this.phrlistview
                    });
    
                    return this.el;
                }
    
            });
    
            return view;
        });
    

    For the HTML pages, they all begin with a <div data-role=header> tag, then a <div data-role=content>, before ending with a <div data-role=footer>, all with their respective content within the opening and closing tags.

    For my listview in question, the JQM code for the listview will be within the <div data-role=content> part of the HTML file. How can I populate this listview with JSON data then?

    (Apologies if I sound extremely noob at this, because I really am >.< Really appreciate the help!)

  • krishwader
    krishwader over 10 years
    this is not a listview. The question clearly mentions listview.
  • Admin
    Admin over 10 years
    Hello hungerpain! Thank you for your really comprehensive help description! I've tried to paste your code into my relevant files, but somehow the whole screen doesnt show (I'm editing it in Dreamweaver CS5.5 btw...). I'm not sure is it because I'm using a JQM template that uses backbone.js?<br> Also, how do I display the JSON data in a listview instead of a grid?
  • krishwader
    krishwader over 10 years
    You mean in the second page? Just replace it with a list view. In the for..in loop use it the way I've populated the names in the first page.
  • krishwader
    krishwader over 10 years
    And regarding your problem, it would help if you out code as a demo on jsfiddle.net. it helps debug more.not the entire code like images n stuff..just the main things. There'll be a drop down to choose query version ,etc. And add backbone. js through the external resources section in the left corner of the screen. It must be concise and to the point. If you give us that, people will be more Willing to help you.
  • Admin
    Admin over 10 years
    Hey @hungerpain i've edited my description of my problem above! Please take a look!
  • Phill Healey
    Phill Healey about 10 years
    @bundleofjoy would you mind showing how this could be amended to grab the results from a url? Thanks.
  • krishwader
    krishwader about 10 years
    Well @PhillHealey , in the pageinit, you could add an ajax call to get the data