I frequently use code like:
<p #if(Model.Sth)
{
?:style="display: none;"
}>Some text</p>
Many template engines have special markers for conditional blocks, for example in Mustache you can write:
<p {{#Model.Sth}}style="display: none;"{{/Model.Sth}}>Some text</p>
Can my Razor code can be written in shorter form?
In Razor you can embed expressions inside parenthesis to execute them inline. If your conditional can be written using the ternary operator, then you can do something like this:
#(this.Model.Sth ? "style='display:none;'" : string.Empty)
The trick is getting Razor to emit the resulting string correctly back into your HTML. You could use HtmlHelper to do it, but it gets messy enough that the long-form conditional is much cleaner.
In the specific case of an attribute, however, there's a special feature of Razor, as of MVC4, that will help. If you specify an attribute using an expression that evaluates to null, MVC won't emit the attribute at all, so you can do:
<p style="#(this.Model.Sth ? "display:none;" : null)">Some Text</p>
(Note that null and string.Empty are different in this case: Razor will emit style="" if your expression evaluates to empty string.)
Related
I am trying to evaluate an expression that comes from a thymeleaf fragment. But it seems everything is just converted to a string.
Here is what I have in my main template
[(~{text:default_voucher::voucher-code})]
And voucher-code fragment looks like
<th:block th:fragment="voucher-code">${Voucher_code}</th:block>
But the value of Voucher_code does get shown. Instead just the text ${Voucher_code} gets shown.
In my main template if refer the variable there instead of using the fragment, the voucher code shows up.
[[${Voucher_code}]]
Is there a way to get this to work?
Update
I got it working by changing the main template to include the fragment like
<th:block th:insert="~{text:default_voucher::voucher-code}" />
You don't display a value like this in Thymeleaf:
<th:block th:fragment="voucher-code">${Voucher_code}</th:block>
Thymeleaf evaluates expressions inside attributes of tags.
Therefore, it should be something like this:
<th:block th:fragment="voucher-code">
<p th:text="${Voucher_code}"></p>
</th:block>
I use spring boot and thymeleaf. I have many entity and I need to create crud ui. All ui will be similar Is it possible to use reflection to reduce ui to generate?
I would like to loop on the fields and get value in the thymeleaf template
In these days I have been working on an issue very similar to yours.
I have discovered that Thymeleaf has this thing called preprocessing which allows you to have nested expression, so something like this works:
<p th:text="${__${'myObj.myField'}__}"></p>
In this situation, the expression __${'myObj.myField'}__ is evaluated first: after this preprocessing, the expression that will be evaluated by the <p> tag will become:
<p th:text="${myObj.myField}"></p>
Which is the desidered result. Note that, in the preprocessed expression, we are passing the field as a string: therefore, it should be totally possible to create a fragments with a th:each in it which accepts a list of strings in which each string is a field. This list could either be injected directly in the model through Java or could be statically declared in the Thymeleaf's markup. An example of such fragment could be:
<div th:fragment = "show-details">
<tr th:each = "field : ${fieldsToPrint}">
<td th:text = "${__${myObj + '.' + field}__}"></td>
</tr>
</div>
Which could, for example, be used like this:
<div th:replace = "myfragments :: show-details(fieldsToPrint = ${ {'name', 'surname'} }, myObj = ${objFromModel})"></div>
The list of fields could either be generate manually or through Java reflection.
This procedure still involves some work, but way less than creating by hand all the views, especially if you can show all the entities with the same show-details fragments. I have not got around to it yet, but it should be possible to use a similar pattern also for editing such entities.
I've got the following cshtml code in my razor view.
<div class="col left-col pull-left">
#for (int i = 0; i < #Model.NewsResults.Count; i = i + 2)
{
NewsResult article1 = #Model.NewsResults[i];
<div>#i - #article1.Title #Html.Partial("NewsItemPartial", article1)</div>
}
</div>
The #i ... seems to tell razor to ouput the data. If I leave the out there, nothing renders.
Please explain how I can do what I have below but without having to use the (before the #i).
You can tell razor to output HTML by putting the text tag instead of div:
<text>#i - #article1.Title #Html.Partial("NewsItemPartial", article1)</text>
Razor is getting confused because it thinks the - is a subtraction operator, and it's trying to subtract Title from i. you could use Mark's method, or you could make it even more localized by putting the <text> block around the -.
#i <text>-</text> #article1.Title #Html.Partial("NewsItemPartial", article1)
However, it looks to me like you're trying to implement a template output, which MVC already provides a mechanism for, called DisplayTemplates. You should really use those instead of Partials.
As has already been mentioned, Razor is considering the - to be a subtraction operator because of its position right after the #i, which is converting it into a C# block.
You can use <text></text> to convert any block (single line or multiline) into a text literal in Razor.
#i <text>-</text> #article1.Title #Html.Partial("NewsItemPartial", article1)
Or better yet, for a single line (or single character as your example), you can alternatively use the #: operator.
#i #:- #article1.Title #Html.Partial("NewsItemPartial", article1)
Reference: http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx/
I would like to know how to and is it posible to add special charaters after Razor syntax.
Example:
#Html.Raw(Model.Text)()
The problem is with () at the end. I'd like to add it just after generated content.
As an alternative to the <text></text> markup, you can simply wrap your Html.Raw statement in parenthesis. Example:
#(Html.Raw(Model.Text))()
This will prevent razor from trying to parse the extra set of parenthesis as they help razor determine when to stop parsing the markup.
Try this:
#Html.Raw(Model.Text)<text>()</text>
<text></text> is special razor markup, not to be confused with actual HTML.
The <text> tag is an element that is treated specially by Razor. It causes Razor to interpret the inner contents of the <text> block as content, and to not render the containing <text> tag element (meaning only the inner contents of the <text> element will be rendered – the tag itself will not). This makes it convenient when you want to render multi-line content blocks that are not wrapped by an HTML element.
Quoted from ASP.NET MVC 3: Razor’s #: and <text> syntax.
I was just wondering how you use the underscore templates in a .aspx view since the <%= %> tags that underscore uses get picked up by the .aspx rendering engine and give me errors.
For instance:
<script type="text/template" id="my-template">
<span class="event" title="<%= description %>">
<%= title %>
</span>
</script>
This template gives me an error since the .aspx rendering engine thinks I'm trying to bind this stuff to the Model.
Thanks.
From the fine manual:
template _.template(templateString, [data], [settings])
[...]
If ERB-style delimiters aren't your cup of tea, you can change Underscore's template settings to use different symbols to set off interpolated code. Define an interpolate regex to match expressions that should be interpolated verbatim, an escape regex to match expressions that should be inserted after being HTML escaped, and an evaluate regex to match expressions that should be evaluated without insertion into the resulting string.
So if the default <%=...%>, <%-...%>, and <%...%> delimiters aren't working for you then you can use different ones with a simple configuration change. For example, if you wanted to use {%...%} instead of <%...%>, then do this after underscore.js is loaded and before you use _.template:
_.templateSettings = {
interpolate: /\{%=(.+?)%\}/g,
escape: /\{%-(.+?)%\}/g,
evaluate: /\{%(.+?)%\}/g
};
Demo: http://jsfiddle.net/ambiguous/TfB5M/