Preserve the opened/closed state of my sub-menus when navigate to another page - asp.net-mvc

I have an asp.net mvc4 solution.
I have a menu on the left side. By default this menu is closed.
If I click on an item, a sub-menu is showed.
The problem is when I navigate to another page, the opened/closed state of sub-menus are forgotten. The new page is showed and all sub-menus are still closed. I would like to preserve the opend/closed state of these sub-menus. How can I proceed?
Here is a portion of my left side menu:
<div class="page-sidebar">
<ul>
<li class="dropdown" data-role="dropdown">
<a><i class="icon-flip-2"></i> Transports</a>
<ul class="sub-menu light sidebar-dropdown-menu">
<li>#Html.ActionLink("En cours", "SearchTransportsAA", "Transp")</a></li>
<li>#Html.ActionLink("Passés", "SearchTransportsBB", "Transp")</a></li>
<li>#Html.ActionLink("Factures", "SearchTransportsCC", "Transp")</a></li>
</ul>
</li>
<li class="dropdown" data-role="dropdown">
<a><i class="icon-drawer-2"></i> Autorisations</a>
<ul class="sub-menu light sidebar-dropdown-menu open">
<li>#Html.ActionLink("Valides", "SearchAutorisAA", "Transp")</a></li>
<li>#Html.ActionLink("Périmés", "SearchAutorisBB", "Transp")</a></li>
<li>#Html.ActionLink("Recherche", "SearchAutorisCC", "Transp")</a></li>
</ul>
</li>
...
...
As you can see above, when 'open' is added to the class, the menu is marked to be open.

One way you could do it, is to have your Views that have this side menu inherit from a model that have property that contains the selected sub-menu item
public class ViewWithSideMenu
{
public ViewWithSideMenu(string menuItem)
{
MenuItem = menuItem;
}
public string MenuItem { get;set; }
}
ViewModel:
public class MyViewmModel : ViewWithSideMenu
{
public MyViewmModel() : base("someMenu") {}
}
View:
<ul class="sub-menu light sidebar-dropdown-menu#(Model.MenuItem == "someMenu"? " open" : "")">
this approach will only open a menu based on the page we are on, it doesn't really remember what the user clicked on, if it's very important for you to keep the user selections, you have 2 options,
keep sending them back to the server with every request (not very good, too much overhead)
keep updating the content using ajax requests and not a full reload of the page, in which case you keep the menu unchanged, and convert all your requests to ajax, and replace the content with the ajax response

You can try this, it worked for me :D
<script type="text/javascript">
$(document).ready(function () {
$("a[href='"+ window.location.pathname +"']").parents(".hidden-ul").css("display", "block");
});
</script>

Related

Binding lost (after click) in angular js small example

I have a very small application in Angular JS. It's placed inside a bigger rails application, but I don't see too much interaction. The angular application, allows the user to interact with a group of categories. As easy as:
var angular_app = angular.module('angular_app', []);
angular_app.config(['$httpProvider', function($httpProvider, $cookieStore) {
//Protection
}]);
angular_app.controller('CategoriesController', function ($scope, $http) {
$scope.isEditing = false;
$scope.categoryName = '';
$http.get('/api/categories').success(function(data) {
//We use this to data-bind with the HTML placed below
$scope.categories = data;
});
$scope.addNewCategory = function() {
...
}
$scope.editCategory = function(index) {
if (!index)
return;
var selectedCategory = $scope.categories[index];
// With ng-show, we make visible the part of the UI
// that should be used for editing
$scope.isEditing = true;
}
$scope.cancelEditCategory = function() {
$scope.isEditing = false;
}
$scope.deleteCategory = function(index) {
...
}
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['angular_app']);
});
The idea is that the information is shown in a list, and we have an 'edit' button that allows the user to see other part of the UI that will let him perform changes.
<div ng-controller="CategoriesController">
<div ng-show='isEditing' class="popup_menu">
DIV FOR EDITING
</div>
<ul>
<li ng-repeat="category in categories">
<a href="#" ng-click='deleteCategory($index)'>[X]</a>
<a href="#" ng-click='editCategory($index)'>[E]</a>{{ category.name }}
</li>
</ul>
<input type="text" id="categoryTextBox" ng-model="categoryName"/>
<button id="submit" ng-click='addNewCategory()'>New category</button>
</div>
When I'm clicking the edit button, the corresponding part of the UI gets visible, but just after that, something happens, and the ul that should render the list, looses completely the binding, just showing something like:
[X] [E]{{ category.name }}
When it must be showing:
[X] [E]computer science
[X] [E]politics
[X] [E]news
(Which is what I have in the scope). It happens a few after the click (and works for a sec). No errors on the console, no interactions with other libraries (as far as I can see).
Thanks!
Turbolinks
I have no experience with Angular, but perhaps your problem could be to do with Turbolinks - this is a way of Rails loading the <body> tag of a page only - keeping the <head> intact.
Turbolinks is notorious for Javascript on Rails, as each time you reload your <body> without reloading the <head> part of your page, all your JS bindings are going to disappear. The solution to this, in normal JS, is to use JQuery / Javascript delegation, and delegate from the document object:
$(document).on("action", "delegated_object", function(){
...
});
Apologies if this does not work - it's a common issue for us, but as I have no experience with Angular, I don't know if it's going to help you or not.
It seems that I should have been more careful with the links:
<a href="#" ng-click='deleteCategory($index)'>[X]</a>
<a href="#" ng-click='editCategory($index)'>[E]</a>{{ category.name }}
Don't know exactly how this works, but seems that if the link has his href attribute, a GET request is made against 127.0.0.1, breaking in some way the angular code. If you put them like:
<a ng-click='deleteCategory($index)'>[X]</a>
<a ng-click='editCategory($index)'>[E]</a>{{ category.name }}
The problem will be solved. Thanks all for reading and helping!

open external link in angulardart in new tab/window

I am writing an angular dart app and the app contains a few links that point to other resources on the server.
I have a weird experience that some links are "handled" by angular and some not.
For example in the code I have these two links that are close to each other. Both are inside the same controllers scope. The first link is handled by angular, the second is opened in a separate window as configured. (Maybe due to the hashbang in the url?)
...
<div class="span4">
<div class="address">Direktlink</div>
not working link
</div>
</div>
<div class="row-fluid">
<div class="span12 modal_image">
<img src="http://localhost/modules/mod_orchit_baumodul/ajax/composite.php?haus=Aachen&variante=8&pos=0" class="ng-binding">
</div>
</div>
</div>
So I created a small directive
/**
* https://github.com/angular/angular.dart/issues/335
* https://github.com/angular/angular.dart/issues/864
*/
#NgDirective(
selector: 'a[externalLink]'
)
class ExternalLinkDirective {
Element element;
ExternalLinkDirective(this.element) {
element.onClick.listen((Event event){
window.location.assign(element.attributes["href"]);
});
}
}
but this has the disadvantage that I can't open the link in a new tab or window.
I couldn't find something that helped me with that in the API docs. :-(
Is there a way to open the first link in a new tab too?
OK, I figured it out. But it opened a new window each time, so I check for the target first.
Feel free to use this directive yourself.
/**
* https://github.com/angular/angular.dart/issues/335
* https://github.com/angular/angular.dart/issues/864
*/
#NgDirective(selector: 'a[externalLink]')
class ExternalLinkDirective {
Element element;
ExternalLinkDirective(this.element) {
element.onClick.listen((Event event) {
String target = "_SELF";
if (isValidTarget()){
window.open(element.attributes["href"], element.attributes['target']);
}
else window.location.assign(element.attributes["href"]);
});
}
bool isValidTarget(){
return element.attributes.containsKey("target") && element.attributes['target'].toLowerCase()!='_self';
}
}
Since route_hierarchical-0.4.19 this issue seems to be fixed.

split listview secondary button click event on dynamically added rows

I'm adding rows to a split listview with jQm, and I can only get the first row (not dynamically added) to trigger a click event. I assume there's a refresh function somewhere that I need to call, but I can't figure out what - I'm already refreshing the listview, which I expected to solve it...
Here's the fiddle:
http://jsfiddle.net/z36fy/1/
and here's the code:
<ul data-role="listview" data-split-icon="minus" id="list">
<li>
Item Description
remove
</li>
</ul>
Add item
JS:
var itemcount=1;
$('#addbtn').click(function() {
var addstr = '<li>Item Description '+itemcount+'remove</li></ul>';
$('#list').append(addstr);
$('#list').listview();
$('#list').listview('refresh');
itemcount++;
});
$('#list a.ui-li-link-alt').on("click",function() {
alert('delbtn clicked');
});
What am I missing?
Because you are dynamically adding DOM elements, you can't bind ahead of time. Instead use event delegation (https://learn.jquery.com/events/event-delegation/):
$('#list').on("click", ".delbtn", function() {
alert('delbtn clicked');
});
This says bind the click event to any items with class delbtn within the list even if they don't exist yet.
Updated FIDDLE

button tag not working in IE7 (using asp.net mvc )

I have this ASP.net MVC project that requires a wizard like interface...
So I am using the next ,back button inside the form.
And I am trapping the button name in my controller to do the required action.
But the problem is the button click is working in IE8,chrome,ff but not in IE7.
It doesnt seem to fire the postback...do I have to explicity fire the postback on Onclick?
Anyone knows why button click not firing in IE7 ???
thanks I appreciate any answer..
Here's the psuedo code I am using...
<% using (Html.BeginForm("ListEntries","Home",FormMethod.Post, new { #Id = "MyForm" } )) {%>
<button name="button" value="next">Next</button>
<button name="button" value="back">Back</button>
//blah....blh...blah...
<% } %>
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ListEntries( string button)
{
if (button == "next")
return RedirectToAction("doNextAction");
else
if (button == "back")
return RedirectToAction("goBack");
}
Button tags in IE (v. 8, at least) will not work without an 'onclick' handler. Well, at least you can't simply wrap the button in an anchor tag.
Doesn't work:
<a href="link.html">
<button>Click Me!</button>
</a>
Works:
<a href="link.html" onclick="javascript:window.location=this.href">
<button>Click Me!</button>
</a>
this link http://www.peterbe.com/plog/button-tag-in-IE makes me believe that in IE7 the button element will not post a single string to your controller so would not match the signature of your controller method, have you tried (as is suggested here) using input elements of type submit instead?
its not something I have seen myself but it seems to match your issue

prototype js event observation carrying to elements children

I have a html list as the following:
<ul>
<li id="one">
<ul id="sub_ul">
<li>sth</li>
<li>sth2</li>
<li>sth3</li>
</ul>
</li>
</ul>
I observe a click event on "one" in order to SlideUp, SlideDown "sub_ul". The problem is that when the list is open, clicking on any of the sub-elements triggers the SlideUp action. I would naturally like to avoid this. Could anybody please tell me how I can do that?
Cheers,
Manojo
In your event handler first check if an item has been clicked.
$('one').observe('click', function(event)}{
if (event.findElement('li') != document) {
event.stop;
return;
}
// continue normal processing
});

Resources