Global Variables in Razor View Engine - asp.net-mvc-3

Is there a way for me to use a functionality similar to what are called Global Variables in the Spark View Engine, but for Razor.
The point of it all lis to be able to define a variable in one section for the title and then being able to set or change the value of that variable later on in another section.
In Spark you would create the variable in a section kind of like this (incomplete code for example purposes):
<html>
<head>
<global type='string' Title='"Site Name"'/>
<title>${Title}</title>
</head>
<body>
<div><use content="view"/></div>
</body>
</html>
And then you could set it in a different view or section or whatever:
<set Title='product.Name + " - " + Title'/>
How would I go about doing something like this in Razor or just solving a similar problem if I have the wrong approach ?

You could use ViewBag.Title inside the layout:
<html>
<head>
<title>#ViewBag.Title - Site Name</title>
</head>
<body>
<div>
#RenderBody()
</div>
</body>
</html>
and then define this variable inside the view:
#model AppName.Models.Product
#{
ViewBag.Title = Model.Name;
}
UPDATE:
Following on the comments question about default values you could use sections.
<html>
<head>
<title>
#if (IsSectionDefined("Title"))
{
RenderSection("Title")
}
else
{
<text>Some default title</text>
}
</title>
</head>
<body>
<div>
#RenderBody()
</div>
</body>
</html>
and then inside your view you could redefine the section if you will:
#section Title {
<text>some redefined title here</text>
}

You can set and then overwrite this value in view as well using this approach:
#PageData["myTitle"] = "Title 1";

Related

Thymeleaf switch statement including every case

I'm working on my first Spring MVC project and I got stuck at a problem. I have 3 types of users in my application: admin, employee and customer. Depending on the type of user, I would like to have a specific type of menu for each of them. I tried using a switch statement in my thymeleaf template but every case gets included in the output and I don't understand why.
This is the code for my method in the controller:
#RequestMapping(value = "list/{roleId}", method = RequestMethod.GET)
public String listFood(Model model, #PathVariable int roleId){
model.addAttribute("title", "Available Foods");
model.addAttribute("roleId", roleId);
model.addAttribute("foods", foodDao.findAll());
return "food/list";
}
And this is the code from the Thymeleaf template (each fragment will be included in the resulting page):
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head th:replace="fragments :: head"></head>
<body class="container">
<h1 th:text="${title}">Food</h1>
<div th:switch="${roleId}">
<p th:case="0"><nav th:replace="admin-fragments :: navigation"></nav></p>
<p th:case="1"><nav th:replace="employee-fragments :: navigation"></nav></p>
<p th:case="2"><nav th:replace="customer-fragments :: navigation"></nav></p>
</div>
</body>
</html>
However, if I change the template to the following one then only the correct case will be included in the resulting page.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head th:replace="fragments :: head"></head>
<body class="container">
<h1 th:text="${title}">Food</h1>
<div th:switch="${roleId}">
<p th:case="0">User is an administrator</p>
<p th:case="1">User is an employee</p>
<p th:case="2">User is a customer</p>
</div>
</body>
</html>
Why isn't the switch from the first template behaving like the one in the second template? What should I change in the first template to be able to have a personalised menu for each type of user? Thank you!

Thymeleaf in spring boot

I am trying to use an HTML template as given below and set 2 values to it dynamically.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title th:text="${title}"></title>
</head>
<body>
<div class="page-content">
<h1 th:text="|Hello ${siteCode}!|"></h1>
</div>
</body>
</html>
I used the below code to set the values.
Model model = new ExtendedModelMap();
model.addAttribute("title", site.getName());
model.addAttribute("siteCode", site.getCode());
I want to get the new html file with the values added in the template variable so that I can store the file to s3. Please help.. Thanks in advance.

Extend A View With Thymeleaf

is it possible extend a shared view with thymeleaf?
I saw that is possible use framents but is not what I want.
Instead I want something similar to .NET MVC, with something like #RenderBody() and another view that extend the shared view by including the shared view.
You can use the Thymeleaf Layout Dialect to extend a view.
Layout page
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
...
<body layout:fragment="body">
...
</body>
</html>
Content page
In your content page, you refer to the layout (decorator) page using the layout:decorator attribute.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout.html">
...
<body layout:fragment="body">
<p>Actual page content</p>
</body>
</html>
It is possible to have multiple fragments in one page.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
...
<body>
<div layout:fragment="content"></div>
<footer layout:fragment="footer"></footer>
</body>
</html>

want to put #renderbody() into a partial view source by _layout

Creating an MVC 3 Razor project. have a very involved UI design. I wanted to put #renderbody() into a partial view source by _layout. The compiler won't let me. Is there a way to do this?
Instead of partial view you can go for master/sub layouts.
MasterLayout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
</head>
<body>
#RenderBody()
</body>
</html>
Layout.cshtml
#{
Layout = "~/Views/Shared/_MasterLayout.cshtml";
}
// html code above render body
#RenderBody()
// html code below render body
Your sublayout(Layout.cshtml) contains the code that should be in the partial view.

ASP.NET MVC layout

I have layout page and the page that uses layout.
How can I add some new elements to the head not changing layout.(layout already contains head)?
Layout:
<head>...</head>
I want my page be like:
<head>all layout head logic... plus
my page new elements...
</head>
You could use sections in the layout. For example:
<html>
<head>
#RenderSection("scripts", false)
</head>
<body>
#RenderBody()
</body>
</html>
and then in the view override this section and provide contents for it:
#section scripts {
<script type="text/javascript">
alert('hello');
</script>
}
<div>Hello from the index view</div>
And since the section is optional (second argument = false) if a view doesn't provide any contents for it, it will stay empty.

Resources