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

2
  • You want to create new form controls based on the JSON or set values on existing controls? Also how does your JSON looks like? Commented Sep 4, 2011 at 9:53
  • inject values to existing controls. i'll edit to show my current JSON format Commented Sep 4, 2011 at 9:55

12 Answers 12

63

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); 
        }  
    });  
}
Sign up to request clarification or add additional context in comments.

8 Comments

Updated for radio buttons and checkboxes -- @LaundroMatt
Doesn't work for a lot of elements (search, number, tel, and so on)
I think you can add them to below "text".
I found $ctrl.prop("type") returns "textarea" where $ctrl.attr("type") did not (Chrome)
@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.
|
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/

Comments

14

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 

Comments

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;
            } 
        }
    });
};

Comments

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));
}

2 Comments

what does this.toggleWrappers(key); is supposed to?
@LeonardoBeal . woops. I removed that line :D. It was a function from my code base.
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.

Comments

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.

Comments

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.

Comments

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

Comments

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

Comments

0

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);
});

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.