I use jsrender lib for client-side template generation but the whole website's output is processed by thymeleaf (spring mvc). The problem is that js template contains condtiion i.e.
<script id="main-menu-form-tmpl" type="text/x-jsrender">
{{if (index && (index == 0 || ...
but thymeleaf requires all the ampersands be escaped as &, but this causes jsrender to fail. Another solution found here, but jsrender fails as well because of unknown syntax.
Is there any way to output script's content without parsing it with thymeleaf engine?
JsRender lets you register templates from strings, as well as from script blocks.
See http://www.jsviews.com/#compiletmpl.
So instead of writing:
var mainTemplate = $.templates("#main-menu-form-tmpl");
and then calling mainTemplate.render(...) or mainTemplate.link(...) etc. you can instead remove your template script block and instead pass your template markup as a string to $.templates() as in:
var mainTemplate = $.templates("... {{if (index && (index == 0 || ...");
...
Or if you want you can keep the script block declaration, but with escaped ampersands and then get the contents of the script block as a string, unescape the ampersands, and pass that string to your template definition:
var mainTemplateString = $("#main-menu-form-tmpl").text().replace(/&/g, "&");
var mainTemplate = $.templates(mainTemplateString);
...
Alternatively you can wrap your template block in <![CDATA and again, strip the wrapper to get the real template markup string you want to pass to the template definition:
var mainTemplateString = $("#main-menu-form-tmpl").text().slice(16, -10);
var mainTemplate = $.templates(mainTemplateString);
...
Related
I want to render the HTML predefined tag (between h2 to h6) based on what is set in my model. Below is the snippet. I am facing issue in my closing tag. closing tag is not processed and it is considered as text and it is truncated in the page view source.
string subArticleLevel = "h2";
if(subarticle.SubTitleLevel!=null)
{
subArticleLevel = subarticle.SubTitleLevel;
}
<#subArticleLevel>#subarticle.SubTitle</#subArticleLevel>
You can use Html.Raw method with explicit code block notation.
#Html.Raw("<")#(subArticleLevel)#Html.Raw(">")#(subarticle.SubTitle)
#Html.Raw("</")#(subArticleLevel)#Html.Raw(">")
Or
Simply use #: prefix to denote it is a start of an html block, if you are already in a code block. The below should work fine.
#{
string subArticleLevel = "h2";
string subarticleSubTitle = "test";
#:<#subArticleLevel>#subarticleSubTitle</#subArticleLevel>
}
I'm not sure what version of MVC you are on but if you have c# 6 you might just use c# string interpolation.
#($"<{subArticleLevel}>{subarticle.SubTitle}</{subArticleLevel}>")
I haven't tried it but if you are getting html encoding you could try.
#Html.Raw($"<{subArticleLevel}>{subarticle.SubTitle}</{subArticleLevel}>")
If you don't have c# 6 available you can try .
#Html.Raw(string.Format("<{0}>{1}</{0}>", subArticleLevel, subarticle.SubTitle))
i am learning asp.net mvc just going through online tutorial
1) just see <span>#model.Message</span> and #Html.Raw(model.Message)
suppose if "Hello Word" is stored in Message then "Hello Word" should display if i write statement like
<span>#model.Message</span> but i just could not understand what is the special purpose about #Html.Raw(model.Message).
what #Html.Raw() will render ?
please discuss with few more example to understand the difference well.
2) just see the below two snippet
#if (foo) {
<text>Plain Text</text>
}
#if (foo) {
#:Plain Text is #bar
}
in which version of html the tag called was introduce. is it equivalent to or what ? what is the purpose of
this tag ?
just tell me about this #:Plain Text is #bar
what is the special meaning of #: ?
if our intention is to mixing text with expression then can't we write like Plain Text is #bar
3) <span>ISBN#(isbnNumber)</span>
what it will print ? if 2000 is stored in isbnNumber variable then it may print <span>ISBN2000</span>. am i right ?
so tell me what is the special meaning of #(variable-name) why bracket along with # symbol ?
4) just see
<span>In Razor, you use the
##foo to display the value
of foo</span>
if foo has value called god then what this ##foo will print ?
5 ) see this and guide me about few more syntax given below point wise
a) #(MyClass.MyMethod<AType>())
b)
#{
Func<dynamic, object> b =
#<strong>#item</strong>;
}
#b("Bold this")
c) <div class="#className foo bar"></div>
6) see this
#functions
{
string SayWithFunction(string message)
{
return message;
}
}
#helper SayWithHelper(string message)
{
Text: #message
}
#SayWithFunction("Hello, world!")
#SayWithHelper("Hello, world!")
what they are trying to declare ? function ?
what kind of syntax it is ?
it seems that two function has been declare in two different way ? please explain this points with more sample. thanks
Few More question
7)
#{
Func<dynamic, object> b = #<strong>#item</strong>;
}
<span>This sentence is #b("In Bold").</span>
what the meaning of above line ? is it anonymous delegate?
when some one will call #b("In Bold") then what will happen ?
8)
#{
var items = new[] { "one", "two", "three" };
}
<ul>
#items.List(#<li>#item</li>)
</ul>
tell me something about List() function and from where the item variable come ?
9)
#{
var comics = new[] {
new ComicBook {Title = "Groo", Publisher = "Dark Horse Comics"},
new ComicBook {Title = "Spiderman", Publisher = "Marvel"}
};
}
<table>
#comics.List(
#<tr>
<td>#item.Title</td>
<td>#item.Publisher</td>
</tr>)
</table>
please explain briefly the above code. thanks
1) Any kind of #Variable output makes MVC automatically encode the value. That is to say if foo = "Joe & Dave", then #foo becomes Joe & Dave automatically. To escape this behavior you have #Html.Raw.
2) <text></text> is there to help you when the parser is having trouble. You have to keep in mind Razor goes in and out of HTML/Code using the semantics of the languages. that is to say, it knows it's in HTML using the XML parser, and when it's in C#/VB by its syntax (like braces or Then..End respectively). When you want to stray from this format, you can use <text>. e.g.
<ul>
<li>
#foreach (var item in items) {
#item.Description
<text></li><li></text>
}
</li>
</ul>
Here you're messing with the parser because it no longer conforms to "standard" HTML blocks. The </li> would through razor for a loop, but because it's wrapped in <text></text> it has a more definitive way of knowing where code ends and HTML begins.
3) Yes, the parenthesis are there to help give the parser an explicit definition of what should be executed. Razor makes its best attempt to understand what you're trying to output, but sometimes it's off. The parenthesis solve this. e.g.
#Foo.bar
If you only had #Foo defined as a string, Razor would inevitably try to look for a bar property because it follows C#'s naming convention (this would be a very valid notation in C#, but not our intent). So, to avoid it from continuing on we can use parenthesis:
#(Foo).bar
A notable exception to this is when there is a single trailing period. e.g.
Hello, #name.
The Razor parser realizes nothing valid (in terms of the language) follows, so it just outputs name and a period thereafter.
4) ## is the escape method for razor when you need to actually print #. So, in your example, you'd see #foo on the page in plain text. This is useful when outputting email addresses directly on the page, e.g.
bchristie##contoso.com
Now razor won't look for a contoso.com variable.
5) You're seeing various shortcuts and usages of how you bounce between valid C# code and HTML. Remember that you can go between, and the HTML you're seeing is really just a compiled IHtmlString that is finally output to the buffer.
1.
By default, Razor automatically html-encodes your output values (<div> becomes <div>). #Html.Raw should be used when you explicitly want to output the value as-is without any encoding (very common for outputting JSON strings in the middle of a <script>).
2.
The purpose of <text> and #: is to escape the regular Razor syntax flow and output literal text values. for example:
// i just want to print "Haz It" if some condition is true
#if (Model.HasSomething) { Haz It } // syntax error
#if (Model.HasSomething) { <text>Haz It</text> } // just fine
As of #:, it begins a text literal until the next line-feed (enter), so:
#if (Model.HasSomething) { #:Haz It } // syntax error, no closing '}' encountered
// just fine
#if (Model.HasSomething)
{
#:Haz It
}
3.
By default, if your # is inside a quote/double-quotes (<tr id="row#item.Id"), Razor interprets it as a literal and will not try to parse it as expression (for obvious reasons), but sometimes you do want it to, then you simply write <tr id="row#(item.Id").
4.
The purpose of ## is simply to escape '#'. when you want to output '#' and don't want Razor to interpret is as an expression. then in your case ##foo would print '#foo'.
5.
a. #(MyClass.MyMethod<AType>()) would simply output the return value of the method (using ToString() if necessary).
b. Yes, Razor does let you define some kind of inline functions, but usually you better use Html Helpers / Functions / DisplayTemplates (as follows).
c. See above.
6.
As of Razor Helpers, see http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx
So HAML 4 includes a coffeescript filter, which allows us coffee-loving rails people to do neat things like this:
- word = "Awesome."
:coffeescript
$ ->
alert "No semicolons! #{word}"
My question: For the end user, is this slower than using the equivalent :javascript filter? Does using the coffeescript filter mean the coffeescript will be compiled to javascript on every page load (which would obviously be a performance disaster), or does this only happen once when the application is started?
It depends.
When Haml compiles a filter it checks to see if the filter text contains any interpolation (#{...}). If there isn’t any then it will be the same text to transform on each request, so the conversion is done once at compile time and the result included in the template.
If there is interpolation in the filter text, then the actual text to transform will vary on each request, so the Coffeescript will need to be compiled each time.
Here’s an example. First with no interpolation:
:coffeescript
$ ->
alert "No semicolons! Awesome"
This generates the code (use haml -d to see the generated Ruby code):
_hamlout.buffer << "<script>\n (function() {\n $(function() {\n return alert(\"No semicolons! Awesome\");\n });\n \n }).call(this);\n</script>\n";
This code simply adds a string to the buffer, so no Coffeescript is being recompiled.
Now with interpolation:
- word = "Awesome."
:coffeescript
$ ->
alert "No semicolons! #{word}"
This generates:
word = "Awesome."
_hamlout.buffer << "#{
find_and_preserve(Haml::Filters::Coffee.render_with_options(
"$ ->
alert \"No semicolons! #{word}\"\n", _hamlout.options))
}\n";
Here, since Haml needs to wait to see what the value of the interpolation is, the Coffeescript is recompiled each time.
You can avoid compiling the Coffeescript on each request by not having any interpolation inside your :coffeescript filters.
The :javascript filter behaves similarly, checking to see if there is any interpolation, but since the :javascript filter only outputs some text to the buffer when it runs there is much less of a performance hit using it. You could possibly combine :javascript and :coffeescript filters, putting interpolated data in :javascript and keeping your :coffeescript static:
- word = "Awesome"
:javascript
var message = "No semicolons! #{word}";
:coffeescript
alert message
matt's answer is clear on what is going on. I made a helper to add locals to :coffeescript filters from a hash. This way you don't need to use global JavaScript variables. As a side note: on Linux, the slowdown is really negligible. On Windows however, the impact on performance is quite important (easily more than 100ms per block to compile).
module HamlHelper
def coffee_with_locals locals={}, &block
block_content = capture_haml do
block.call
end
return block_content if locals.blank?
javascript_locals = "\nvar "
javascript_locals << locals.map{ |key, value| j(key.to_s) + ' = ' + value.to_json.gsub('</', '<\/') }.join(",\n ")
javascript_locals << ";\n"
content_node = Nokogiri::HTML::DocumentFragment.parse(block_content)
content_node.search('script').each do |script_tag|
# This will match the '(function() {' at the start of coffeescript's compiled code
split_coffee = script_tag.content.partition(/\(\s*function\s*\(\s*\)\s*\{/)
script_tag.content = split_coffee[0] + split_coffee[1] + javascript_locals + split_coffee[2]
end
content_node.to_s.html_safe
end
end
It allows you to do the following:
= coffee_with_locals "test" => "hello ", :something => ["monde", "mundo", "world"], :signs => {:interogation => "?", :exclamation => "!"} do
:coffeescript
alert(test + something[2] + signs['exclamation'])
Since there is no interpollation, the code is actually compiled as normal.
I have the url parmeters http://www.nositeinparticular.coom/product1?test=brand&old=Superman&new=Batman.
I was wanting to know the proper way to use javascript to do the following;
Look to see if test=brand
If it does replace all the values of old with the value of new, ie replacing the word Superman with Batman.
I have this so far to see if test equals brand:
$(document).ready(function() {
var url = location.pathname;
if (url.indexOf("test=brand")) {
}
How would I go about parsing the values from the url and running the replacment?
I've noted that # statement in Razor templates converts quotes in strings into HTML symbols.
How can I show correct HTML attribute then? Sample code:
<body#(ViewBag.Highlight == true ? " onload=\"prettyPrint()\"" : "")>
result:
<body onload="prettyPrint()">
That's completely incorrect. How can i achieve normal:
<body onload="prettyPrint()">
in my case?
I've tried HtmlString object from this answer. But it's impossible to convert HtmlString to string even with explicit type cast.
You will need to use Html.Raw(). Try it this way:
#Html.Raw(String.Format("<body{0}>", ViewBag.Highlight == true ? " onload=\"prettyPrint()\"" : ""))
As the documentation says:
Returns markup that is not HTML encoded.