Reputation: 33
I'm trying to populate a listview with json results. I've installed fiddler and can acknowledge that I do get the json results back. I positively validated the JSON results. However somehow they do not show up in the listview. I can't seem to find out where it goes wrong.
JSON results: [{"Id":1,"Title":"Electrical"},{"Id":2,"Title":"Piping"},{"Id":3,"Title":"Mechanical"},{"Id":4,"Title":"Software"}]
Code:
<!DOCTYPE html>
<head>
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.js"></script>
<style>
.count {
position: absolute;
font-size: 11px;
font-weight: bold;
padding: .2em .5em;
top: 50%;
margin-top: -1em;
}
.ui-li-aside {
float: right;
width: 50%;
text-align: right;
margin: 1.4em 0px 0px 0px !important;
position: absolute;
right: 25px;
}
.ui-li-heading, .ui-li-desc {
width: 90%;
text-overflow: ellipsis;
}
strong { font-style: normal; }
</style>
<script type="text/javascript" >
var hackerNews = (function($,undefined) {
var pub = {}, $this = $(this);
pub.init = function() {
$("#btnRefresh").live("click", function () {
pub.getAndDisplayNews();
});
$this.bind("news.updated", function (e, news) {
displayNews(news);
});
$this.bind("news.updated", function(e, news) {
$("#itemCount").text(news.items.length);
});
};
pub.getAndDisplayNews = function() {
//$.mobile.loading();
getNews(function () {
//$.mobile.loading();
});
};
function getNews(callback) {
$.ajax({
url: "http://localhost:31634/expertREST.svc/GetKnowledgeFields",
dataType: "jsonp",
success: function (data, textStatus, xhr) {
$this.trigger("news.updated", data);
if (callback) callback(data);
}
});
}
function displayNews(news) {
var newsList = $("#hackerNews").find(".newsList");
newsList.empty();
$("#newsItem").tmpl(news.items).appendTo(newsList).trigger("create");
newsList.listview("refresh");
}
return pub;
}(jQuery));
hackerNews.init();
hackerNews.getAndDisplayNews();
</script>
</head>
<body>
<div data-role="page" id="hackerNews">
<div data-role="header" data-backbtn="false">
<a id="btnRefresh" href="#" data-icon="refresh">Refresh</a>
<h1>Find-an-Expert <span id="itemCount" class="count ui-btn-up-c ui-btn-corner-all">0</span></h1>
</div>
<div id="content" data-role="content">
<ol class="newsList" data-role="listview"></ol>
</div>
</div>
<script id="newsItem" type="text/x-jquery-tmpl">
<li data-messageId="${Id}" class="newsItem">
<h3>${Title}</h3>
</li>
</script>
</body>
Does anyone have a clue? Thanks
Upvotes: 3
Views: 2307
Reputation: 33
Well, thanks for the feedback. I noticed the ajax call didn't even reach the success event so that made me think if there isn't anything wrong with the json I get back after all. Maybe I also forgot to mention that my service is a WCF service .NET4. Googled and guess what. I had to add the crossDomainScriptAccessEnabled="true" option in my web.config:
<bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
Appaerently it's what is needed for WCF to work with jsonp.
I found the explanation on the following link
Thanks.
Upvotes: 0
Reputation: 534
JSONP works by appending the response to the DOM. During a JSONP call, JQuery automatically adds a "callback" parameter in the GET call. Your service must then return the result wrapped with the callback function, in the format:
callback(<jsondata>)
Here's a simple PHP example (in prod, add callback name validations):
// .. prepare result $callback = $_GET['callback']; echo $callback.'('. json_encode($result). ');'; ?>
Also, your use of "bind" is faulty too since passing "data" to it will only give the first record to "displayNews". Simplify it by calling functions directly:
success: function (news, textStatus, xhr) { displayNews(news); $("#itemCount").text(news.length); if (callback) callback(news); }
Finally, change your displayNews to iterate over the list:
function displayNews(news) {
var newsList = $("#hackerNews").find(".newsList");
newsList.empty();
$.each(news, function(k,v) {
$("#newsItem").tmpl(v).appendTo(newsList).trigger("create");
});
newsList.listview("refresh");
}
Upvotes: 1
Reputation: 30893
I find I get better results when I define the type
settings. Example:
$.ajax({
url: "http://localhost:31634/expertREST.svc/GetKnowledgeFields",
type: 'GET',
dataType: "jsonp",
success: function (data, textStatus, xhr) {
$this.trigger("news.updated", data);
if (callback) callback(data);
}
});
I would also advise setting async
to false, yet I see this is not supported by jsonp
:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.
Edit: error
can't be used, that's not very helpful.
Note: This handler is not called for cross-domain script and JSONP requests. This is an Ajax Event.
Not sure how you can trouble shoot this further.
Upvotes: 1