简体   繁体   中英

How do I dynamically populate jQuery Mobile pages using JSON data?

I'm trying to get data from some external JSON ( http://ip-api.com/json ). I then want to use the keys to dynamically populate a listview. I want each list item to be a link, and when you click the link, the jQuery Mobile page will contain the key's matching value. I have two jQuery Mobile pages, one home, and one other.

I'm trying to achieve this by changing the id of the the second "data-role=page" div to the current key data, and also appending key data to h2, and appending the value data to p. It's creating a correct list of the keys, but when I click on the first item, the h2 contains ALL of the keys, and the p contains ALL of the values. How can I amend this so that each key/value pair ends up as the h2 and p of whichever jQuery Mobile page is currently being created by clicking the corresponding key list item?

I've been trying to use the code from How to populate a jQuery Mobile ListView with JSON data? but I can't quite get it working as it isn't using external JSON.

<!DOCTYPE html>
<html>
    <head>
        <title>Geo-Location Data</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="assets/css/themes/geoLocation.css" />
        <link rel="stylesheet" href="assets/css/themes/jquery.mobile.icons.min.css" />
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile.structure-1.4.5.min.css" />
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
        <script src="assets/js/geoLocation.js"></script>
    </head>
    <body>
        <div data-role="page" id="homePage"> 
            <div data-role="header">
                <h1>Geo-Location Data</h1>
            </div>
            <div data-role="main" class="ui-content">
                <div data-role="collapsible" data-collapsed="true">
                    <h2>Click here for Geo-Location Data</h2>
                    <ul id="list" data-role="listview" data-filter="true" data-inset="true" data-icon="user" data-autodividers="true">
                    </ul>
                </div>
            </div>
        </div>
        <div data-role="page" id="dataPage"> 
            <div data-role="header">
                <h2 id="dataHeading"></h2>
            </div>
            <div data-role="content">
                <p></p>
            </div>
        </div>
    </body>
</html>

$(document).ready( function() {
    $.getJSON("http://ip-api.com/json", function(data){
        $.each(data, function(key, val){
            $("ul#list").append('<li>' + '<a href="#' + key + '" data-transition="slide">'+ key + '</a>' + '</li>');
            $("ul#list").listview("refresh");
            $("div#dataPage").attr("id", key);
            $("h2#dataHeading").append(key);
            $("p").append(val);
        });
    });
})

You are using an $.each loop so it keeps appending $("h2#dataHeading").append(key); & $("p").append(val); to the 2nd page as it loops through the json data so its not actually creating separate pages. All it does is change the id of the dataPage page once and it wont be able to find $("div#dataPage") thereafter so i'm surprised all the links in the items work except for the first one.

A more efficient way is use the data-* attribute to store the key and val directly on the list items, grab them upon click, append to the 2nd page and open the 2nd page dynamically. This alleviates the need for separate pages while keeping the DOM small

eg

$(document).ready( function() {
    $.getJSON("http://ip-api.com/json", function(data){
        $.each(data, function(key, val){
            $("ul#list").append('<li data-key="'+key+'" data-val="'+val+'"><a>'+ key + '</a></li>');
            $("ul#list").listview("refresh");
        });
    });

//The list item click function
$("#list> li").on("click", function() {
var key= $(this).attr("data-key");
var val= $(this).attr("data-val");
$("#dataHeading").empty().append(key);
$("p").empty().append(val);
$(":mobile-pagecontainer").pagecontainer("change", "#dataPage",  { transition: "slide" });
});

});

I suggest replacing $(document).ready with something like pagecreate as JQM works best with inbuilt page Events

When using $(":mobile-pagecontainer") you could also send data to a page but you will need another function like pagebeforeshow to append the data to the page before it displays it -- If you decide to do it this way, read the Notes for what versions is supported. JQM deprecates some events in versions in favor of new replacement events

A solution. What worked was entirely dispensing with the second JQM page, and creating it by appending the data to the body in the JavaScript. Here's the updated code.

<!DOCTYPE html>
<html>
    <head>
        <title>Geo-Location Data</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="assets/css/themes/geoLocation.css" />
        <link rel="stylesheet" href="assets/css/themes/jquery.mobile.icons.min.css" />
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile.structure-1.4.5.min.css" />
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
        <script src="assets/js/geoLocation.js"></script>
    </head>
    <body>
        <div data-role="page" id="homePage"> 
            <div data-role="header">
                <h1>Geo-Location Data</h1>
            </div>
            <div data-role="main" class="ui-content">
                <div data-role="collapsible" data-collapsed="true">
                    <h2>Click here for Geo-Location Data</h2>
                    <ul id="list" data-role="listview" data-filter="true" data-inset="true" data-icon="arrow-r" data-autodividers="true">
                    </ul>
                </div>
            </div>
        </div>
    </body>
</html>

$(document).ready( function() {
    $.getJSON("http://ip-api.com/json", function(data){
        $.each(data, function(key, val){
            $("ul#list").append('<li>' + '<a href="#' + key + '" data-transition="slide">'+ key + '</a>' + '</li>');
            $("body").append('<div data-role="page" id="'+ key +'"><div data-role="header" id=""><h2 id="dataHeading"></h2 ></div><div data-role="content"><p>'+ val +'</p></div></div>');
            $("ul#list").listview("refresh");
        });
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM