Itai Sagi
Itai Sagi

Reputation: 5615

Using jQuery and JSON to populate forms?

I was wondering how is it popssible to populate forms using JSON?

I have a JSON string which I get using php's json_encode() And I want to use the JSON string to populate form controls (such as textarea or text input).

How can I achieve such thing without using external plugins (like jQuery populate plugin, which I saw).

EDIT: JSON format:

[{"id":"41","parent_id":null,"node_name":"name","slug":"","lft":"3","rgt":"4"}]

This is what I get from json_encode()

Upvotes: 36

Views: 59365

Answers (12)

drumkid
drumkid

Reputation: 23

And this is valid (following Alexander Gs solution), if you have a select with multiple options: (assuming that your JSON has something like

{"key":["value1","value2"]}

in it.)

function populateForm(frm, data) {
jQuery.each(data, function(key, value){
    var $ctrl = jQuery('[name='+key+']', frm);
    if($ctrl.is('select')){
        jQuery("option",$ctrl).each(function(){
            $this = this;
            if (typeof value === "object") {
                jQuery.each( value, function(i, l) {
                if ($this.value === l) {  $this.selected=true; }
                })
            }
          else if (this.value === value) { this.selected=true; }
        })
    }
    else {
        switch($ctrl.prop("type"))
        {
            case "text" :   case "hidden":  case "textarea":
            $ctrl.val(value);
            break;
            case "radio" : case "checkbox":
            $ctrl.each(function(){
                if(jQuery(this).attr('value') === value) {  jQuery(this).attr("checked",value); } });
            break;
        }
    }
});

}

Just replace jQuery with $ if needed.

Upvotes: 0

tim
tim

Reputation: 2724

Here are my two cents. :) An iterator for multi-dimensional form data:

var prefill = function(field, value) {

  if (['array', 'object'].includes(typeof value)) {
    $.each(value, function(index, node) {
      prefill(field+'['+index+']', node);
    });
    return;
  }

  $(':input[name="'+ field +'"]').val(value);
};

Example for <input name="key"> or <input name="key[..]">:

$.each(json, function(key, value) {
  prefill(key, value);
});

Example for <input name="data[key][..]">:

$.each(json, function(key, value) {
  prefill('data['+ key +']', value);
});

Upvotes: 0

Nowshath
Nowshath

Reputation: 842

There is a problem here with textarea, then I change it to a default switch value

Use this to assign values to Many Controls :

function populate(frm, data) {   
    $.each(data, function(key, value) {  
        var ctrl = $('[name='+key+']', frm);  
        switch(ctrl.prop("type")) { 
            case "radio": case "checkbox":   
                ctrl.each(function() {
                    if($(this).attr('value') == value) $(this).attr("checked",value);
                });   
                break;  
            default:
                ctrl.val(value); 
        }  
    });  
}

Upvotes: 63

Alexander G
Alexander G

Reputation: 276

Thanks Nowshath. It worked for me. I added a extra check in your version to be able to populate select options as well.

function populateForm(frm, data) {   
$.each(data, function(key, value){  
    var $ctrl = $('[name='+key+']', frm); 
    if($ctrl.is('select')){
        $("option",$ctrl).each(function(){
            if (this.value==value) { this.selected=true; }
        });
    }
    else {
        switch($ctrl.attr("type"))  
        {  
            case "text" :   case "hidden":  case "textarea":  
                $ctrl.val(value);   
                break;   
            case "radio" : case "checkbox":   
                $ctrl.each(function(){
                   if($(this).attr('value') == value) {  $(this).attr("checked",value); } });   
                break;
        } 
    } 
});  


}; // end of populateForm() function 

Upvotes: 14

Nicholas
Nicholas

Reputation: 3784

This is an apendix to @Nowshath's answer

This works for multilevel objects as well

 populateForm(form, data) {
    $.each(data, function(key, value) {

        if(value !== null && typeof value === 'object' ) {
            this.populateForm(form, value);
        }
        else {
            var ctrl = $('[name='+key+']', form);
            switch(ctrl.prop("type")) {
                case "radio": case "checkbox":
                ctrl.each(function() {
                    $(this).prop("checked",value);
                });
                break;
                default:
                    ctrl.val(value);
            }
        }
    }.bind(this));
}

Upvotes: 4

batomaeus
batomaeus

Reputation: 166

I had the same problem and have developed the version shown above a little further. Now it is possible to have individual checkboxes that return the value as well as groups that returns an array of names. The coding is tested, used and working correctly.

        function populateForm($form, data)
        {
            //console.log("PopulateForm, All form data: " + JSON.stringify(data));

            $.each(data, function(key, value)   // all json fields ordered by name
            {
                //console.log("Data Element: " + key + " value: " + value );
                var $ctrls = $form.find('[name='+key+']');  //all form elements for a name. Multiple checkboxes can have the same name, but different values

                //console.log("Number found elements: " + $ctrls.length );

                if ($ctrls.is('select')) //special form types
                {
                    $('option', $ctrls).each(function() {
                        if (this.value == value)
                            this.selected = true;
                    });
                } 
                else if ($ctrls.is('textarea')) 
                {
                    $ctrls.val(value);
                } 
                else 
                {
                    switch($ctrls.attr("type"))   //input type
                    {
                        case "text":
                        case "hidden":
                            $ctrls.val(value);   
                            break;
                        case "radio":
                            if ($ctrls.length >= 1) 
                            {   
                                //console.log("$ctrls.length: " + $ctrls.length + " value.length: " + value.length);
                                $.each($ctrls,function(index)
                                {  // every individual element
                                    var elemValue = $(this).attr("value");
                                    var elemValueInData = singleVal = value;
                                    if(elemValue===value){
                                        $(this).prop('checked', true);
                                    }
                                    else{
                                        $(this).prop('checked', false);
                                    }
                                });
                            }
                            break;
                        case "checkbox":
                            if ($ctrls.length > 1) 
                            {   
                                //console.log("$ctrls.length: " + $ctrls.length + " value.length: " + value.length);
                                $.each($ctrls,function(index) // every individual element
                                {  
                                    var elemValue = $(this).attr("value");
                                    var elemValueInData = undefined;
                                    var singleVal;
                                    for (var i=0; i<value.length; i++){
                                        singleVal = value[i];
                                        console.log("singleVal : " + singleVal + " value[i][1]" +  value[i][1] );
                                        if (singleVal === elemValue){elemValueInData = singleVal};
                                    }

                                    if(elemValueInData){
                                        //console.log("TRUE elemValue: " + elemValue + " value: " + value);
                                        $(this).prop('checked', true);
                                        //$(this).prop('value', true);
                                    }
                                    else{
                                        //console.log("FALSE elemValue: " + elemValue + " value: " + value);
                                        $(this).prop('checked', false);
                                        //$(this).prop('value', false);
                                    }
                                });
                            }
                            else if($ctrls.length == 1)
                            {
                                $ctrl = $ctrls;
                                if(value) {$ctrl.prop('checked', true);}
                                else {$ctrl.prop('checked', false);}

                            }
                            break;
                    }  //switch input type
                }
            }) // all json fields
        }  // populate form

Upvotes: 0

iautomation
iautomation

Reputation: 1084

In case anyone is looking to populate from a multidimensional json format, such as the result of $.serializeJSON[ https://github.com/marioizquierdo/jquery.serializeJSON ], here's a function to convert to a flat format.

function json2html_name_list(json, result, parent){
    if(!result)result = {};
    if(!parent)parent = '';
    if((typeof json)!='object'){
        result[parent] = json;
    } else {
        for(var key in json){
            var value = json[key];
            if(parent=='')var subparent = key;
            else var subparent = parent+'['+key+']';
            result = json2html_name_list(value, result, subparent);
        }
    }
    return result;
}

Usecase example with the functions above:

populateForm($form, json2html_name_list(json))

With all the examples above though:

var $ctrl = $('[name='+key+']', frm);

needs to be changed to

var $ctrl = $('[name="'+key+'"]', frm);

to prevent a syntax error with jQuery

Take note list arrays have to be written with numbers(e.g. fruit[0], instead of fruit[]) in order to be work with this function.

Upvotes: 2

Ian Tearle
Ian Tearle

Reputation: 345

I found the original script didn't play nice with array[] names because of missing quotes in the name selector:

var $ctrl = $('[name="'+key+'"]', frm); 

Upvotes: 0

Spiel
Spiel

Reputation: 41

With little improvements (except radio buttons):

function resetForm($form)
{
    $form.find('input:text, input:password, input:file, select, textarea').val('');
    $form.find('input:radio, input:checkbox').removeAttr('checked').removeAttr('selected');
}

function populateForm($form, data)
{
    resetForm($form);
    $.each(data, function(key, value) {
        var $ctrl = $form.find('[name='+key+']');
        if ($ctrl.is('select')){
            $('option', $ctrl).each(function() {
                if (this.value == value)
                    this.selected = true;
            });
        } else if ($ctrl.is('textarea')) {
            $ctrl.val(value);
        } else {
            switch($ctrl.attr("type")) {
                case "text":
                case "hidden":
                    $ctrl.val(value);   
                    break;
                case "checkbox":
                    if (value == '1')
                        $ctrl.prop('checked', true);
                    else
                        $ctrl.prop('checked', false);
                    break;
            } 
        }
    });
};

Upvotes: 4

saurshaz
saurshaz

Reputation: 509

For a weird but valid JSON syntax like

    [{'name':<field_name>,'value':<field_value>},
    {'name':<field_name>,'value':<field_value>},
    {'name':<field_name>,'value':<field_value>},
    {'name':<field_name>,'value':<field_value>}]

look at this http://jsfiddle.net/saurshaz/z66XF/

We had this weird syntax being used in our application and we got around by writing the logic as above.

Upvotes: 0

Guffa
Guffa

Reputation: 700322

For just text controls (i.e. no radios or checkboxes), you can make a simple version of a populate function:

function populate(frm, data) {
  $.each(data, function(key, value){
    $('[name='+key+']', frm).val(value);
  });
}

Usage example:

populate('#MyForm', $.parseJSON(data));

Demo: http://jsfiddle.net/Guffa/65QB3/3/

Upvotes: 27

Matt
Matt

Reputation: 7249

This can get pretty complicated. It's best to use a tool to parse your JSON. You can create simple forms pretty easily, but you still need to parse it.

Check this plugin out instead: http://neyeon.com/2011/01/creating-forms-with-json-and-jquery/

Or you can use ext4.

Upvotes: 0

Related Questions