Create a Map in Thymeleaf html - thymeleaf

Currently I have created a fragment which takes a list of properties and urls in order to create a menu:
menuFrag (thymeleafMap)
I wanted to populate this in the front end but I am not sure how to make directly in thyme leaf
<div th:replace="fragments/menu :: menuFrag ((<#{menu.item1},#(/menuItem1)><(#{menu.item2},#(/menuItem2)>))"></div>
Is there a way to do this or would it I have to pass this information down from the controller?
Also if there was a way for me to just pass in two array's that would also work.

It is actually possible to write map literals in thymeleaf, like this:
<div th:replace="fragments/menu :: menuFrag (menu=${ {{item:'Item1',url:'/menuItem1'},{item:'Item2',url:'/menuItem2'}} })"></div>
(Note that it is in fact a map nested into a list to be able to iterate over the outer one. Thymeleaf (or should I say SpringEL) seems to produce LinkedHashMap for the map and ArrayList for the list according to my observations)
You can then iterate over the items in your menu fragment like this:
<ul th:each="item: $(menu)">
<li><a th:text="${item.item}" th:href="#{${item.url}}" />Item</li>
</ul>

i hope i understand your question right.
First you can create a Map<key, value>, key is the menu name (#{menu.item1}) and the value is the URL (#(/menuItem1)) in your controller where the journey begin.
Controller looks something like this:
Map<String, String> menu = new HashMap<String, String>();
menu.put("Google", "www.google.de");
menu.put("Yahoo", "www.yahoo.de");
menu.put("Apple", "www.apple.de");
menu.put("Microsoft", "www.microsoft.de");
model.addAttribute("menuMap", menu);
Second you have the two templates, the first is your main and the second the menu fragment. In the main you have to "access" the map from your controller and call the 'menu' fragment, like this:
<div th:include="menu :: copy(${menuMap})"></div>
in the second template, menu fragment you take the map that you get from the main and iterate over this, like the following:
...
<div th:fragment="copy(menuMap)" >
Hello World
<ul th:each="instance : ${menuMap}">
<li><a th:text="${instance.key}" th:href="#{${instance.value}}">key</a></li>
</ul>
</div>
...
That's all, with this you get your menu.

Related

object does not contain definition for pageNumber

I am trying to simply run a foreach loop inside my view of my MVC application. But, in debug mode I can see it got the list successfully. However, I get an error saying object does not contain definition for pageNumber. Please, note pageNumber is available on each of those list. What am I doing wrong?
MVC View code:
#foreach (var button in ViewBag.PageButtons)
{
<li class="page-item"><a class="page-link" href="#">#button.pageNumber</a></li>
}
Your error dialog and the message show the type of button is an object in the View. As the error states, the .NET object does not contain a definition of pageNumber indeed. In the View, you need to cast button to your type.
The new code may look like this (CRLFs are for readability):
#foreach (var button in ViewBag.PageButtons)
{
<li class="page-item">
<a class="page-link" href="#">
#(((YourClassNameHere)button).pageNumber)
</a>
</li>
}
You need to replace YourClassNameHere with whatever class name you used to define an element of the list you send to the View.
ViewBag is dynamic, so you'll need to cast your button for the call to .pageNumber to work:
#((button as PageButton).pageNumber)
or
#(((PageButton)button).pageNumber)

Velocity solution like Thymeleaf

I would like to know if I can use Velocity Template like Thymeleaf when I have an object in Spring with attributes, let say, (product.courseName) and I want to send it to an HTML page this way
h1 th:text="${product.courseName}" HTML Example Course Name /h1
so i can show it directly...
Thymeleaf let me isolate the HTML development from the Spring Coding, but I cannot find such a simple approach in Velocity. Can I show the HTML with "HTML Example Course Name" in a browser and the real Course Name from each object when Velocity executes (just like in Thymeleaf)?
PD: I would appreciate any documentation reference.
SPRING CONTROLLER
#RequestMapping("/product/{id}")
public String getProductById(#PathVariable Integer id, Model model){
model.addAttribute("product", productService.getProduct(id));
return "product";
}
PRODUCT.HTML
<div class="row">
<div class="col-md-12">
<h1 th:text="${product.courseName}">Course Name</h1>
</div>
</div>
Thanks
Yes but not exactly you are doing it. If you take a look the section properties of the reference documentation it's explained how to do it:
Properties
The second flavor of VTL references are properties, and properties
have a distinctive format. The shorthand notation consists of a
leading $ character followed a VTL Identifier, followed by a dot
character (".") and another VTL Identifier. These are examples of
valid property references in the VTL:
$customer.Address
$purchase.Total
And aswell is explained, if you use it, it calls the getter of the property like thymeleaf surely does.
$customer.Address. It can have two meanings. It can mean, Look in the
hashtable identified as customer and return the value associated with
the key Address. But $customer.Address can also be referring to a
method (references that refer to methods will be discussed in the next
section);
$customer.Address could be an abbreviated way of writing
$customer.getAddress()
........
edited
So in resume, don't use thymeleaf tags like th:text.
<h1>$product.courseName</h1>

Accessing a single value using foreach loop in view coming from the view model in durandal

I have a Project Title, what I want to do is when I click on the title, all of the associated activities are displayed, I have an API, which brings all the associated activities,API is developed in YII framework, the API is called in view model and all the activities are accessible in the view through foreach loop, what I want to do is to display a single activity a time, at the moment when i click on project title, all activites are displayed, I want one activitiy to be displayed when clicked once. Please if any one can answer.
this is my viewModel...
function fetchProjectActivities() {
var self = this;
// this.current_activities.length=0;
dataservice.projectactivities(self.id()).then(function (data) {
//self.current_activities().clear();
for (x in data) {
self.current_activities.push(new Activity(data[x].activity.id, data[x].user_id, data[x].user.first_name, data[x].user.last_name, data[x].activity.message, new Date(data[x].create_date), data[x].time_spent, data[x].tags, null, data[x].activity.status,
self.name()));
}
console.log("aaa" + self);
});
}
and this is my view...
<div class="grid-item project-item clearfix">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"><h3>
<div data-bind="foreach:projects">
<div data-bind="foreach: current_activities">
<span data-bind="text: title()"></span>
</div>
</div>
</div>
</div>
and here is the function which gets invoked when I click on Projects title.
Project Name: <a data-bind="click: $root.fetchProjectActivities"><span data-bind="text: name()">
There are a couple of thing that I can see.
there is a rogue <h3> tag in the html that will cause grief with knockoutjs. that will need to be closed or removed.
the for loop in the view model really should be for (var x in data) {...} otherwise you will end up with x declared as a variable on the global scope.
Now to cycle through the activities of the project, what you are effectively doing is paging through current_activities array, one at a time. You will need to keep track of the currently selected activity and a way to go forward with each click and a list of all the activities.
so you will need a pager view model. there is a very basic one on the knockoutjs site that you could use and modify to your needs.

Direct Model.Property versus Html Helper DisplayFor in Razor

Is there a reason to use preferably one of these:
#Model.Property
#Html.DisplayFor(m => m.Property)
I never arrived in a crossroad where one works differently from the other.
There is any difference?
Model.Property - as you know - will just write out the value of the property in question. Html.DisplayFor(m => m.Property), on the other hand, will call a display template, which can render out other markup around the property value.
For example, you might define a display template like so:
#model String
<div class="property-wrapper">
<p>#Model.Property</p>
</div>
The surrounding divs will be rendered around the value of the property when using DisplayFor (if the display template is selected, which typically means it has a filename matching the property's type, is specified in the UIHint attribute for the property, or is explicitly specified in the call to DisplayFor.
You also have access to model metadata in your display templates, meaning you can do something like this:
<div class="property-label">
#Html.DisplayNameForModel()
</div>
<div class="property-value">
#Model.Property
</div>
Display templates give you a huge amount of flexibility and reusability. The best way to explore this is to start building custom templates and see where it takes you.

How to serialize each item in IEnumerable for ajax post

I have a PartialView that displays IEnumerable<Movie>.
_MoviePartial.cshtml
#foreach(var movie in Model) {
<div class="content">
<span class="image"><img src="#movie.Posters.Profile" alt="#movie.Title"/></span>
<span class="title">#movie.Title</span>
<div class="score`">
<span class="critics-score">#movie.Ratings.CriticsScore</span>
<span class="audience-score">#movie.Ratings.AudienceScore</span>
</div>
#Html.ActionLink("Add Movie", "Add", "MyMovies")
</div>
}
When the user clicks the "Add Movie" ActionLink I am going to do an ajax post to add the selected movie to the users collection. My problem is that I would like to send the entire selected Movie class to the "Add" action but not sure how to serialize each movie since the entire Movie class is not rendered in the PartialView, just a few properties. I know I can serialize something like this...
<script type="text/javascript">
var obj = #Html.Raw(Json.Encode(movie));
</script>
But I'm not sure how that would work inside a foreach loop that renders html, especially inside a PartialView.
So, just to be clear, when a user clicks the "Add Movie" ActionLink I would like to send the serialized Movie class for that respective movie to my controller via ajax.
My questions is...
Is there a better way to serialize each movie and append it to it's respective anchor? I know there's the data- html5 attribute but I thought they only allow string values, not json objects. I also know I could use jQuery's .data() function but I'm struggling to think through how to get that to run from a PartialView, especially since the html rendered by _MoviePartial.cshtml may be returned from a controller via ajax.
A framework such as knockout.js would really make your life easier here.
Basically, you would:
Load all the movie data as a JSON array using eg: Json.Encode(Model);
Create a foreach template using knockout to render your data. Knockout will then handle the trouble of keeping the displayed movies to a complete movie model.
My preference is to return a JSON object as the response with two properties; HtmlString and Data. HtmlString may contain a rendered partial view and Data may contain a serialized object of the request.
I find this is insanely easier to work with JSON, then trying to return HTML with embedded JSON object(s).

Resources