سؤال

I want to emit some js from jQuery templates e.g I have template like

<script id="tmplID" type="text/x-jQuery-tmpl">
<input id="static.${val}" type="text"/>
<input id = "static2.${val}" type="text"/>
<script type="text/javascript">
$('#static.'+${val}).change(function(){
  alert('some value');
});
</script>
</script>  

When I call this template like:

var obj = {val:'123'};
$('#tmplID').tmpl(obj).appendTo("some_container");

it renders the JavaScript change function as string on the page whereas I want it to be appended as executable JavaScript.

هل كانت مفيدة؟

المحلول

There are multiple issues with your code.

First of all, you should never use nested <script> tags. Even if the closing </script> tag is inside a string in a javascript block you should still split it so it doesn't appear as is, as it could and will trip even the most standards compliant browsers. Not to mention the older ones...

Similarly, you should avoid using dots in IDs, as it is very easy to overlook when writing your jQuery selectors. #id.something means "select the element with the id id which also has class something applied to it". If you can't live without it, you can escape it when writing your selector like #id\\.something, which will "select the element with the id id.something".

It's also a bad idea to put javascript inside your template, you should re-think what you're trying to achieve. There is almost always a way around it:

  • You can bind your events with .delegate() or .live() to elements which you will only create in the future.

  • Instead of hard-coding the ID in the script, you can use different selectors, e.g. you can apply a unique class to use with the above bindings so it won't interfere with existing markup. If you need the ID inside the event handler, you can easily extract it with this.id or $(this).attr('id').

  • If you want to customise 'some value' in your script, you can add custom attributes to your elements, e.g. <input id="static_something" data-custom="some value" /> and extract it in your function using $(this).data('custom').

Taking all of the above into account, I would re-write your code to something similar to this:

<script id="tmplID" type="text/x-jquery-tmpl">
<input id="static_${val}" class="templateinput" type="text" data-custom="value1" />
<input id="static2_${val}" class="templateinput" type="text" data-custom="value2" />
</script>

<script type="text/javascript">
// jQuery ready function
$(function(){
    $('.templateinput').live('change', function(){
        var element_id = this.id;
        var element_data = $(this).data('custom');

        alert('The value of input #' + element_id + ' is: ' + element_data);
    });
});
</script>

If you have a known container which will contain all your template items, use .delegate() instead for clarity to avoid global binding.

نصائح أخرى

Couldn't you just setup the event after rendering the template?

var obj = {val:'123'};
$('#tmplID').tmpl(obj).appendTo("some_container");

$('#static.'+obj.val).change(function() {
    ...
});
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top