Inline if statement that Intellij understands - scala

I'm trying to create some sort of class="active" functionality using Twirl and Play 2.3 but I can't find a solution that works, is short and doesn't throw my Intellij syntax all over the place.
This is what I currently have:
<ul class="nav navbar-nav">
<li #(if (request.uri == "/") Html("""class="active""""))>Home</li>
<li #(if (request.uri == "/about") Html("""class="active""""))>About</li>
<li #(if (request.uri == "/features") Html("""class="active""""))>Features</li>
</ul>
And this is what Intellij thinks of it:

Yeah, IntelliJ sometimes is confused with view's syntax, anyway you can create i.e. custom util for adding (or not) the active class (Java sample)
package utils;
import play.api.templates.Html;
import play.mvc.Http;
public class AttrHelpers {
public static Html setActiveClass(String requiredPath, Http.Request request) {
return (requiredPath.equals(request.uri())) ? Html.apply("class=\"active\"") : null;
}
}
So then you can use it in your views like:
<li #utils.AttrHelpers.setActiveClass("/about", request) >
About
</li>
<li #utils.AttrHelpers.setActiveClass("/features", request) >
Features
</li>

Related

ASP.NET Core MVC customizing site variables

I have an ASP.NET Core MVC (with EF) site and I want administrators to modify some variables via admin panel. For example contact e-mail, counter section visibility, navigation menu visibility etc.
And most of the parameters are in _Layout.cshtml.
May I learn the best practice how to manage this issue.
For example: I have a one row table that named GeneralSettings and it has some columns (IsLoginEnable, IsPrivacyVisible etc.) and want to read these columns in _Layout.cshtml
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
#if (true) //for example I want to write here "if (Model.ToList()[0].IsLoginEnable)" instead of this
{
<partial name="_LoginPartial" />
}
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
#if (true) //if (Model.ToList()[0].IsPrivacyVisible)
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
}
</ul>
I've added comments near the if conditions that I actually want to do.
Updated Answer
Seed your GeneralSettings on the application first start.
The admins can modify it from the UI using a regular form.
When needed, get it from the server's memory via the IMemoryCache service. If it's not present in the memory fetch it from the database and cache it.
When a modification in the GeneralSettings occures, purge it from memory using the IMemoryCache service.
The below code is just an example and may need to be modified to work in your application.
Turn your GeneralSettings into a service:
public Interface IGeneralSettingsService
{
Task<GeneralSettings> GetSettingsAsync();
}
public class GeneralSettingsRepo : IGeneralSettingsService
{
//Inject Context...
//Inject IMemoryCache...
public async Task<GeneralSettings> GetSettingsAsync()
{
if (!memoryCache.TryGetValue("GeneralSettings", out GeneralSettings GS))
{
GS = await context.GeneralSettings.AsNoTracking().FirstOrDefaultAsync();
_ = memoryCache.Set<GeneralSettings>("GeneralSettings", GS, new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(cachehours),
SlidingExpiration = TimeSpan.FromHours(cachehours)
});
}
return GS;
}
}
In your admin controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UpdateGlobalSettings(SettingsVm vm)
{
//Update properties...
memoryCache.Remove("GeneralSettings"); //Purge old settings from cache
}
And finally in your Layout.cshtml inject the settings service:
#inject IGeneralSettingsService GeneralSettingsService
#{
var settings = await GeneralSettingsService.GetSettingsAsync();
}
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
#if (settings.IsLoginEnabled)
{
<partial name="_LoginPartial" />
}
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
#if (settings.IsPrivacyVisible)
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
}
</ul>
Don't forget to register the service in ConfigureServices.

jstree - node path has unexpected space characters

I need to get node path of jstree element ,I using this code :
$(function () {
$('#jstree').jstree();
$('#jstree')
// listen for event
.on('changed.jstree', function (e, data) {
if (data.action == "select_node") {
var node_path = data.instance.get_path(data.node, "/");
console.log(node_path)
}
});
});
But I get unexpected space character (You can see in console.log() function)
http://jsfiddle.net/3q9Ma/741/
I need a pretty path like this : Folder1/children 1
Please tell me what wrong .
Thank you
The problem actually with the HTML in your fiddle. It looks like this:
<div id="jstree">
<ul>
<li>Folder 1
<ul>
<li id="child_1">Child 1</li>
<li>Child 2</li>
</ul>
</li>
<li>Folder 2</li>
</ul>
</div>
The get_path function is doing exactly what it is supposed to - taking the text from the parent <li> followed by the text from the child <li>. What is happening is that the text from the parent Folder 1 is actually 'Folder/n ', which is causing your problem. I see why you have your HTML structured the way you do, since the example on jstree tells you to do it this way. A way around it would be to remove the line break after your Folder 1. It looks terrible, but it will make your get_path function work:
<div id="jstree">
<ul>
<li>Folder 1<ul>
<li id="child_1">Child 1</li>
<li>Child 2</li>
</ul>
<li>Folder 2</li>
</ul>
</div>

executing java/scala code in scala.html templates

Can I execute that line of code
nav = request().path().toString()
inside of scala template like index.scala.html
I would like to have that code to check on witch side is user and to mark it on menu
using code like this in main.scala.html:
<li class="#("active".when(nav == "contact"))">
Contacts
</li>
I would recommend you different approach, create tag - resuable template, which takes Integer as an argument,
it will render menu and mark as an active different menuitem depends on value.
#(menuItem: Int)
<ul >
<li #if(menuItem==1){ class="active" } >
////
</li>
<li #if(menuItem==2){ class="active" }>
</li>
<li #if(menuItem==3){ class="active" }>
///
</li>
</ul>
from your contact page and any other page, call this tag with corresponding value, #views.html.tags.menu(1)
You can define variables like that if that is your question. If it is not your question than please try to explain your problem in more detail.
#nav = { #request().path().toString() }

How to increment a variable in template without loop -- Play 2.1.1, Java

I would like to generate ID's for an HTML list.
The list is generated dynamically from the database.
I cant use a for loop or the list.zipWithIndex function because my logic contains a few loops for the generation of the list already, in which the counter needs to be incremented too. I also tried it with the defining function, but its not allowed to reasign values like this: #{id = id + 1}
Whats the best way to accomplish the generation of Id's?
Thats part of the template (uniqueId needs to be replaced with an integer):
<div id="tree">
<ul>
<li id="uniqueId">
<a class="dashboard" href="/">Dashboard</a>
</li>
<li id="uniqueId">
<b>Products</b>
<ul id="uniqueId">
#for(cat <- Application.allCategories()) {
<li id="uniqueId">
<a class="name" href="#routes.Categories.getd(cat.id).url">#cat.name</a>
<ul>
#for(prod <- Application.allProducts()) {
<li id="uniqueId">
<a class="name" href="#routes.Product.getById(prod.id).url">#prod.name</a>
</li>
#*more code and the closing tags...*#
Use just ... object's id prefixed to make it unique, example for first listing:
#for(cat <- Application.allCategories()) {
<li id="cat_#cat.id">
for second:
#for(prod <- Application.allProducts()) {
<li id="prod_#prod.id">
or if the same product can be displayed in several categories prefix it with cat.id as well:
#for(cat <- Application.allCategories()) {
<li id="cat_#cat.id">
#for(prod <- Application.allProducts()) {
<li id="prod_#(cat.id)_#(prod.id)">

HTML attribute in Scala Template

I am a Java developer who recently started to learn about the Play Framework. I have been trying to get the below template working but cant seem to get it. I have got the following in my Scala template
#navItem(label: String, link1: String) = {
#{if (Application.isAuthenticated()) {
<li class="active">
label
</li>
}
else {
<li class="disabled">
{label}
</li>
}
}
}
I am calling this later in my template like so
<ul class="nav">
#navItem("Search Documents", "/search")
</ul>
The generated link has href as localhost:9000/#link1 instead of localhost:9000/search. I am not sure whats going on.
PS: If I change my template as below it works fine. But I want to understand why the above template wont work.
#navItem(label: String, link1: String) = {
<li class="#(if (Application.isAuthenticated()) "active" else "disabled")">
#label
</li>
}
Not quite sure about this, but my guess would be the following: The #{ ... } indicates the beginning of a dynamic statement and all of its content is treated as Scala code. Thus, it is a normal if-condition with two strings as a result, both of which are simply returned in the template.
Why are you marking it as a multi-line code block anyway? Have you tried it like this? (note the missing curly braces after the 2nd # sign):
#navItem(label: String, link1: String) = {
#if(Application.isAuthenticated()) {
<li class="active">
#label
</li>
} else {
<li class="disabled">
#label
</li>
}
}