Bind drop down list inside cshtm with server side data - asp.net-mvc-4

I have users list and want to bind that on top navigation bar, this will always visible for many pages, how i can bind it, i don't want to add code on each file, is there any method in mvc4 that is called for each view?
My view:
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
Name Three<b class="caret"></b>
<ul class="dropdown-menu">
//Here i want to show data dynamically, data can be in collection.
<li>Name one</li>
<li>Name two</li>
<li>Name Three</li>
<li>Four</li>
</ul>
</li>
</ul>
</div>
Controller:
ICollection<Names> names = this.obj.GetNames();

In situations like this I prefer to use a code behind call to the view bag. try something like this
#Html.DropDownList("Action", PathToController.GetUsers())
then on the controller where you want to put this method
public static List<SelectListItem> GetUsers(){
List<SelectListItem> ls = new List<SelectListItem>();
var result = //database call here
foreach(var temp in result){
ls.Add(new SelectListItem() { Text = temp.Name, Value = temp.ID });
}
return ls;
}

Related

Is there a function in Laravel Livewire that allows the value property of a html element to be passed into a function?

Is there a function in Laravel Livewire that allows the value property of a html element (be it a radio button, checkbox, dropdown list or textbox) to be passed into a function?
For example: I have on a page a list. This list consists of different cooked dishes. I select a dish from the list by clicking on it and the value passed. Can this value be passed into a function?
LiveWire Controller
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Dishes extends Component
{
public function showRecipe($value)
{
//query database or some conditional logic
}
public function render()
{
return view('livewire.dishes')
}
}
LiveWire Component
<div>
<ul>
<li value="pizza" wire:click="showRecipe(this.value)">Pizza</li>
<li value="cherry_pie" wire:click="showRecipe(this.value)">Cherry Pie</li>
<li value="beef_stronganoff" wire:click="showRecipe(this.value)">Beef Stroganoff</li>
<li value="caesar_salad" wire:click="showRecipe(this.value)">Caesar Salad</li>
<li value="lobster_newburg" wire:click="showRecipe(this.value)">Lobster Newburg</li>
</ul>
</div>
value is not a valid attribute on an <li> tag. However, you can put an anchor-tag with a "prevent default" action it, or just keep the wire:click on the li and pass the data directly to the method.
<div>
<ul>
<li wire:click="showRecipe('pizza')">Pizza</li>
<li wire:click="showRecipe('cherry_pie')">Cherry Pie</li>
<li wire:click="showRecipe('beef_stronganoff')">Beef Stroganoff</li>
<li wire:click="showRecipe('caesar_salad')">Caesar Salad</li>
<li wire:click="showRecipe('lobster_newburg')">Lobster Newburg</li>
</ul>
</div>
If you generate this in a loop with PHP/blade, you should use wire:key on it. The key should be something unique, so Livewire can keep track of each individual record.
<div>
<ul>
#foreach([
'pizza' => 'Pizza',
'cherry_pie' => 'Cherry Pie',
'beef_stronganoff' => 'Beef Stroganoff',
'caesar_salad' => 'Caesar Salad',
'lobster_newburg' => 'Lobster Newburg',
] as $value=>$name)
<li wire:key="dish-{{ $loop->index }}" wire:click="showRecipe('{{ $value }}')">{{ $name }}</li>
#endforeach
</ul>
</div>

How to keep the tab active? ASP.NET Core Razor Pages

Hi there,
I have a problem with my tabs in navbar.
The result I wish:
See the "Home" tab class active by default
Clicking on another tab must to remove active class from the <a> that is already active (at the starting point it is "Home" tab)
Add the same class active to the tab I click on (which also mean that app redirects me)
Keep the clicked tab active
What I've got so far:
I see the "Home" tab set active by default
Clicking on any tab removes class active as I mentioned above and adds the same class to the clicked tab
Redirection happens and "Home" tab returns its default state (becomes active again)
I share my code below:
HTML
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse" id="navigation">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link active" id="home" asp-area="" asp-page="/home/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" id="declarations" asp-area="" asp-page="/declarations/Index">Declarations</a>
</li>
<li class="nav-item">
<a class="nav-link" id="topics" asp-area="" asp-page="/topics/Index">List of Topics</a>
</li>
<li class="nav-item">
<a class="nav-link" id="contacts" asp-area="" asp-page="/contacts/Index">Contacts</a>
</li>
<li class="nav-item">
<a class="nav-link" id="faq" asp-area="" asp-page="/faq/Index">FAQ</a>
</li>
</ul>
</div>
jQuery
$("#navigation .navbar-nav a").click(function() {
$("#navigation .navbar-nav").find("a.active").removeClass("active");
$(this).addClass("active");
localStorage.className = "active";
});
$(document).ready(function() {
stayActive();
});
function stayActive() {
$(this).children().addClass(localStorage.className);
}
Since you are using Razor page, everytime user clicks on a tab, the page will be rendered again on server and then sent back. Therefore I suggest that we set the active class on serverside based on the current route.
Add a new HtmlHelper class
public static class HtmlHelperExtensions
{
public static string ActiveClass(this IHtmlHelper htmlHelper, string route)
{
var routeData = htmlHelper.ViewContext.RouteData;
var pageRoute = routeData.Values["page"].ToString();
return route == pageRoute ? "active" : "";
}
}
Go to your _ViewImports.cshtml and add this import.
Without this, it will not recognize the helper we're about to add in step 3.
#using <Namespace of the class you wrote in step 1, if not already here>
Then your cshtml will be
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse" id="navigation">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link #Html.ActiveClass("/home/Index")" id="home" asp-area="" asp-page="/home/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link #Html.ActiveClass("/declarations/Index")" id="declarations" asp-area="" asp-page="/declarations/Index">Declarations</a>
</li>
...Same for 3 other tabs, make sure that the route you pass in ActiveClass method
...must be the same as the route in asp-page
...If you're afraid of duplication, make some static class to store these routes as constants
</ul>
</div>
In addition to #Nam Le answer I suggest complete solution.
I've found the way how can we use the exception properly.
First of all, as we set active class on serverside based on the current route, we have to add asp-route-routeId="{routeId:int}" in the cshtml we work with.
Secondly, use this jQuery code:
jQuery
$("#navigation .navbar-nav a").click(function() {
$("#navigation .navbar-nav").find("a.active").removeClass("active");
$(this).addClass("active");
localStorage.className = "active";
});
$(document).ready(function() {
stayActive();
});
function stayActive() {
$(this).addClass(localStorage.className);
}
And the last step is to setup "launchUrl": "route/routeId" in the launchSetting.json file to run the application with certain route. This action make our HtmlHelper extension react and add active status to the tab we want.
Hope that here is no any gross mistakes in the solution I suggest :)
UPD: don't forget to add route in cshtml #page "/route/routeId"

Umbraco: How to check if a member is allowed to access a page programmatically

I'm setting up a Umbraco 8 site for creating a prototype.
As I'm playing around with the default code of the Starter Kit, I wanted to change the behaviour of the top navigation.
Currently you can only hide pages for all visitors, but I want to only hide pages based on the members (group) permissions.
I see, that you can check, if a member is in a role with Role.IsUserInRole, but I cannot see a way to get the allowed roles for a page.
Do I need to get the roles and loop through them?
If yes, how do I get them?
If no, what is the right way to do this?
I got it working this way:
IContent content = base.Services.ContentService.GetById(item.Id);
PublicAccessEntry entry = base.Services.PublicAccessService.GetEntryForContent(content);
if (entry != null)
{
foreach (var r in entry.Rules)
{
if (Roles.IsUserInRole(r.RuleValue))
{
<a class="nav-link #(item.IsAncestorOrSelf(Model) ? "nav-link--active" : null)" href="#item.Url">#item.Name</a>
}
}
}
else
{
<a class="nav-link #(item.IsAncestorOrSelf(Model) ? "nav-link--active" : null)" href="#item.Url">#item.Name</a>
}
Maybe this needs some more work, as I guess the performance is not that good.
I don't know there is a built-in dependency between Roles and Pages so you get roles for a page but consider setting certain roles that you need i.e Pro, Free, Monthly Membership...
For each role you may show / hide specific content, and to get all roles in your database use GetAllRoles method.
Then loop through the roles and check if the logged in user is a member or not to give him right access.
After your second comment I went through an Umbraco V8 demo in which I applied the following which I suggest for you:
Create groups A & B
Create members A & B
Create Login and Logout form
Create 3 templates Master, Login & Page
Create 3 document types Master, Login & Page
Create one parent Content i.e Home
Create three childs Contents i.e Login, A & B
Show navigation menu item A for members of group A
Show navigation menu item B for members of group B
Deny access to page A for unregistered members
Deny access to page B for unregistered members
Preview:
Code used in point 8 & 9:
#{
var isMemberofB = false;
var isMemberofA = false;
}
#{
var myUser = System.Web.Security.Membership.GetUser();
if (myUser != null)
{
<p class="ui red sub header">
<i class="user icon"></i>
you're logged in as #myUser.UserName
#{
isMemberofB = System.Web.Security.Roles.IsUserInRole(myUser.UserName, "B");
if (isMemberofB)
{
<p class="ui green sub header">
<i class="user icon"></i>
you're a member of role B
</p>
}
else
{
isMemberofA = System.Web.Security.Roles.IsUserInRole(myUser.UserName, "A");
if (isMemberofA)
{
<p class="ui green sub header">
<i class="user icon"></i>
you're a member of role A
</p>
}
}
}
#*This example shows how to use lazy loaded images, a sticky menu, and a simple text container*#
</p>
}
}
<a href="#" class="ui right floated dropdown item">
Dropdown <i class="dropdown icon"></i>
<div class="menu">
#if (isMemberofA)
{
<div class="item">Link To Page A</div>
}
#if (isMemberofB)
{
<div class="item">Link To Page B</div>
}
<div class="divider"></div>
<div class="header">Header Item</div>
<div class="item">
<i class="dropdown icon"></i>
Sub Menu
<div class="menu">
<div class="item">Link Item</div>
<div class="item">Link Item</div>
</div>
</div>
<div class="item">Link Item</div>
</div>
</a>

Dynamic menu from database

I have a Login page where on login it takes user to Home Page where dynamic menu is loaded.The problem is that when a user clicks on one of the menulink the loaded menu is not visible
This is because I have written the code inside Index action of theHome controller.
So my question is where should I write the logic for dynamic menu so that it is accessible on clicking the menulink.
_Layout.cshtml file where menu is loaded
#model SMS.Models.ViewModel.DashboardVM
#if (Model != null && Model.MenuParentList.Count > 0)
{
<!-- Sidebar Menu -->
<ul class="sidebar-menu">
<li class="header">MAIN NAVIGATION</li>
<li class="active">
<a href="#">
<i class="fa fa-dashboard"></i> <span>Dashboard</span>
</a>
</li>
#foreach (var parentItem in Model.MenuParentList)
{
<li class="treeview">
<a href="#">
<i class="fa fa-th"></i>
<span>#parentItem.MenuParentName</span>
<i class="fa fa-angle-left pull-right"></i>
</a>
<ul class="treeview-menu">
#Html.Partial("_MenuParent", Model.MenuList.Where(x => x.ParentID == parentItem.MenuParentID))
</ul>
</li>
}
</ul>
}
Logic for dynamic menu goes here
public ActionResult Index()
{
var _dashboardVM = new DashboardVM
{
User = _employee.Users.FirstOrDefault(),
MenuParentList=_db.Menus
.Where(x => _parentList.Contains(x.Id))
.Select(x => new SMS.Models.ViewModel.DashboardVM.MenuParent
{
MenuParentID = x.Id,
MenuParentName = x.MenuName
})
.OrderBy(x=>x.MenuParentID)
.ToList(),
MenuList=_employee.Designation.Role.MenuRoles
.Select(x=>x.Menu)
.ToList()
};
}
Create a separate [ChildActionOnly] method that generates your menu and call it from the layout page so its available in all pages
[ChildActionOnly]
public ActionResult Menu()
{
var model = new DashboardVM
{
....
}
return PartialView("_Menu", model);
}
and create a _Menu.cshtml partial view to generate the html
#model DashboardVM
....
and then in your layout, remove #model SMS.Models.ViewModel.DashboardVM (a layout should not have a model unless that model is a base class for all models used by the layout) and then include
#Html.Action("Menu", yourControllerName)
which will call the Menu method and insert the partial view it returns into the layout.

index of matching items in parent element even if they're in other child containers

I need to get the index of the li.play relevant to the ul.showreel_thumbnails. Is this even possible? All i seem to get is the li index inside ul.row
<ul class="showreel_thumbnails">
<li>
<ul class="row">
<li class="play_video">item</li>
<li class="play_video">item</li>
<li class="play_video">item</li>
</ul>
</li>
<li>
<ul class="row">
<li class="play_video">item 4</li>
<li class="play_video">item</li>
</ul>
</li>
</ul>
so if item 4 is clicked it should give me the index of 4 etc...
best, Dan.
It may not be valid HTML but here's how it would work (with JQuery):
function FindMyCount()
{
var item_count = 0;
$("#showreel_thumbnails li").each(function() {
++item_count;
if($(this).hasClass("igotclicked"))
return false;
});
return item_count;
}
$("#showreel_thumbnails li").click(function() {
$(this).addClass("igotclicked");
var myCount = FindMyCount(); // 1 - the # of li's under the showreel piece
$(this).removeClass("igotclicked");
// Do what you want here.
});