MVC getting id on button click - asp.net-mvc

I am trying to get the id of the selected button.
This is my code below
<% foreach (var item in Model.getLeagues) { %>
<a href=Teams.aspx class="leagueImage">
<img src="../../<%: item.image %>" alt="<%: item.name %>" />
</a>
<% } %>
With this code I am generating 5 buttons and then I need the id of the clicked button.
Any help of how I can get this id ?
Thanks

If you want to get the ID from the controller, why not take the suggestion Marko made, but instead of putting it into the id attribute, instead put make it part of your href tag and pass the ID attribute.
By default, the routing in MVC expects back an ID which is part of your route in:
http://sitename/{Controller}/{Action}/{Id}
So, you could do something like this (I'm going to use Razor syntax, but, you can adjust):
#for(var i = 0; i < Model.getLeagues.Count; i++) {
Html.ActionLink("Button Name", "Index", "MyController", new { id = Model.getLeages[i] }, new { #class="classname", alt = "#Model.getLeagues[i].name" }) %>
}
And, in your controller (rename as appropriate) you would have:
public class MyController : Controller {
public ActionResult Index(int id) {
// Do stuff with the ID that you get back here.
}
}
Also, you'll notice that I broke out your image information. Instead, make a class in your stylesheet like:
a.classname
{
background: url(../Images/image.gif) no-repeat top left;
/* Do whatever else you need to do here to style your buttons. */
}
I didn't check any of the code, so can't guarantee it's syntactically perfect, but that should get you going down a right path.
I did notice your path to Teams.aspx. If you are coming from WebForms, you can edit your routing file to direct towards the RESTful route like this:
routes.MapPageRoute("Teams", "MyController/Index", "~/WebForms/Index/Teams.aspx");
(Credit to: https://stackoverflow.com/a/10175580/132528)

If you change your loop to following:
<% for (var i = 0; i <= Model.getLeagues.Count; i++) { %>
<a href="Teams.aspx" id="link_<%: i %>" class="leagueImage">
<img src="../../<%: Model.getLeagues[i].image %>" alt="<%: Model.getLeagues[i].name %>" />
</a>
<% } %>
now you have anchor tags with unique IDs (link_0, link_1, ...). So now using jquery click event like this:
$(document).ready(function() {
$(".leagueImage").click(function() {
alert($(this).id);
});
});
will get you a popup box that will display the ID of the clicked anchor tag.

If you are looking to get the index of the collection you are looping though, try this:
Model.getLeagues.indexOf(item)

Related

Can't get Properties of a Specific Child Page

I just started using umbraco 4 days ago and I'm stuck with this problem.
I have a page named "About Us" that is a child under "Home" and I need to get some of its properties in the "Home" Page.
I created a partial view macro to do this but I get the error loading partial view script instead.
Below is my code:
#{ var selection = CurrentPage.Children.Where(x => x.Name == "aboutus"); }
#if (selection.Any())
{
<ul>
#foreach (var item in selection)
{
<div class="sc-inner">
<h4>
#item.PageTitle</h4>
<p>
#Umbraco.Truncate(#item.mainAboutDescription, 100)</p>
<a class="btn btn-danger" href="#item.Url">Read More...</a>
</div>
break;
}
</ul>
}
Can someone please tell me what I'm doing wrong?
Thanks in advance.
Edits:
The error on the website I got is below;
Error loading Partial View script (file: ~/Views/MacroPartials/homePage_aboutUsSection.cshtml)
Assuming the partial is inheriting UmbracoTemplatePage the CurrentPage property is a dynamic, you cannot use lambda expressions as an argument to a dynamically dispatched operation.
If you wish to use Linq to query the content use Model.Content rather than CurrentPage which is an IPublishedContent e.g.
#{ var selection = Model.Content.Children.Where(x => x.Name == "aboutus"); }
Note: the Name property will return the documents Name as entered in the CMS most likely 'About Us' instead of 'aboutus'
Using the about will return an IEnumerable<IPublishedContent> so you will need to use the GetPropertyValue method rather than accessing the content dynamically:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{ var selection = Model.Content.Children.Where(x => x.Name == "aboutus"); }
#if (selection.Any())
{
<ul>
#foreach (var item in selection)
{
<li class="sc-inner">
<h4>
#item.GetPropertyValue("pageTitle")
</h4>
<p>
#Umbraco.Truncate(#item.GetPropertyValue<string>("mainAboutDescription"), 100)
</p>
<a class="btn btn-danger" href="#item.Url">Read More...</a>
</li>
break;
}
</ul>
}
Very bad practice to use the Name property for querying in your code - what if somebody changes the Name to About for example. Your code would break. If there is something else that is unique on the node then it would be better.
For example if you have an aboutUs document type for your about us page you could use:
Model.Content.Children.Where(x => x.DocumentTypeAlias == "exactNameOfYourDocTypeAliasHere")
or, although not so robust, the Id of the page could be used.
Model.Content.Children.Where(x => x.Id == 1234)
The Id is far less likely to change than the Name of a key page like this.
I would generally not use the Id in code either but it is far better than Name

How to have a button in a form post to a different action

Let's say I have a form listing some items:
#using (Html.BeginForm("Index", "SagePayServerInframe", FormMethod.Post))
{
if (Model.Tokens.Any())
{
<h2>Select an existing card</h2>
for (int i = 0; i < Model.Tokens.Count; i++)
{
<div class="sagepay-wrapper">
<div><span>Card Type:</span> #Model.Tokens[i].CardType</div>
<div><span>Last 4 Digits:</span> #Model.Tokens[i].Last4Digits</div>
<div><span>Expiry Date:</span> #Model.Tokens[i].ExpiryDate</div>
<div>
#Html.RadioButtonFor(m => m.SelectedTokenId, Model.Tokens[i].Id, new { #id = "SelectedTokenId" + i })
<label for="SelectedTokenId#(i)">SELECT</label>
</div>
</div>
}
}
<input type="submit" value="Continue" class="uppercase"/>
}
Now, I want to put a Delete button against each entry as well. I can't seem to have another form within the existing form (it wouldn't show on the page when I tried a new Html.BeginForm).
How would I achieve this? Ideally, I'd like to be able to post back to a DeleteToken action. I get the feeling I'm missing something simple but not sure what it is.
Use a Jquery hack like (Code not tested, may have syntax error, sorry for that)
When button1 is pressed, access the form object and reset the form url.
$("#button1").click(form(){
$(this).form.URL = "../Controller1/Action1";
});
AND when button2 is clicked
$("#button2").click(form(){
$(this).form.URL = "../Controller2/Action2";
});

jQuery .show() not working on <span> tag

This seems like it would be pretty straightforward. I have a text box and I want a link to display based on whether or not there is content in there. In my document.ready I have the code set to
$(document).ready(function () {
$('#searchValue').change(function () {
if ($('#searchValue').val().length > 0) {
$('#home').show();
} else {
$('#home').hide();
}
});
and here is the section from my ASP MVC view with the links I'm referring to. I want everything outside the span to display when the page loads, everytime. Anything in the span, only when there is information in the text box.
#Html.ActionLink("Create New", "Create") |
#Html.ActionLink("Export to Spreadsheet", "ExportToCsv")
<span class="home" style="display:none;">
| #Html.ActionLink("Back to Index", "Index")
</span>
I've tried this with and without the style="display:none;" attribute and I cannot get the .show() or .hide() to fire. I have stepped through the code and can see that the condition in the doucment.ready is working, however, and that part of the code is being reached.
You need class selector instead of id selector, You have home as class of span not the id either you assign home to id or use class selector.
Change
$('#home')
To
$('.home')
You code would be
$(document).ready(function () {
$('#searchValue').change(function () {
if ($('#searchValue').val().length > 0) {
$('.home').show();
} else {
$('.home').hide();
}
});
You're calling span id of home and it actually is the class.
Change to $('.home')
Simple enough:
$('#searchValue').change(function () {
if ($(this).val().length > 0) $('.home').show();
else $('.home').hide();
});

Can we dynamically change the URL with Ajaxy call on ASP.NET MVC page?

I have an ASP.NET MVC application that has a view called Products.
This Products View has a Left Menu Navigation that is implemented using NavMenuProducts.ascx Partial View.
This Menu is implemented using JQuery Treeview so that it has the list of ProductNames as the Parent Node and it is expandable(For Example: 10 Products).
Each of these Products have a ChildNode as DocTypeName and it is a hyperlink(For Example: 3 DocTypeNames).
When the user clicks ChildNode Hyperlink all the matching Documents are displayed and is implemented using Ajaxy call. So that the user has better UI experience.
But the problem with this is the url always is static(Example: http://DocShare )
But based on the Node that is clicked, I want the url like http://DocShare/Products/Product1/Letter
I am wondering how to make this dynamic url using Ajaxy call.
NOTE: If I am using HTML.ActionLINK, then I am getting dynamic URL. But this ActionLink, while the Page is loading, we are getting random treeview screen. TO avoid that flickering tree effect, I am making Ajax call for better UI experience.
Any solution would be appreciated for getting dynamic url with Ajaxy call.
Here is the Code:
NavigationProducts.ascx Page:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MedInfoDS.Controllers.ProductViewModel>" %>
<script type="text/javascript">
$(document).ready(function () {
$(".docId").click(function () {
alert("DocTypeName: " + this.id);
$("#docDetails").load('<%= Url.Action("DocumentDetails") %>', { ProductName: "darbepoetin alfa", DocTypeName: this.id }, function (responseText, status) {
});
return false;
});
});
<div id="treecontrol">
<a title="Collapse the entire tree below" href="#">Collapse All</a> | <a title="Expand the entire tree below"
href="#">Expand All</a> | <a title="Toggle the tree below, opening closed branches, closing open branches"
href="#">Toggle All</a>
</div>
<div id="divByProduct">
<ul id="red" class="treeview-red">
<% foreach (var item in Model.Products)
{ %>
<li><span>
<%=item.Name%></span>
<ul>
<%foreach (var item1 in Model.DocTypes) { %>
<li><span>
<%= Html.ActionLink(item1.DocTypeName, "Products", new { ProductName = item.Name, DocTypeName = item1.DocTypeName })%>
<br />
<a class="docId" href="#" id="<%=item1.DocTypeName%>"><%= item1.DocTypeName%></a>
<%= Html.Hidden("ProductName", item.Name)%>
</span></li>
<% } %>
</ul>
</li>
<% } %>
</ul>
</div>
Controller Method:
// Response to AJAXy call to populate details for given ProductName and DocType
[HttpPost]
public virtual ActionResult DocumentDetails(string ProductName, string DocTypeName)
{
var entities = new MIDSContainer();
if (ProductName == null) return View();
int ProductId = (entities.Products.FirstOrDefault(p => p.Name == ProductName)).ProductId;
int DocTypeId = (entities.DocTypes.FirstOrDefault(d => d.DocTypeName == DocTypeName)).DocTypeId;
var documents = (from d in entities.Documents.Where(p => p.ProductId == ProductId && p.DocTypeId == DocTypeId && p.AvailableForUse == true && p.Status == "Approved") orderby (d.Description) select d).ToList();
return View(documents);
}
There's a pretty comprehensive solution here: http://ajaxpatterns.org/Unique_URLs
I assume you want to "change the url" so that the Back button works in the browser to navigate between the different products. You can't actually change the URL without a postback, but you can change the url's Hash value. By changing the Hash value you will be able to support the browsers Back button just like the URL itself was changed but without any postbacks.
In the following URL:
http://site/page#SomeValue
The Hash value is "#SomeValue".
You can set the Hash using "document.Hash" in JavaScript.
To make it much easier to work with the "document.Hash" value and setup a function to get notified when it changes, I create the jHash project.
You'll probably want to look at jHash to help you do what you're looking for.
http://jhash.codeplex.com/

Html.ActionLink as a button or an image, not a link

In the latest (RC1) release of ASP.NET MVC, how do I get Html.ActionLink to render as a button or an image instead of a link?
I like to use Url.Action() and Url.Content() like this:
<a href='#Url.Action("MyAction", "MyController")'>
<img src='#Url.Content("~/Content/Images/MyLinkImage.png")' />
</a>
Strictly speaking, the Url.Content is only needed for pathing is not really part of the answer to your question.
Thanks to #BrianLegg for pointing out that this should use the new Razor view syntax. Example has been updated accordingly.
Late response but you could just keep it simple and apply a CSS class to the htmlAttributes object.
<%= Html.ActionLink("Button Name", "Index", null, new { #class="classname" }) %>
and then create a class in your stylesheet
a.classname
{
background: url(../Images/image.gif) no-repeat top left;
display: block;
width: 150px;
height: 150px;
text-indent: -9999px; /* hides the link text */
}
Borrowing from Patrick's answer, I found that I had to do this:
<button onclick="location.href='#Url.Action("Index", "Users")';return false;">Cancel</button>
to avoid calling the form's post method.
Call me simplistic, but I just do:
<a href="<%: Url.Action("ActionName", "ControllerName") %>">
<button>Button Text</button>
</a>
And you just take care of the hyperlink highlight. Our users love it :)
Using bootstrap this is the shortest and cleanest approach to create a link to a controller action that appears as a dynamic button:
Click Me
Or to use Html helpers:
#Html.ActionLink("Click Me", "Action", "Controller", new { #class = "btn btn-primary" })
if you don't want to use a link, use button. you can add image to button as well:
<button type="button" onclick="location.href='#Url.Action("Create", "Company")'" >
Create New
<img alt="New" title="New" src="~/Images/Button/plus.png">
</button>
type="button" performs your action instead of submitting form.
Just simply :
<button onclick="#Url.Action("index", "Family", new {familyid = Model.FamilyID })">Cancel</button>
A late answer but this is how I make my ActionLink into a button. We're using Bootstrap in our project as it makes it convenient. Never mind the #T since its only an translator we're using.
#Html.Actionlink("Some_button_text", "ActionMethod", "Controller", "Optional parameter", "html_code_you_want_to_apply_to_the_actionlink");
The above gives a link like this and it looks as the picture below:
localhost:XXXXX/Firms/AddAffiliation/F0500
In my view:
#using (Html.BeginForm())
{
<div class="section-header">
<div class="title">
#T("Admin.Users.Users")
</div>
<div class="addAffiliation">
<p />
#Html.ActionLink("" + #T("Admin.Users.AddAffiliation"), "AddAffiliation", "Firms", new { id = (string)#WorkContext.CurrentFirm.ExternalId }, new { #class="btn btn-primary" })
</div>
</div>
}
Hope this helps somebody
You can't do this with Html.ActionLink. You should use Url.RouteUrl and use the URL to construct the element you want.
A simple way to do make your Html.ActionLink into a button (as long as you have BootStrap plugged in - which you probably have) is like this:
#Html.ActionLink("Button text", "ActionName", "ControllerName", new { #class = "btn btn-primary" })
<button onclick="location.href='#Url.Action("NewCustomer", "Customers")'">Checkout >></button>
Even later response, but I just ran into a similar issue and ended up writing my own Image link HtmlHelper extension.
You can find an implementation of it on my blog in the link above.
Just added in case someone is hunting down an implementation.
<li><i class='fa fa-user'></i><span>Users View</span></li>
To display an icon with the link
Do what Mehrdad says - or use the url helper from an HtmlHelper extension method like Stephen Walther describes here and make your own extension method which can be used to render all of your links.
Then it will be easy to render all links as buttons/anchors or whichever you prefer - and, most importantly, you can change your mind later when you find out that you actually prefer some other way of making your links.
you can create your own extension method
take look at my implementation
public static class HtmlHelperExtensions
{
public static MvcHtmlString ActionImage(this HtmlHelper html, string action, object routeValues, string imagePath, string alt, object htmlAttributesForAnchor, object htmlAttributesForImage)
{
var url = new UrlHelper(html.ViewContext.RequestContext);
// build the <img> tag
var imgBuilder = new TagBuilder("img");
imgBuilder.MergeAttribute("src", url.Content(imagePath));
imgBuilder.MergeAttribute("alt", alt);
imgBuilder.MergeAttributes(new RouteValueDictionary(htmlAttributesForImage));
string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);
// build the <a> tag
var anchorBuilder = new TagBuilder("a");
anchorBuilder.MergeAttribute("href", action != null ? url.Action(action, routeValues) : "#");
anchorBuilder.InnerHtml = imgHtml; // include the <img> tag inside
anchorBuilder.MergeAttributes(new RouteValueDictionary(htmlAttributesForAnchor));
string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);
return MvcHtmlString.Create(anchorHtml);
}
}
then use it in your view take look at my call
#Html.ActionImage(null, null, "../../Content/img/Button-Delete-icon.png", Resource_en.Delete,
new{//htmlAttributesForAnchor
href = "#",
data_toggle = "modal",
data_target = "#confirm-delete",
data_id = user.ID,
data_name = user.Name,
data_usertype = user.UserTypeID
}, new{ style = "margin-top: 24px"}//htmlAttributesForImage
)
For Material Design Lite and MVC:
<a class="mdl-navigation__link" href='#Url.Action("MyAction", "MyController")'>Link Name</a>
#using (Html.BeginForm("DeleteMember", "Member", new { id = Model.MemberID }))
{
<input type="submit" value="Delete Member" onclick = "return confirm('Are you sure you want to delete the member?');" />
}
There seems to be lots of solutions on how to created a link that displays as an image, but none that make it appear to be a button.
There is only good way that I have found to do this. Its a little bit hacky, but it works.
What you have to do is create a button and a separate action link. Make the action link invisible using css. When you click on the button, it can fire the click event of the action link.
<input type="button" value="Search" onclick="Search()" />
#Ajax.ActionLink("Search", "ActionName", null, new AjaxOptions {}, new { id = "SearchLink", style="display:none;" })
function Search(){
$("#SearchLink").click();
}
It may be a pain in the butt to do this every time you add a link that needs to look like a button, but it does accomplish the desired result.
use FORMACTION
<input type="submit" value="Delete" formaction="#Url.Action("Delete", new { id = Model.Id })" />
Just found this extension to do it - simple and effective.
The way I have done it is to have the actionLink and the image seperately.
Set the actionlink image as hidden
and then added a jQuery trigger call. This is more of a workaround.
'<%= Html.ActionLink("Button Name", "Index", null, new { #class="yourclassname" }) %>'
<img id="yourImage" src="myImage.jpg" />
Trigger example:
$("#yourImage").click(function () {
$('.yourclassname').trigger('click');
});
Url.Action() will get you the bare URL for most overloads of Html.ActionLink, but I think that the URL-from-lambda functionality is only available through Html.ActionLink so far. Hopefully they'll add a similar overload to Url.Action at some point.
This is how I did it without scripting:
#using (Html.BeginForm("Action", "Controller", FormMethod.Get))
{
<button type="submit"
class="btn btn-default"
title="Action description">Button Label</button>
}
Same, but with parameter and confirmation dialog:
#using (Html.BeginForm("Action", "Controller",
new { paramName = paramValue },
FormMethod.Get,
new { onsubmit = "return confirm('Are you sure?');" }))
{
<button type="submit"
class="btn btn-default"
title="Action description">Button Label</button>
}

Resources