Setting html id on a sub menu's <ul> with Telerik MVC Menu Control - telerik-mvc

Using the Telerik Asp.net MVC menu control, I'm trying to get an id on the ul's in sub menus. I've tried putting the HtmlAttributes(new { #id="myId" }) call in a few places but can't seem to figure out where to put it to get the id on the .
In the code snippet below, I've shown the two places I've tried calling the HtmlAttributes method. The comment after the call explains where the Telerik control is actually putting the id.
#(Html.Telerik().Menu()
.Name("mainMenu")
.Items(menu =>
{
menu.Add()
.Text("Tools")
.Items(item =>
{
item.Add().Text("Add To Toolbox").HtmlAttributes(new {#id="toolsMenu"}); #* this puts the id on the "Add To Toolbox" <li>*#
item.Add().Text("Toolbox");
}).HtmlAttributes(new {#id="toolsMenu"}); #* this puts the id on the "Tools" <li>*#
menu.Add()
.Text("Setup")
.Items(item =>
{
item.Add().Text("Print Header");
item.Add().Text("MenuLabelAccountInformation");
});
}).OpenOnClick(true))
Is there a way to get an ID on the <ul> with this control?

You can't set the id attribute of the UL from server side code. You could use jQuery to do that by hooking up the menu's OnLoad client-side event:
<script type="text/javascript">
function onLoad() {
var id = 0;
$(this).find("ul").each( function() {
this.id = "ul_" + id;
id ++;
});
}
</script>

Related

Filter card list with Razor View

Im trying to make a filter like in AngularJS when u use:
ng-repeat="u in users | filter:searchBar">
And your input filter looks like
<input type="text" id="searchBar" placeholder="start typing" ng-model="searchBar">
But the things its that im working on MVC with Razor View and I do not know how to approach this filter.
The list of cards is made with a foreachlike this:
#foreach{ var item in Models){
<div class="card">
<div class="card-container">
some content
</div>
</div>
}
Any ideas?
You can do the filtering with ajax. Here is a server side filtering solution.
First, you should move the code which renders the result to a partial view. Let's say you created a partial view called CustomerList.cshtml. Move the list code to that.
#model IEnumerable<Customer>
#foreach (var item in Model)
{
<div class="card">
<div class="card-container">
#item.Name
</div>
</div>
}
Now in your main view, you can call this partial view and pass the data to it. Wrap the call to the partial view in a container div. Add a input element for user to enter the search key. Assuming your main view is also strongly typed to IEnumerable<Customer>
#model IEnumerable<Customer>
<input type="text" id="search" data-url="#Url.Action("Index")" />
<div id="div-items">
#Html.Partial("CustomerList",Model)
</div>
Now we need to have some javascript code which listen to the keyup event on the search input, read the value of it and make an ajax call to the server where it uses the search key and get the filtered set of data, pass that to the same partial view and return the partial view result.
You can use jQuery $.get method
$(document).ready(function () {
$("#search").keyup(function() {
var v = $(this).val();
$.get($(this).data("url"), { searchKey: v }).done(function(res) {
$("#div-items").html(res);
});
});
});
Now make sure your server action method returns the filtered data like this
public ActionResult Index(string serchKey="")
{
var items = db.Customers.AsQueryable();
if (!String.IsNullOrEmpty(searchKey))
{
items = items.Where(a => a.Name.StartsWith(searchKey));
}
var t = items.ToList();
if (Request.IsAjaxRequest())
{
return PartialView("CustomerList",t );
}
return View(t);
}
Another option is to do client side filtering. on the items. But if i am going that direction, i would choose a client side MVC framework like angular to do that for me

AngularJS addClass isn't working

I have been trying to addClass through AngularJS and the code doesn't seem to work, weird thing is addClass is working on Parent Menu Item but doesn't work on Sub item.
I have a nested UL and LI, when I click on the Parent LI ParentLi function gets called and it adds a "focused" class to the Clicked LI, this works fine but when I click on Nested LI's I call childLi and I do the same operation as done for the Parent but class doesn't get added. I am new to Angular and I hope I am doing this in the right way.
$scope.parentLi = function(event) {
var liElement = angular.element(event.target.parentNode);
var allParentLiElements = document.getElementsByClassName('parent-dropdown');
if (!liElement.hasClass('focused')) {
angular.element(allParentLiElements).removeClass('focused');
liElement.addClass('focused');
} else
liElement.removeClass('focused');
};
$scope.childLi = function(event){
var liElement = angular.element(event.target.parentNode);
var allParentLiElements = document.getElementsByClassName('child-dropdown');
if(!liElement.hasClass('focused')){
angular.element(allParentLiElements).removeClass('focused');
$(event.target).closest('.parent-dropdown').addClass('focused');
liElement.addClass('focused');
} else
liElement.removeClass('focused');
}
Note that i have edited my jsfiddle code based on the answer given by Jiam30.
adding focused class should work like active class i.e the menu that i just clicked should have focused class other should not, same way if i have hover on menu item and click on subitem, both the subitem and the parent item should have focused class.
Fiddle
Manipulating elements in a controller should be avoided.
Use ng-class instead (also use ng-repeat to avoid HTML repetition). For instance:
<li class="dropdown parent-dropdown" ng-click="parentLi()" ng-class="{'focused': isDropdownFocused}"></li>
With this function in the controller:
$scope.parentLi = function() {
$scope.isDropdownFocused = !$scope.isDropdownFocused;
};
Updated Fiddle: http://jsfiddle.net/6be56/127/

Could we add our menu items in Gitkit Starter kit "Sign In cum User Info " ( #navbar )?

Could we add our menu items in Starter kit Gitkit NavBar ?
There are two list items in the drop down : Manage Account and Sign Out.
Is it possible to add a third option with a URL link ( say like Update Profile ) ?
The html for the #navbar gets loaded through Javascript code of Gitkit.
I use GAE Python.
Possible solutions which I could think of are :
After my webpage loads completely, I could add my own <li> items to the list of dropdown menu provided by #navbar.
Or
Write a custom "Sign In cum User Info " ( #navbar ) widget.
Is there a better and simpler approach ?
MY REQUEST TO GITKIT TEAM FOR ENHANCEMENT
It would be great if we could provide our custom menu items along with their URL links as options to below JS code which loads #navbar :
<script type=text/javascript>
window.google.identitytoolkit.signInButton(
'#navbar', // accepts any CSS selector
{
widgetUrl: "http://www.mywebsite.com/oauth2callback",
signOutUrl: "/",
// Example of possible solution ( my suggestion ):
custom_menu_item__1__name : "item_1", // My Custom Menu Item 1
custom_menu_item__1__link : "http://site/link_url_1",
::
custom_menu_item__n__name : "item_1", // My Custom Menu Item n
custom_menu_item__n__link : "http://site/link_url_1",
}
);
</script>
UPDATE
Temporary Fix = I have added the needed menu options using jquery temporarily. Code snippet provided below to help anyone with similar needs till official solution arrives :
On page load,
custom_menu_add_job_id = setInterval(function(){
add_custom_menu();
}, 5000);
function add_custom_menu(){
if ($("#navbar").find(".gitkit-user-card-menu").length){
$(".gitkit-user-card-menu").append($("<li class='gitkit-user-card-menuitem' id='smh_user_profile' tabindex='0'> <img src='/images/person_32x32.png' class='user_profile_menu_icon' > Profile </li>")
.click(function(){
window.location.href = window.location.protocol + "//" + window.location.host + "/user/";
})
);
clearInterval(custom_menu_add_job_id);
}
}
If you want, you could check it live at ShowMyHall.
Customized menu items are now supported in Google Identity Toolkit javascript widget. Examples:
window.google.identitytoolkit.signInButton(
'#navbar', // accepts any CSS selector
{
widgetUrl: "...",
dropDownMenu: [
{
'label': 'Check Configuration',
'url': '/config'
},
{
'label': 'Sign out',
'handler': function() {google.identitytoolkit.signOut();}
},
{
'label': 'Manage Account',
'handler': function() {google.identitytoolkit.manageAccount();}
},
]
};
Until this feature arrives, I also implemented a similar temporary fix that you outlined at the end of your question. I got around using a timer as follows (note that my gitkit is using the div login):
$(window).load(function() {
$("#login").hover(function() {
add_custom_menu_items();
})
});
function add_custom_menu_items(){
if ($("#login").find(".gitkit-user-card-menu").length == 1){
if ($("#my_data_link").length == 0) {
$(".gitkit-user-card-menu li:eq(0)").after($('<li class="gitkit-user-card-menuitem" id="my_data_link" tabindex="0">My data</li>'));
}
}
}
Basically when you hover over the div it adds the menu item, but only if it hasn't already been added.
The navbar drop down menu does not support images but if you really need that, here's a hacky way to do it in jquery:
var config = {...}; // your config which includes the custom drop down menu.
// Render button on load. (now supported)
window.onload = function() {
window.google.identitytoolkit.signInButton(
'#navbar', // accepts any CSS selector
config);
// This will modify the html content of the first option in drop down menu.
// Make menu dom changes.
jQuery('#navbar li:first-child').html('<img src="img.png">My Label');
}

ComboBox Not Dropping Down List of Items

I am using a Kendo ComboBox in my app and defined the markup of the control as follows:
#(Html.Kendo().ComboBox().Name("GroupUserName")
.Placeholder("- Select Group -")
.Suggest(true)
.BindTo(
(Model.Groups ?? new[] { Model.Group })
.Select(i => new { i.GroupName, i.GroupUserName })
)
.DataTextField("GroupName")
.DataValueField("GroupUserName"))
I know that there are 2 records being bound in the BindTo method, and these are being passed to the client component.
jQuery(
function(){
jQuery("#GroupUserName").kendoComboBox({"dataSource":
[{"GroupName":"membershipgroup01","GroupUserName":"membershipgroup01"},
{"GroupName":"publicgroup01","GroupUserName":"publicgroup01"}]
,"dataTextField":"GroupName","dataValueField":"GroupUserName",
"placeholder":"- Select Group -","suggest":true
});
});
However, the combobox, when I hit the drop down, doesn't show anything. There is no drop down to allow me to select a value. See this image:
There is no drop down that appears when you click the drop down selector. Why?
I'm using JQuery 1.8.2, along with the kendo.all and kendo.aspnetmvc scripts...
You are binding to an anonymous type without field names. Kendo doesn't have anything to grab because the objects you told it to bind to don't have fields named GroupName and GroupUserName.
From what it looks like, you shouldn't need to bind to an anonymous type at all. So this:
.BindTo(
(Model.Groups ?? new[] { Model.Group })
.Select(i => new { i.GroupName, i.GroupUserName })
)
Should be:
.BindTo(
(Model.Groups ?? new[] { Model.Group })
)
If for some reason you do need to bind to an anonymous type you can give the fields the appropriate names:
.BindTo(
(Model.Groups ?? new[] { Model.Group })
.Select(i => new { GroupName = i.GroupName, GroupUserName = i.GroupUserName })
)
For me this was a conflict between JQuery UI and Kendo UI. When I removed references to JQuery UI, it worked.

Add class to DIV if checkbox is checked onload

I need help with a script to add an "active" class to a div when a hidden checkbox is checked. This all happening within a somewhat complex form that can be saved and later edited. Here's the process:
I have a series of hidden checkboxes that are checked when a visible DIV is clicked. Thanks to a few people, especially Dimitar Christoff from previous posts here, I have a few simple scripts that handle everything:
A person clicks on a div:
<div class="thumb left prodata" data-id="7"> yadda yadda </div>
An active class is added to the div:
$$('.thumb').addEvent('click', function(){
this.toggleClass('tactive');
});
The corresponding checkbox is checked:
document.getElements("a.add_app").addEvents({
click: function(e) {
if (e.target.get("tag") != 'input') {
var checkbox = document.id("field_select_p" + this.get("data-id"));
checkbox.set("checked", !checkbox.get("checked"));
}
}
});
Now, I need a fourth ( and final ) function to complete the project (using mootools or just plain javascript, no jQuery). When the form is loaded after being saved, I need a way to add the active class back to the corresponding div. Basically reverse the process. I AM trying to figure it out myself, and would love to post an idea but anything I've tried is, well, bad. I thought I'd at least get this question posted while I work on it. Thanks in advance!
window.addEvents({
load: function(){
if (checkbox.checked){
document.getElements('.thumb').fireEvent('click');
}
}
});
Example: http://jsfiddle.net/vCH9n/
Okay, in case anyone is interested, here is the final solution. What this does is: Create a click event for a DIV class to toggle an active class onclick, and also correlates each DIV to a checkbox using a data-id="X" that = the checkbox ID. Finally, if the form is reloaded ( in this case the form can be saved and edited later ) the final piece of javascript then sees what checkboxes are checked on page load and triggers the active class for the DIV.
To see it all in action, check it out here: https://www.worklabs.ca/2/add-new/add-new?itemetype=website ( script is currently working on the third tab, CHOOSE STYLE ). You won't be able to save/edit it unless you're a member however, but it works:) You can unhide the checkboxes using firebug and toggle the checkboxes yourself to see.
window.addEvent('domready', function() {
// apply the psuedo event to some elements
$$('.thumb').addEvent('click', function() {
this.toggleClass('tactive');
});
$$('.cbox').addEvent('click', function() {
var checkboxes= $$('.cbox');
for(i=1; i<=checkboxes.length; i++){
if(checkboxes[i-1].checked){
if($('c_'+checkboxes[i-1].id))
$('c_'+checkboxes[i-1].id).set("class", "thumb tactive");
}
else{
if($('c_'+checkboxes[i-1].id))
$('c_'+checkboxes[i-1].id).set("class", "thumb");
}
}
});
// Add the active class to the corresponding div when a checkbox is checked onLoad... basic idea:
var checkboxes= $$('.cbox');
for(i=1; i<=checkboxes.length; i++){
if(checkboxes[i-1].checked){
$('c_field_tmp_'+i).set("class", "thumb tactive");
}
}
document.getElements("div.thumb").addEvents({
click: function(e) {
if (e.target.get("tag") != 'input') {
var checkbox = document.id("field_tmp_" + this.get("data-id"));
checkbox.set("checked", !checkbox.get("checked"));
}
}
});
});

Resources