Calling messages.properties dynamically with controller model variable and Thymeleaf - spring-boot

I have my messages.properties like this:
tablas.menu.paises=Pa\u00EDses
tablas.menu.regiones=Regiones
tablas.menu.anhos=A\u00F1os
tablas.menu.universidades=Universidades
tablas.menu.usuarios=Usuarios
In the .html I have a menu showing each item with th:each:
<li class="nav-item" th:each="menu : ${menus}">
<a th:text="#{tablas.menu.${menu.nombre}}"></a>
</li>
For each "menu in ${menus}", menu.nombre has the values paises, regiones, anhos...
But thymeleaf doesn't recognise the model variable inside the #{}, and this it is giving me in the view the error when it doesn't find the message:
??tablas.menu.${menu.nombre}_es_ES??
Configuration is ok, if I change the call for #{tablas.menu.regiones} I get 'regiones' and so.
Is there any way to call a message from messages.properties dynamically using a model variable like this?
Thanks.

You can use the #messages utility object for this:
<a th:text="${#messages.msg('tablas.menu.' + menu.nombre)}" />
Or you can create the string using literal substitution:
<a th:text="#{|tablas.menu.${menu.nombre}|}" />
I would recommend using preprocessing only as a last resort, as bad values can cause runtime errors. (Although they do work for this.)

Related

How to prevent loops in laravel global variable

I've created file GlobalVariable.php inside app\Composers
public function compose($view)
{
$categories = \App\Models\Category::all();
$view->with('globCategory', $categories);
}
then register to AppServiceProvider the code view()->composer('*', GlobalVariable::class);
I use global $globCategory for creating dynamic navbar
<ul class="nav nav-tabs border-0 flex-column flex-lg-row">
#foreach ($globCategory as $item)
<li class="nav-item">
{{$item->name}}
</li>
#endforeach
</ul>
the only problem here when I see laravel debuggar it show repetition of categories query.
here is the result
How to avoid this looping query? is there correct way?
The way you're registering your view composer (using '*' instead of a particular view name), it's going to call the compose method for every single rendered view + subview.
What you can do is instead of this:
view()->composer('*', GlobalVariable::class);
Have this:
\View::share('globCategory', \App\Models\Category::all());
This will globally share your categories (within views), and run the query only once.
View composers, as described from the laravel documentation, bind data to a view every time it is rendered. They clean our code by getting fetching data once and passing it to the view.
While it is possible to get the data in every controller method and pass it to the single view, this approach may be undesirable.
Replace the view name with an asterisk wildcard.

Translation in parameter of translation with Thymeleaf

Using Thymeleaf 3.0.9, suppose I have this translation:
hello=Hello {0}
In my template, I have:
<span th:text="#{hello(${user.getName()})}"></span>
Now suppose user.getName() can be null, so I want to display something nice in that case:
<span th:text="#{hello(${user.getName()?:'Unknown'})}"></span>
This works fine.
Now I also want to tranlate Unknown, how can I do this?
I tried:
<span th:text="#{hello(${user.getName()?:#{unknown})}"></span>
But that does not seem to work.
I think you can use the #messages utility object:
<span th:text="#{hello(${user.getName()?:#messages.msg('unknown')})}"></span>
And add property in the messages file(s):
unknown=Unknown

How can I capitalize a string showed by Thymeleaf into a page?

I am working on a Spring MVC application that uses Thymeleaf as template engine and I am trying to capitalize some string showed into my page. On my page I have something like this:
<li class="com__nav-item" th:each="menuItem : ${#authentication.principal.listaFunzioniUtente}">
<a href="" class="com__nav-link centered">
<span class="blue-line animate scaleIn delay-3" style="font-size: 1.4em; text-align: center;" th:text="${#strings.capitalize(menuItem.desFnz)}"></span>
<span class="white-circle animate scaleIn delay-5"></span>
</a>
</li>
As you can see in the previous code, in the first <span> tag, I show a string inside the desFnz property of the menuItem object.
It works fine, my problem is that I want capitalize all the characters, so I tried to do:
th:text="${#strings.capitalize(menuItem.desFnz)}"
using the #strings.capitalize() but it can't work, in fact in my page I still obtain the text but not capitalized. Why? What am I missing? How can I fix this issue?
#strings.capitalize(menuItem.desFnz) will only capitalize the 1st character, where as #strings.toUpperCase(menuItem.desFnz) will convert the entire string to uppercase. Here is the documentation for the Strings class.
you can do it by
$string.toLowerCase() or $string.toUpperCase()
Just adding to Pradeep Pati's point.
In case you are using it in the spring boot project where some of your values are coming from messages.properties
like In messages.properties file, You have something like:
email.dailyAlert.greeting.newTemplate = Dear {0},
Then to substitute the value in place of {0} (in the Title case), you need to write like the below line.
<p th:text="#{email.dailyAlert.greeting.newTemplate(${#strings.capitalize(orgSlug)})}"></p>
The final output will be:
Dear Organisation,

Laravel: Render queried Data whith Blade functions

Currently I'm getting some data from the database and after that I want to render it within my Blade template.
In my queried data I have blade functions like url('/foo') combined with some html. And here is the problem.
When I'm using {!! $child->description !!} the HTML is rendered correctly, but my Blade function won't work:
Function: url('/foo)
Output: http://myurl.de/url('/foo')
When I'm using the "normal" Syntax like {{ $child->description }} the generated URL is correct (http://myurl.de/foo), but the HTML is not rendered.
So my question is:
How can I use my queried Blade function within rendered HTML? ^^
/Edit
Okay, perhaps my question is too abstract. So I want to show you my problem based on my example. (generated template image - only on german, sorry)
Every form is a database entry like:
categoryName
categoryParent
...
categoryDescription
As you can see on my image, the categoryDescription is the small text under my first input field with the small button.
I want to use this script abstract as possible so that I can fill the entry with every content I want to fill in.
In this case my content is:
lore ipsum <a class="btn btn-primary btn-sm pull-right" href="url('foo')">dolor</a>
As you can see there is the mentioned Blade-function (url) and the HTML.
{!! !!} - this dont escapse string so if u have something from database like,
something it would output it like that.
While in other hand {{ }} this would give you just "something" without , it is used to protect you from injections.
Maybe blade error.{{}}
lore ipsum <a class="btn btn-primary btn-sm pull-right" href="{{url('foo')}}">dolor</a>
Laravel Blade

Bind custom attributes on Ember view with controller data in xhandlebars script

{{#each App.SampleViewController}}
{{#view App.SampleView contentBinding="this" sort-date="content.sortDate" name="content.name"}}
<a href="#" onclick="App.loadSampleDetails(this);" {{bindAttr id="content.id"}}>
{{/view}}
{{/each}}
How to add custom attributes/generic attributes (like in the above example sort-date/name attributes) to the view element from the xhandlebars script tag, I know that using attributeBindings we can add, but I have the dynamic data coming from controller through each.
You can use the attributeBindings property to define additional attributes that will get added to the DOM output for a view. See the "HTML Attributes" section in the Ember.View docs: http://docs.emberjs.com/#doc=Ember.View&src=false

Resources