1

I have this code:

{% for user in users %}

        <form name="form_user_{{ user.id }}" method="post" action="/networks/{{ net.id }}/sensors/{{ sens.id }}/rights">
          <tr>
            <td>
              <div>
                {{ escape(user.name) }}
                <input type='hidden' name="id" value='{{ user.id }}'>
              </div>
            </td>
            <td>

              <label class="radio inline" onclick="document.forms['form_user_{{ user.id }}'].submit();">
                <input type="radio" name="perms" id="perms_{{user.id}}_0" value="0">
                None
              </label>
              <label class="radio inline" onclick="document.forms['form_user_{{ user.id }}'].submit();">
                <input type="radio" name="perms" id="perms_{{user.id}}_1" value="1">
                Read
              </label>
              <label class="radio inline" onclick="document.forms['form_user_{{ user.id }}'].submit();">
                <input type="radio" name="perms" id="perms_{{user.id}}_4" value="4">
                Read + Commands
              </label>

              {{ xsrf_form_html() }}
            </td>

          </tr>
        </form>

and I would bring this code in a function script at the bottom of the html page and associate the function to a onClick event.

I'm trying to write the function but it doesn't work.

Where is the error in this function?

function createFormAndSubmit(){

{% for user in users %}

 var submitForm = document.createElement("form_user_{{ user.id }}");
 document.body.appendChild(submitForm);
 submitForm.method = "POST";

 var newElement = document.createElement("<input type='hidden' name='id' value='{{ user.id }}'>");
 inputForm.appendChild(newElement);

 var newElement = document.createElement("<input type='radio' name='perms' id='perms_{{user.id}}_0' value='0'>");
 inputForm.appendChild(newElement);

 submitForm.action= "/networks/{{ net.id }}/sensors/{{ sens.id }}/rights";
 document.forms['form_user_{{ user.id }}'].submit();
 submitForm.submit();

{% end %}

}

I'm trying to build the form attaching every element in a tree structure.

Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
sharkbait
  • 2,980
  • 16
  • 51
  • 89

2 Answers2

2

You are doing it wrong: Do not try to generate Javascript code in any template language.

The recommended approach to pass data form server-side to client-side Javascript code

  • Create your JavaScript code as a separate .js file

  • Embed related data to HTML code using data-attributes as JSON when you generate HTML from a page template

http://html5doctor.com/html5-custom-data-attributes/

  • When the page executes in the browser, on the client-side DOM ready event read this data if you are on a page where you need to perform the magic task. You can do this by calling jQuery to find out necessary elements which carry the data attribute $("div.my-marker-css-class").size() > 0

http://api.jquery.com/ready/

  • Read the data-attribute payload using JSON.parse($("div.my-marker-css-class").data())

  • ... and fill-in or generate necessary client-side DOM (HTML) elements using jQuery or client side templating

DOM tree based JavaScript template engines

This way

  • You do not need to have generate JavaScript code

  • It's more maintainable (you get syntax highlighting to .js files and so on). You can use Firebug etc. to debug your JavaScript code and error line numbers make sense.

  • It's more cache friendly and places less payload to HTML page

This approach is technically superior and once mastered, is easier to maintain and less bug prone. However, it also means that you must understand the full software stack what goes from the server into your browser and this means more learning for newcomer developers.

Community
  • 1
  • 1
Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435
2

Mikko is 100% correct. You will need to pass the raw data from the server and parse it with javascript.

Thankfully, there are plugins that can make this easier. http://daffl.github.com/2011/01/06/jquery-dform.html is one.

Here is a python encoder/decoder: http://docs.python.org/2/library/json.html

And to get the JSON from the server you would use: http://api.jquery.com/jQuery.getJSON/

I don't know python well enough to give a complete example, but these are the basic steps you can take to achieve your goal.

EDIT: I will take a stab at an example, but be prepared to debug it :) EDIT 2: change to make the javascript in its own file as requested by OP.

Your HTML will look like this:

<html>
<head>
<script src='path to jquery'></script>
<script src='path to dForm plugin'></script>
<script src='myjs.js'></script> <!-- use relative path -->
</head>
<body>
<form id="myform"></form>

</body>
</html>

Your myjs.js file will look like this:

    $(function(){
        if($("#myform).length > 0) // only run if #myform exists
        $("#myform").buildForm("http://example.com/myform.json");
    });

The myform.json python file will have something like the following code:

import json
json.dumps({'success': True, 'data': users.values()})

See format python output to json for more information regarding python and JSON formatting.

To do this with inline python, try the following:

<html>
<head>
<script src='path to jquery'></script>
<script src='path to dForm plugin'></script>
</head>
<body>
<script>
var dataArray = [
{% for user in users %}
   {
    "action" : "/networks/{{ net.id }}/sensors/{{ sens.id }}/rights",
    "method" : "post", // or get
    "elements" :
    [
        { "type" : "hidden",
          "name" : "id",
          "value" : "{{ user.id }}"
        },
        {
            "name" : "perms",
            "id"   : "perms_{{user.id}}_0",
            "type" : "radio",
            "value": "0"
        },
        {
            "name" : "perms",
            "id"   : "perms_{{user.id}}_0",
            "type" : "radio",
            "value": "0"
        },
        {
            "type" : "submit",
            "value" : "Submit"
        }
        ]
   },
{% end %}
];

for(var i =0; i<dataArray.length; i++){
   $("body").append("<form id='form"+ i +"'></form>");
   $("#form" + 1).dForm(dataArray[i]);
}
</script>
</body>
</html>

I wouldn't personally recommend the inline method, but, its an option. You will also need to account for the extra comma due to the loop. It may add an empty array item depending on the browser. IE may choke altogether.

Community
  • 1
  • 1
Andrew Grothe
  • 2,562
  • 1
  • 32
  • 48
  • jQuery.dForm is very interesting. I have to understand how can I write my form in this way. Any help? :) – sharkbait Mar 14 '13 at 11:36
  • 1
    @sharkbait I've added some code for you to see, you will have to experiment with the python json output as I don't know what your user object looks like or really anything about python in general. Regardless, once the python script returns valid JSON, the form should build for you. – Andrew Grothe Mar 14 '13 at 11:56
  • 2
    jQuery.dForm beaome a new friend of mine :) – Mikko Ohtamaa Mar 15 '13 at 13:00
  • Also, just for completeness sake (although I wouldn't exactly recommend doing it) you can write out the JSON array with inline python like the hard-coded inline JSON in the dForm example I linked to. An AJAX call is the better way though. – Andrew Grothe Mar 15 '13 at 13:55
  • Can you write me how to do in an answer? – sharkbait Mar 15 '13 at 14:16
  • @sharkbait I've updated with an inline example. Its not pretty *(or recommended)* but there you have it. – Andrew Grothe Mar 15 '13 at 16:21