I have seen a mention of using JQuery tmpl in a faster way to create a string instead of DOM elements: http://riley.dutton.us/2010/10/12/jquery-templates-vs-jqote-2-a-followup.html
I just can't seem to get it working though. I am using JQuery 1.6.4 and the latest tmpl files from GitHub. My code is below - can anyone point out the obvious mistake? Many thanks.
JsonData is a response from a web service and is correctly formed JSON - I can bind it using the well publicised approad to tmpl and also using JQote2.
jQueryTemplate looks something like:
<script id="jQueryTemplate" type="text/x-jquery-tmpl">
<li><span>${Name}</span><span>${ProductName}</span></li>
</script>
My JS to call the template:
var myTemplate = $('#jQueryTemplate').template();
var html = myTemplate($, { data: JsonData }).join('');
$("#container").html(html);
I seem to get undefined as the result of $('#jQueryTemplate').template(); and this error:
Uncaught TypeError: Object
<li><span>${Name}</span><span>${ProductName}</span></li>
has no method 'join'
Thanks for any help given.
define your template like this;
$.template( "jQueryTemplate", "<li><span>${Name}</span><span>${ProductName}</span></li>" );
render your template like this;
$.tmpl( "jQueryTemplate", JsonData ).appendTo( "#container" );
or
define your template like this;
<script id="jQueryTemplate" type="text/x-jquery-tmpl">
<li><span>${Name}</span><span>${ProductName}</span></li>
</script>
render your template like this;
$( "#jQueryTemplate" ).tmpl(JsonData).appendTo("#container" );
After much digging I eventually found an example of this approach explained by Boris Moore. Thanks Boris for your great work.
https://github.com/jquery/jquery-tmpl/issues/50
I created a jsperf to compare the two approaches - it is my first jsperf so hopefully it is set up correctly to get meaningful results. It shows a massive difference. I guess it depends on usage but mine is pretty basic markup generation so the string output combined with .html() will do the trick.
http://jsperf.com/jquery-tmpl-as-string
Hope this helps if you find yourself needing to improve tmpl performance and don't have the opportunity to switch to another templating engine.
Related
I am trying to learn the popular method of using controllerAs as opposed to binding everything to the $scope. Briefly documented here : http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/
I am going to provide a much simplified example of my code in order to understand how to properly code in this manner.
angular
.module('gc',['gc.login']);
angular
.module('gc.login',[]);
(function () {
'use strict';
angular
.module('gc.login')
.controller('gcLoginController', gcLoginController);
gcLoginController.$inject = [];
/* #ngInject */
function gcLoginController() {
var vm = this;
vm.blah = "blah";
activate();
////////////////
function activate() {
console.log("Hello World!");
}
}
})();
The code above was created using snippits from the author of the article, but when I try to bind to the variable "blah" in the html, it does not work. It doesn't output anything at all.
<body id="ng-app" ng-app="gc">
<div class="wrapper" ng-controller="gcLoginController as vm">
"{{vm.blah}}"
</div>
</body>
This simply outputs ""
Can anyone see what error was made in using this method?
Ah shoot it was a stupid mistake. Thank you to those who double checked my work in plunker. I was using a node.js server for this project along with the template engine "Swig". Apparently that was a mistake to combine Angular and Swig, because they both use {{ }} to bind variables, which is why my code (which as charlietfl pointed out is actually working) didn't seem to work. I will update the title of this post to help others who may have a similarly difficult to trace issue with Angular / Swig.
Update - can get around this problem : https://gist.github.com/angelochen960/4188293
I'm struggling with this even after reading the MSDN documentation and the following online guides:
Codefoster
Stephen Walter
I think my problem is easy to fix and that I just am thinking about something in the wrong way. Basically I am querying my web service and on success running the following method. I am then trying to bind the result to my listview. For now I am using a hardcoded value publicMembers.itemlistwhich has been declared at the top of the document just to make sure I can actually bind to the list before doing it with my query results. Ignore line 2 for now.
Success Method:
_lookUpSuccess: function xhrSucceed(Result) {
var response = JSON.parse(Result.responseText);
listView = document.querySelector("#termTest");
ui.setOptions(listView, {
itemDataSource: publicMembers.itemList,
itemTemplate: document.querySelector(".itemtemplate"),
})
},
Now, instead of using document.querySelector, I have also tried with WinJS.Utilities.id and WinJS.Utilities.query, neither of which worked either. This doesn't break my code and introduce an error but it doesn't bind to the listview either so I think I have an issue in querying the right DOM element. However exactly the same code does work if I add it to the top of the script, it is only when I place it in this method that it stops working.
EDIT: Also to clarify, when I debug publicMembers.itemList is storing the values I expect them to be.
Please point out if I have explained things poorly and I will try and improve my question.
Thanks.
I haven't used WinJS.UI.setOptions, but rather this other way of setting the data source. Can you see if it works?
_lookUpSuccess: function xhrSucceed(result) {
var response = JSON.parse(result.responseText);
listView = document.querySelector("#termTest");
listView.winControl.itemDataSource = publicMembers.itemList;
},
This would assume you're defining the itemTemplate as part of the data-win-options attribute of your ListView's HTML element. You could also probably just do listView.winControl.itemTemplate = document.querySelector(".itemtemplate") if you prefer to set it programmatically.
I'm learning emberjs and I've done a pretty simple example. The HTML template is:
<script type="text/x-handlebars">
Hello <b>{{App.appOwner}}</b>
</script>
And then the javascript is:
App = Ember.Application.create({
appOwner : 'Erik'
});
App.appOwner = 'Tom';
Which does pretty much what you expect. The emberjs.com documentation says templates are auto-updating -- so I added this:
$(document).click(function() {
console.log('HERE!');
App.appOwner = 'Alphonse';
});
Which quite unexpectedly failed. I had added the console.log just to make sure the click handler was being called, which it was. Why doesn't it update?
You need to use .set() mutator method, because javascript doesn't have facilities to intercept the direct properties changes:
App.set('appOwner', 'Alphonse');
There are some messages coming from a Javascript file to a GSP page. How can I implement g:message in a Javascript page?
For example:
if ($('#name').val() == "") {
$('#nameStatus').show();
$('#nameStatus').html('<font color=red>Company Name can not be blank</font>');
return false;
Try this kind of syntax :
function foo() {
return "${message(code:'my.message.code')}";
}
If I understand correctly, you want to be able to use the output from g:message in your javascript.
There is a very helpful blog post which talks about how to use g:createLink in a similar way that you want, so you can easily adapt it to use g:message as well. Check out the post here, there is some useful info in the comments as well.
The idea is to create javascript objects in your GSP file; which should be defined before including your javascript file; and then just access those global objects in your js code.
Edit:
You might also be interested in the GSParse Plugin. I haven't tried it my self but I think it accomplishes what you are looking for as well.
I am experimenting with Jetpack and I would like to parse all the years in a given html page and then wrap the year with a link to the Wiki page. I tried the code in jquery and there it works but now I am using it in Jetpack and it gives an error $(doc).replace is not a function. I am definitely new to Jquery / Jetpack so maybe I am missing something really easy but your help is much appreciated.
EDIT: I have tried the suggestions but I am still stuck. The weird thing is that this
JQuery function works:
(function($) {
$.fn.clickUrl = function() {
var regexp = /([1-2][0-9][0-9][0-9])/gi;
this.each(function() {
$(this).html(
$(this).html().replace(regexp,'<ahref=\"http://nl.wikipedia.org/wiki/$1\">$1<\/a>')
);
});
return $(this);
}
})(jQuery);
and basically, I would like to 'port' this function to Jetpack.
This is the 'old' non-working port of my JQuery function to Jetpack:
jetpack.statusBar.append({
html: "Hyperlink Years",
width: 80,
onReady: function(widget){
$(widget).click(function(){
var regexp = /([1-2][0-9][0-9][0-9])/gi;
var doc = jetpack.tabs.focused.contentDocument;
$(doc).each(function() {
$(this).html(
$(doc).replace(regexp,'<a href=\"http://nl.wikipedia.org/wiki/$1\">$1<\/a>'));
});
return $(doc);
});
}
});
I'm not familiar with jetpack, but your jquery seems to be quite messed up.
If "doc" is an HTML document, then doing $(doc).each() doesn't really make sense. It would only loop once, and "this" would be the same as doc.
Then later you are doing $(doc).replace(regexp, ...), but replace() is not a jquery function. You might have wanted to do .html().replace(regexp, ...); HOWEVER, I do not recommend doing this because it will not work - you will just end up replacing any numbers in the document, even if they are part of another URL or the HTML of the page.
For more information, refer to this question or google for jquery text nodes:
Find text string using jQuery?