how to extract a whole number in Thymeleaf? - thymeleaf

I do not find the way to get the whole part of a decimal number in Thymeleaf.
For example: 2,54 will be 2, or 234,01 will be 234.
numbers.formatInteger
rounds the number up or down, but 2,54 gets to 3 instead of 2.

I can't find a simple way to do this with the built in thymeleaf objects/methods, but this will work (even if it's a little painful).
Controller
#GetMapping
public String page(Map<String, Object> model) {
.
.
DecimalFormat f = new DecimalFormat("#");
f.setRoundingMode(RoundingMode.FLOOR);
model.put("format", f);
.
.
}
Page
<th:block th:with="n=${2.54}">
<!-- outputs 2 -->
<span th:text="${format.format(n)}" />
</th:block>

Related

Inline Razor output after dash

I don't know how to output a variable in Razor as part of an attribute name after a dash:
<span data-#(DataAttributeName)="value"/>
// fails, output:
<span data-#(DataAttributeName)="value"/>
<span data- #(DataAttributeName)="value"/>
// works, however, the space results in invalid HTML:
<span data- myname="value"/>
How to do that properly?
Currently, I have the following workaround:
<span #("data-" + DataAttributeName)="value"/>
But I don't like it for obvious style reasons + Visual Studio tells me that "an attribute name is expected" and shows an error (although it seems to work properly), also something I don't like.
That's a tricky part in razor engine, it tries to be smart to save some escape but sometimes leave no easy solution in scenarios like this.
Just to stay neat, I may create a HtmlHelper Extension, which might be a overkill, but just in case you are sick of red things in editor like me :)
public static class MyHtmlHelperExtension
{
public static MvcHtmlString DataAttribute(this HtmlHelper helper, string attrName, string value)
{
return new MvcHtmlString(string.Format("data-{0}='{1}'", attrName, value));
}
}
Then in your view it can be somehow cleaner:
<span #Html.DataAttribute(DataAttributeName, "value") />

XPath Node selection

I am using HtmlAgilityPack to parse data for a Windows Phone 8 app. I have managed four nodes but I am having difficulties on the final one.
Game newGame = new Game();
newGame.Title = div.SelectSingleNode(".//section//h3").InnerText.Trim();
newGame.Cover = div.SelectSingleNode(".//section//img").Attributes["src"].Value;
newGame.Summary = div.SelectSingleNode(".//section//p").InnerText.Trim();
newGame.StoreLink = div.SelectSingleNode(".//img[#class= 'Store']").Attributes["src"].Value;
newGame.Logo = div.SelectSingleNode(".//div[#class= 'text-col'").FirstChild.Attributes["src"].Value;
That last piece of code is the one I am having problems with. The HTML on the website looks like this (simplified with the data I need)
<div id= "ContentBlockList" class="tier ">
<section>
<div class="left-side"><img src="newGame.Cover"></div>
<div class="text-col">
<img src="newGame.Logo http://url.png" />
<h3>newGame.Title</h3>
<p>new.Game.Summary</p>
<img src="newGame.StoreLink" class="Store" />
</div>
</div>
</section>
As you can see, I need to parse two images from this block of HTML. This code seems to take the first img src and uses it correctly for the game cover...
newGame.Cover = div.SelectSingleNode(".//section//img").Attributes["src"].Value;
However, I'm not sure how to get the second img src to retrieve the store Logo. Any ideas?
newGame.Cover = div.SelectSingleNode(".//img[2]").Attributes["src"].Value;
You didn't post the entire thing but, this should do the trick.
You can try this way :
newGame.Cover = div.SelectSingleNode("(.//img)[2]")
.GetAttributeValue("src", "");
GetAttributeValue() is preferable over Attributes["..."].Value because, while the latter throws exception, the former approach returns the 2nd parameter (empty string in the example above) when the attribute is not found.
Side note : your HTML markup is invalid as posted (some elements are not closed, <section> for example). That may cause confusion.

How to display a string with new lines as a string with <br />'s in AngularDart?

Given that I have a string being displayed on the page in AngularDart.
... <strong>Notes: </strong> {{cmp.selectedStudent.notes}} ...
How can I make it display multi-line? In the string I have newline characters, I want them to be encoded as <br /> characters in the html output.
You can replace the '\n' in your string with <br/> and use something like the proposed my-bind-html directive shown in my answer here How to add a component programatically in Angular.Dart? (the code might be a bit outdated due to a lot of recent changes in Angular)
You could use ng-repeat and repeat over your notes lines but first you need to split them by '\n' so you get an array of lines.
List<String> _notesList = null;
List<String> get notesList {
if (_notesList==null) _notesList = notes.split("\n").toList(); return _notesList;
}
.
<span ng-repeat="note in cmp.selectedStudent.notesList">{{note}}<br /></span>
By default, angular doesn't interpret HTML balise to avoid some unpredictible behavior or others bad thing, but you can disable this verification with
ng-bind-html
link to the official doc : NgHtmlBind
So you can replace directly the '\n' character by the 'br' html node.
So you can do :
// ...
String getHtmlBrNote() {
return this.notes.replaceAll("\n", "<br />");
}
// ...
and after in angular
... <strong>Notes: </strong> <span ng-bind-html="cmp.selectedStudent.getHtmlBrNote()"></span> ...
And it will be ok

Razor syntax isn't recognizing '#' after an underscore

I am trying to do the following:
#foreach(var p in #Model.line_products){
<img class="small_img_#Model.line_products[i].short_name" src="/Content/images/#Model.line_products[i].image_name" />
}
Which isn't working, it renders the text just the way it is, not recognizing the '#'. I found this other post in Stackoverflow, which suggests adding parenthesis in the following way:
#foreach(var p in #Model.line_products){
<img class="small_img_(#Model.line_products[i].short_name)" src="/Content/images/#Model.line_products[i].image_name" />
}
Using this workaround, I get that my id is rendered as small_img_(MODEL ATTRIBUTE). Isn't there a workaround which doesn't require adding specific characters? (such as the parenthesis).
You have more errors than a simple undercore problem here. You cannot use #Model inside your if. You are already in a # block. Simply use #foreach(var p in Model.line_products).
Plus, the way you wrote the parenthesis, they will get rendered. What you want is
small_img_#(Model.line_products[i].short_name)
Put the parenthesis after the # instead of before:
class="small_img_#(Model.line_products[i].short_name)"
I sometimes put a couple of Guids in the id of an element and an underscore separator doesn't work.
There are two ways around this. First use the entity code _ instead and secondly just use a hyphen.
<input id="chk_#classLeader.ClassLeader_#ing.Ingredient.Guid" type="checkbox" class="chk_Done form-check">
<input id="chk-#classLeader.ClassLeader-#ing.Ingredient.Guid" type="checkbox" class="chk_Done form-check">
This is because I want to grab out the Guid's when the check box is clicked with some JQuery like this:
$(".chk_Done").click(function () {
var obj =[];
const itemId = ($(this).attr("id"));
const myArray = itemId.split("_");
var ClassLeaderGuid = myArray[1], IngredientGuid = myArray[2];

How can I change the way GRAILS GSP fieldValue formats Integers?

I have a field in my domain object which I define as an Integer...
Integer minPrice
I then access it in a GSP page as follows:
${fieldValue(bean: myBean, field: 'minPrice')}
and what I get in my HTML is...
100,000
which is not an Integer, it's a String. Worse still it's a formatted String in a particular locale.
This is a problem because I have a SELECT control on an HTML FORM which has a (non-ordinal) range of values for minPrice which I want to store in my domain object as integers, and I don't want to store an index to some array of values that I have to repeatedly map back and forth between, I want the value itself.
My select control looks like this...
<g:select name="minPrice"
value="${fieldValue(bean: personInstance, field: 'minPrice')}"
onchange="setDirty()"
noSelection='${['0':'Select a number...']}'
from="${[
['name':'100,000', 'id':100000],
['name':'200,000', 'id':200000],
['name':'300,000', 'id':300000]
]}"
optionKey="id" optionValue="name"
/>
When I get the value from the SELECT field to post back to the server it correctly has an Integer value, which I persist. However the return trip never pre-selects the right row in the drop-down because the value is this comma separated String.
This works fine elsewhere in my code for small numbers where the comma formatting doesn't come into play, and the round-trip in and out of the SELECT is successful. But values >999 don't work.
The docs say "This tag will inspect a bean which has been the subject of data binding and obtain the value of the field either from the originally submitted value contained within the bean's errors object populating during data binding or from the value of a bean's property. Once the value is obtained it will be automatically HTML encoded."
It's that last bit that I want to avoid as it appears to format Integers. So, what little bit of Grails/GSP magic do I need to know so I can get my Integer to be rendered as an integer into my SELECT and pre-select the right row?
EDIT:
I have tried some further things based on the answers below, with pretty disappointing results so far...
If I put the <gformatNumber/> tag in my <g:select/> I get the page code as text in the browser.
<g:select name="minPrice"
value='<g:formatNumber number="${fieldValue(bean: personInstance, field: 'minPrice')}" format="#" />'
onchange="setDirty()"
noSelection='${['0':'Select a number...']}'
from="${[
['name':'100,000', 'id':100000],
['name':'200,000', 'id':200000],
['name':'300,000', 'id':300000],
]}"
optionKey="id" optionValue="name"
/>
Using the number format tag from GSP on my Integer value of 100000 like this...
var x = <g:formatNumber number="${fieldValue(bean: personInstance, field: 'minPrice')}" format="#" />;
gives 100. Remember that the fieldValue gives back 100,000, so this is not a surprise.
If I use the jsp taglib like this...
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
var y = <fmt:formatNumber value="${fieldValue(bean: personInstance, field: 'minPrice')}" pattern=".00"/>;
I get an error from the page compiler Cannot format given Object as a Number.
I guess I have a wider concern than I can't seem to get an Integer value as a genuine integer into my code if it is greater than 999 because of the default (and unconfigurable) behaviour of the fieldValue directive. However my specific problem of not being able to pre-select an Integer value in a SELECT control is not going away. At the moment I'm at a bit of a loss.
Anyone have any further ideas?
Do you want to show the raw number? like 100000?
You can get the field directly:
${myBean.minPrice}
I think you have at least two possible solutions.
One is to use the JSTL taglib as described in the docs.
Another, cooler way is to use the 'formatNumber' tag included with grails - also in the docs.
For your purpose, the use of that tag might look like this:
<g:formatNumber number="${fieldValue(bean: myBean, field: 'minPrice')}" format="######" />
Use the 'groupingUsed' attribute in combination with your format:
<g:formatNumber number="${fieldValue(bean: personInstance, field: 'minPrice')}"
format="#"
groupingUsed="true" />
Better use custom PropertyEditor in order not to bother with formatNumber tag every time you output a value.
Like, declare a bean in resources.groovy:
myOwnCustomEditorRegistrar(CustomEditorRegistrar)
And create your class:
class CustomEditorRegistrar implements PropertyEditorRegistrar {
void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(BigDecimal.class, new MyBigDecimalEditor(BigDecimal.class))
}
}
Change
var x = <g:formatNumber number="${fieldValue(bean: personInstance, field: 'minPrice')}" format="#" />;
to
var x = <g:formatNumber number="${personInstance.minPrice}" format="#" />;
I found the best way to handle this was doing what Victor Sergienko (upped btw) hinted at with using a PropertyEditor.
Create an editor for Integer, put in src/groovy:
class IntegerEditor extends PropertyEditorSupport {
void setAsText(String s) {
if (s) value = s as Integer
}
public String getAsText() {
value
}
}
and register it using a PropertyEditorRegistrar (also in src/groovy):
class MyEditorRegistrar implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry reg) {
reg.registerCustomEditor(Integer, new IntegerEditor())
}
}
add your registrar into the spring config (grails-app/conf/spring/resource.groovy):
beans = {
customEditorRegistrar(MyEditorRegistrar)
}
From now on any Integers that are bound, receive errors (or not) and then redisplayed with the fieldValue tag should be displayed by Integer's default toString - you can customise this behaviour in the editor by amending the getAsText implementation.
Personally I would create a wrapper for this kind of thing so you can set up an editor just for that type rather than across the board for a frequently used type. Though I realise this would mean a little bit of mapping when persisting to the DB...
I have a solution/work-round... The answer seems to be, "do nothing".
Instead of trying to parse the stringified number back into an integer, I left it as a formatted string for the purposes of the select. This meant I had to change my from values as follows:
<g:select name="minPrice"
value="${fieldValue(bean: personInstance, field: 'minPrice')}"
onchange="setDirty()"
noSelection='${['0':'Select a number...']}'
from="${[
['name':'100,000', 'id':'100,000'],
['name':'200,000', 'id':'200,000'],
['name':'300,000', 'id':'300,000']
]}"
optionKey="id" optionValue="name"
/>
Of course when I post back to the server the value that gets sent is "100,000" as an escaped String. What I realised was that Grails, or Spring, or Hibernate, or something in the stack, would do the coersion of the String back into the right Integer type prior to persistence.
This works just fine for my purposes, however I think it is basically a work-round rather than a solution because of locale issues. If my thousand separator is a "." and my decimal separator is ",", which it is for much of Europe, then my code won't work.
Use like this :
<g:formatNumber number="${fieldValue(bean: personInstance, field: 'minPrice')}"
format="#.##"/>;

Resources