36

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()

Itai Sagi
  • 5,537
  • 12
  • 49
  • 73

10 Answers10

62

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); 
        }  
    });  
}
Philll_t
  • 4,267
  • 5
  • 45
  • 59
Nowshath
  • 832
  • 7
  • 14
  • 5
    Updated for radio buttons and checkboxes -- @LaundroMatt – Nowshath Jan 25 '13 at 05:24
  • Doesn't work for a lot of elements (search, number, tel, and so on) – Aurelio De Rosa Apr 08 '13 at 00:50
  • 1
    I think you can add them to below "text". – Valentin Despa Apr 08 '13 at 08:37
  • I found $ctrl.prop("type") returns "textarea" where $ctrl.attr("type") did not (Chrome) – Phil Windley Dec 19 '13 at 18:01
  • @ivo-nascimento, You should use `ctrl.prop()` instead of `ctrl.attr()` for better compatibility and use with more input types. Also, you can add support for select elements by re-using your radio case, with `if($this(this).attr("selected", true);` Lastly, `var $ctrl` should probably be `var ctrl` instead, for performance reasons. – Tony Chiboucas Sep 24 '14 at 18:39
  • If you use mvc forms and have an array in the model then the name of the input could be like "ObjectName[0].Property", in that case this code throws an error. The solution is, you have to replace: `var ctrl = $("[name='" + key + "']", frm);` – BRap Oct 29 '19 at 13:44
  • @TonyChiboucas How ctrl gives better performance than $ctrl? I mean, does the variable name has any impact on the program performance? – ankur_rajput Jun 10 '20 at 19:51
  • 1
    @ankur_rajput, you're right. The variable name won't have any effect. I was using `$ctrl` vs `ctrl` to denote storing the JQuery object or a reference to the element. Storing the entire JQuery object will use a lot of ram, and has some potential to create other problems. – Tony Chiboucas Jun 11 '20 at 20:26
26

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/

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
13

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 
dipenparmar12
  • 3,042
  • 1
  • 29
  • 39
Alexander G
  • 256
  • 2
  • 7
4

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;
            } 
        }
    });
};
Spiel
  • 41
  • 3
4

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));
}
Community
  • 1
  • 1
Nicholas
  • 3,529
  • 2
  • 23
  • 31
2

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.

iautomation
  • 996
  • 10
  • 18
0

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.

saurshaz
  • 489
  • 5
  • 17
0

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); 
Ian Tearle
  • 342
  • 1
  • 5
  • 14
0

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
batomaeus
  • 156
  • 1
  • 1
  • 8
0

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.

Matt
  • 7,049
  • 7
  • 50
  • 77