0

JSON object:

{"id":75,"year":2011,"make":"Aston Martin","model":"V12 Vanquish"}

jQuery:

function post() {
  $("form").on("ajax:success", function(e, data, status, xhr) {
    var json = JSON.parse(xhr.responseText);
    $.each(json, function(k, v) {
      $("#vehicle_record").append('<li class="'+k+'">'+v+'</li>');
    });
  });
}

HTML page output:

75
2011
Aston Martin
V12 Vanquish
75
2011
Aston Martin
V12 Vanquish

Questions:

  1. Why is the output rendered twice? (I only expect it once)
  2. Is there a better way to render JSON to the page? (please advise)

--UPDATE--

The following a walk through of the UX:
FORM ONE: name > click next > post > FORM TWO > Choose Vehicle > click next > post > see vehicle picked: add another vehicle? Y (BACK to FORM TWO) / N (continue...)

I need to be able to use post for each model independently without interference. So how do I get for example all of the JSON objects submitted to the vehicle model? (I need this post function to be modular)

Perhaps I can do something like this?:

function post() {
  $("form").on("ajax:success", function(e, data, status, xhr) {
    var json = JSON.parse(xhr.responseText);
    var model = e.currentTarget.action;
    renderOnPage(json, model);
  });
}
function renderOnPage(data, model) {
  if ( model.match(/vehicles/) ) {
  $.each(data, function(k, v) {
    $("#vehicle_record").append('<li class="'+k+'">'+v+'</li>');
  });
  }
}
MrPizzaFace
  • 7,807
  • 15
  • 79
  • 123
  • 3
    looks like the method `post` was called twice!!! – Arun P Johny Mar 01 '14 at 00:53
  • 1
    What's the `ajax:success` event? That's not a standard jQuery event, AFAIK. – Barmar Mar 01 '14 at 00:54
  • 1
    can you add a console logging in the post method as the first line and see how many times it is called – Arun P Johny Mar 01 '14 at 00:54
  • Also put it in the callback function, to see if something is triggering the event twice. – Barmar Mar 01 '14 at 00:55
  • re rendering json ( client side templating ) if you don't want to make something, I like **ejs** ( simple ) and **linkedins fork of dust** ( if you need logic templating ) – Rob Sedgwick Mar 01 '14 at 00:58
  • Ok so yes `post` is called twice and JSON is returned but for two different models. I will update my question. – MrPizzaFace Mar 01 '14 at 01:04
  • Recommend if that's the case that you call `$("#vehicle_record").empty();` inside the success before the loop - however, you may still get inconsistent results if the events overlap – Rick Dailey Mar 01 '14 at 01:05
  • @Rick calling empty() is not a good solution to the problem but thanks for your suggestion. – MrPizzaFace Mar 01 '14 at 01:20
  • One thing that comes to mind is that the Ajax calls occurs twice. If Chrome is used, there may be a Chrome extension involved that causes this problem. See the post below for a similar situation: [IHttpHandler execute twice on chrome](http://stackoverflow.com/questions/19520070/ihttphandler-execute-twice-on-chrome) – holmes2136 Mar 01 '14 at 04:01

2 Answers2

1

Better or maybe best way to render JSON on HTML (without using third party libraries) is to come up with something like this:

<html>
<body>
<span>ID</span>: <span json-path="id"></span>
<span>Year</span>: <span json-path="year"></span>
<span>Make</span>: <span json-path="make"></span>
<span>Model</span>: <span json-path="model"></span>
</body>
</html>

where json-path is just any attribute name that you want to come up with. Now on success of AJAX you should do something like this:

function refreshPage(data) {
   $("[json-path]", $(document)).each(function() {
    $(this).text(data[$(this).attr("json-path")]);
   });
}

Now if you need more complex features like to display an array of items ins JSON in a table or LIST then just add a switch case statement in above refreshPage

 switch((this).prop('tagName')) {
        case "INPUT":
           $(this).val(data[$(this).attr("json-path")])

Using this approach you can even map your json-path to an array on JSON path for a TABLE or SELECT tag and then use switch case to identify and render each type of elements differently.

TechMaze
  • 477
  • 2
  • 9
  • Hey thanks for your suggestion could you perhaps share a link with a thorough example of your suggested implementation. Thanks again. – MrPizzaFace Mar 01 '14 at 01:35
0

Your post function actually binds a handler twice to success event, therefore its obvious it's been executed twice. You don't actually need to call function explicitly I suppose. Simply

$("form").on("ajax:success", function(e, data, status, xhr) {
    var json = JSON.parse(xhr.responseText);
    $.each(json, function(k, v) {
      $("#vehicle_record").append('<li class="'+k+'">'+v+'</li>');
    });
});

would work. Don't call post on clicks

code-jaff
  • 9,230
  • 4
  • 35
  • 56