thymeleaf expression in title tag doesn't get evaluated - title

I'm trying to have the title of my web page change based on whether the domain model is NEW or existing. The expression works everywhere else on the page but not in the <title></title>
Here's what I have:
<title th:text="${myobject['new']} ? 'Creating New' : 'Updating'">[Template Title]</title>
I have the same expression (copy and paste) in the page which renders fine:
<span th:text="${myobject['new']} ? 'Creating New' : 'Updating'">[Template Title]</span>
But it just doesn't work when in the title tag
I've also tried using th:if th:unless:
<title th:if="${myobject['new']}">Creating New</title>
<title th:unless="${myobject['new']}">Updating</title>
which I am also using later on in the page for showing different submit buttons. I just cant figure out why the title tag is behaving differently.
Also, I'm using ultraq layout which is part of the cause. The expression evaluates on a template that uses no layout template.

In my opinion you don't have comparison before ? sign. I managed to change title using this code:
controller:
#RequestMapping({"/site"})
public String showSite(final ModelMap modelMap) {
modelMap.addAttribute("parameter", null);
return "site";
}
html:
<title th:text="${parameter != null} ? 'Parameter is null' : 'Its NOT null!'">this will be replaced anyway...</title>
So maybe try to compare myobject['new'] to something (for ex. null).
HTH

Related

Razor template/component solution that supports child Razor markup

Is there a template/component solution in ASP.NET Core Razor, that supports inner Razor markup?
Here's a use case:
1. Say I have some repetitive markup for example "a div with nice borders, shadows and two buttons at the bottom"
2. Obviously this markup has a common "header" and a "footer" in the HTML code
3. I need to pass arbitrary Razor markup to insert between header and footer. Not just a model object - but some actual markup that will be rendered between header and footer. I can't use foreach because this markup is different every time - it can be text-content, a form, an image, or some complicated Razor-rendered stuff.
Basically I'm looking for a "Surround this Razor with more Razor" templating solution
Something like:
#{
//this function renders my beautiful box
Func<dynamic, IHtmlContent> myFunction = #<div class="relative flex flex-col rounded-2xl border border-gray-200 bg-white p-8 shadow-sm">
#item
</div>;
}
<!-- and then I call it passing some Razor as input -->
#myFunction(
<ul>
<li>#SomeRazorMethod()</li>
</ul>
);
Something like a Layout - but the one I can use multiple times on the same page.
Is there anything like that? This is a pretty common componentizing tool - "wrap my markup with other markup" - that is present in other templating engines (React, Vue, etc), but apparently not in Razor.
Just to be clear: I'm looking for a Razor-based solution, not a C#-based one. So that my header-footer markup stays in markup files (.cshtml), not in C# files that will have hard-coded HTML magic strings.
Based on your example, this might help.
#functions {
public static IHtmlContent MyBox(dynamic item, Func<dynamic, IHtmlContent> template)
{
var html = new HtmlContentBuilder();
html.AppendHtml("<div class='bestcss'>");
html.AppendHtml(template(item));
html.AppendHtml("</div>");
return html;
}
}
#MyBox(null, #<div class='innercss'>#(10 == 12 ? "MyTest Equals" : "No Equal") hello</div>)
And if you like to pass modeldata, it will be:
#MyBox(customerdata, #<div class='innercss'>#(10 == 12 ? "MyTest Equals" : "No Equal") hello #item.FirstName</div>)
I have used some arbitrary if condition for testing.
You can use Partial Pages or Views which are Razor files containing snippets of HTML and server-side code to be included in any number of pages or layouts.
Just like standard Razor pages, partial pages support the #model
directive specifying the type for the partial's data model. All of the
rendering methods have overloaded versions that take a model to be
consumed in the partial.
#Shah's answer got me one step closer to a solution, however, it seems like the the actual question I'm trying to solve is "can I pass Razor markup as an input parameter".
Turns out you can, you just have to put # in front of it:
#{
void MyFunc(Func<object, IHtmlContent> template)
{
<div>#template(null)</div>
}
}
#{ MyFunc(#<div>The ID is: #Model.Id</div>); }
<!-- mind the '#' before the 'div' -->

ASP.net navbar with bootstrap

Good evening every one .
i would like to add an image near a navbar , but i'm not able to imitate the code propose by bootstrap , because ASP.net use helpers of razor while in bootstrap web site there use diretly an html code.
please how could i adapt this in ASP.net
You should try following code instead of the HTML of bootstrap,
where imagepath is your image path.
Razor Syntax Rules for C#:
Razor code blocks are enclosed in #{ ... }
Inline expressions (variables and functions) start with #
C# code is case sensitive
Variables are declared with the var keyword
Code statements end with semicolon
Strings are enclosed with quotation marks
C# files have the extension .cshtml
#model YourProject.Models.ImageModel
#{
imagePath= "xyz/xyz.jpg"
}
#if(imagePath != ""){
<img src="#imagePath" alt="Image Name" width="200px" />
}
If you take image path from model then you try following code:
#model YourProject.Models.ImageModel
#if(Model.Photo != null && Model.Photo != ""){
<img src="#Url.Content(#Model.Photo)" alt="#Model.AlternateText" />
}
If you don't understand then please refer following link:
https://learn.microsoft.com/en-us/aspnet/web-pages/overview/ui-layouts-and-themes/9-working-with-images

Show hide html attribute based on model var in Razor - "#" must be followed by a valid code block

I am using razor to show/hide page content based on variables in the model:
#if (Model.TicketShown == null)
{
#:<div id="ticket-section">
} else {
#:<div id="ticket-section" style="display:none">
}
//More Code
#:</div>
I have been using it for a while, but today I am getting the error '"#" must be followed by a valid code block' just on the closing tag. I am using the syntax elsewhere and it works fine.
Why and is there a more elegant way of doing this? Thanks
#: is meant to be used inside code blocks (see Explicit line transition), your #:</div> might not be inside one. You could use Html.Raw as alternative (e.g. #Html.Raw("</div>")).
With the help of the ?: operator, you could also rewrite the if as follows:
<div id="ticket-section" style=#(Model.TicketShown == null ? "" : "display:none")>
...
</div>

How do I allow my ASP.NET Core tag helpers to be self-closing

I have written a tag helper that I can use as follows...
<mytaghelper attr1="jim"></mytaghelper>
I would like to be able to shorten this to just...
<mytaghelper attr1="jim">
...or at least...
<mytaghelper attr1="jim"/>
However, I can't get this to work. Here is some sample code for the Process method...
public override void Process(TagHelperContext context, TagHelperOutput output) {
output.TagName = "div";
output.PreContent.SetHtmlContent("<div>");
output.Content.SetHtmlContent("OUTPUT HTML GOES HERE");
output.PostContent.SetHtmlContent("</div>");
output.Attributes.Clear();
}
I have tried adding a TagStructure setting to the HtmlTargetElement attribute on the class...
[HtmlTargetElement("mytaghelper", TagStructure = TagStructure.WithoutEndTag)]
...but it doesn't seem to make any difference. <mytaghelper attr1="jim"/> generates <div /> and <mytaghelper attr1="jim"></mytaghelper> generates <div></mytaghelper>.
If I set the TagStructure to NormalOrSelfClosing then included a closing tag works, but <mytaghelper attr1="jim"/> gives an empty <div />
Anyone able to explain what I need to do?
TagStructure.WithoutEndTag is able to write the tag with only a start tag or self-closing, but the output would be <div > or <div/> . Self-closing anchor tags are not valid HTML, so you wouldn't want to create one, but you might want to create a tag helper that's self-closing. Tag helpers set the type of the TagMode property after reading a tag. Add the below code line Inside the process method:
output.TagMode = TagMode.StartTagAndEndTag;
Take a moment to read Author Tag Helpers in ASP.NET Core which covers this perfectly .
The correct syntax is:
[HtmlTargetElement("mytaghelper", TagStructure = TagStructure.WithoutEndTag)]
Which should be applied to the taghelper class, not the Process method. You may already be doing that, but it wasn't clear in your question. I believe you still must use the self-closing tag syntax (/>) for it work, though.

Passing a GET parameter to ActionLink in ASP.NET

Sorry but I am new to C# and ASP.NET and I saw alot of posts about this problem but I quite didn't get it. I am trying to understand how to pass a GET parameter to an action thru HTML.ActionLink:
here is the the URL:
http://localhost:36896/Movies/SearchIndex?searchString=the
and my CSHTML page should look like this:
<input type="Text" id="searchString" name="searchString" />
#Html.ActionLink("Search Existing", "SearchIndex", new { searchString = "the"})
this hard coded parameter "the" is actually working, but how can I select the input element with id=searchString, with something like document.getElementById("searchString").value
Thanks,
If the value you want to send as GET parameter is not known on the server you cannot use the Html.ActionLink helper to add it. You need to use javascript to manipulate the existing link and append the parameter.
It looks like you have an input field that contains a search string and you want to send the value entered in this field to the server. A better way to handle this scenario is to use an HTML form with method="GET" instead of an ActionLink. This way you don't need to use any javascript - it's part of the HTML specification:
#using (Html.BeginForm("SearchIndex", "Movies", FormMethod.Get))
{
#Html.EditorFor(x => x.SearchString)
<button type="submit">Search</button>
}
Now when you click on the Search button the value entered in the SearchString field will automatically be sent to the SearchIndex action:
http://localhost:36896/Movies/SearchIndex?searchString=the
But if you absolutely insist on using an ActionLink you will have to write javascript to manipulate the href of the existing link when this link is clicked in order to append the value to the url. It's an approach I wouldn't recommend though because the HTML specification already provides you this functionality throughout HTML forms.
This makes the #Html.EditorFor refer to the Title field of the object, kinda in a random way but it works!
#using (Html.BeginForm ("SearchIndex", "Movies", FormMethod.Get))
{
#Html.EditorFor( x => x.ElementAt(0).Title)
<button type="submit">Search</button>
}
Still couldn't pass input parameter to the URL in the GET.
EDIT:
FINAL SOLUTION:
#Html.TextBox("SearchString")
<button type="submit">Filter</button>
and on the controller side, switch the input parameter. Basically it will automatically recognize the passed parameter.
public ActionResult SearchIndex(string searchString)
{
...
}