Setting ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix will prepend all name and id attributes.
I'm wondering if there is a way to prefix just the id and leave the name alone.
The scenario is this: A partial view is being loaded by AJAX multiple times on a page. A JavaScript library we are using requires the use of ids but we also want to be able to post the forms (so the names need to match the server model).
Our current solution is to generate a unique number for each time the partial view is loaded, set the HtmlFieldPrefix to items[n] (where n is the generated number) and for our action to recieve an array of items (where we only need to receive one). This gives us a globally unique id and a name which can be parsed by the model binder.
This feels ugly, though. Any suggestions?
I had the same issue as yourself.
#{ ViewData.TemplateInfo.HtmlFieldPrefix = "Prefix"; }
#using(Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.TextBoxFor(m => m.MerchantAccount.MerchantName, new { maxlength = 29, size = 35 })<br />
#Html.ValidationMessageFor(m => m.MerchantAccount.MerchantName)
}
Firstly, my bad idea: Use jQuery on page load to remove undesired prefix to all names.
$('[id*="Prefix_']).each(function(i, e) {...
What we actually ended up doing was suggested here: https://stackoverflow.com/a/1318342/4946681
Basically, on the controller you state what prefix to strip (by specifying a bind prefix in the method signature) and it's done for you automatically.
Now we can have our ID prefixes cake, and eat (bind) them, too!
Related
in webform we never have to think about controls ID or name for unique ness. everything webform handle automatically. so tell me when we assign name to html control's ID then how can i provide unique name ? please help me with small code snippet
just see it
#Html.DropDownListFor(x => x.Field, ModelClass.MakeSelectListUtenti(Model.Destinations), new { id="Destinations"})
here we specify the controls id name as "Destination" but how can i specify name like "UniqueID_" + "Destination" ?
someone show me a way to do it like below
#Html.DropDownListFor(x => x.Field, ModelClass.MakeSelectListUtenti(Model.Destinations), new { id= #guid.NewGuid().ToString() + "Destinations"})
i like to know is there any other way around. i heard that something new technique has been introduce in mvc4. is it true....what is that?
if possible also show me various way to generate unique client side id in mvc 3/4.
thanks
As I know,there is noway can do it on official way,so I suggest a jQuery way:
First set a custom attribute instead the id for dropdownlist like this:
#Html.DropDownListFor(x => x.Field, ModelClass.MakeSelectListUtenti(Model.Destinations), new { originalid="Destinations"})
And this can be put multi times,then write a script on your page:
$(document).ready(function () {
$("[originalid]").each(function () {
var originalid = $(this).attr("originalid");
$(this).attr("id", $("[originalid='" + originalid + "']").index($(this)) + "_" + originalid);
});
})
And the same id will be init as "0_Destinations" "1_Destinations" etc.
I can't get to VS to give you a code example, but I would do something similar to what you have been shown, but using integers.
I am assuming the ID's are an issue because you are creating dropdowns on the fly. Otherwise you would obviously just change the text.
If you are creating dropdowns on the fly from a list, you could put it within a for loop and use the current number as a pre-pend to your id. This would give a result like id= #myInt + "_Destinations" -> '0_Destinations', '1_Destinations' etc. I have used this pattern many times. It makes for easy jQuery selection and is much tidier than Guid ids.
If you are not looping through a list, you could create a method that gives you a number and then pre-pend that in an Id.
I'm trying to change the emitted name of the html input created by #Html.HiddenFor.
The code I'm using this:
#Html.HiddenFor(e => e.SomeProperty, new { #id = "some_property", #name = "some_property" }
Now this works for the id, however it doesn't work for the name. Now I don't really care for the id now, I need the name to change, because that's the one that get's posted back to the target server.
Is there
A property I can apply on SomeProperty in my model?
A way in the Html.HiddenFor to override the name property?
Or am I stuck to do a plain <input ...> by hand?
You need to use the Html.Hidden (or write out the <input ...> by hand) instead of the Html.HiddenFor
#Html.Hidden("some_property", Model.SomeProperty, new { #id = "some_property" })
The goal of the strongly typed helpers (e.g the one which the name end "For" like HiddenFor) is to guess the input name for you from the provided expression. So if you want to have a "custom" input name you can always use the regular helpers like Html.Hidden where you can explicitly set the name.
The answer from unjuken is wrong because it generates invalid HTML.
Using that solution generates TWO name attributes:
<input Name="some_property" name="SomeProperty" id="some_property" type="hidden" value="test" />
So you will have Name="some_property" AND name="SomeProperty" which is INVALID HTML because an input can only have ONE name attribute! (although most browers happen to take the first Name="some_property" and don't care about the second one...)
If you use:
#Html.HiddenFor(e => e.SomeProperty, new { #id = "some_property",
#Name = "some_property" });
Notice the capital "N" in #Name. It´ll work.
I was curious as to why specifically overriding the name attribute wouldn't work. Unless I capitalized it (i.e. new {#Name = 'somename'} ), then it doesn't seem to work. As others have pointed out, this only works because it generates duplicated name attributes and Chrome cleans it up.
I looked at the latest MVC source code to figure out what is going on. Consider the following snippet from the GenerateInput method in DefaultHtmlGenerator.cs:
var fullName = NameAndIdProvider.GetFullHtmlFieldName(viewContext, expression);
if (string.IsNullOrEmpty(fullName))
{
throw new ArgumentException(
...
}
var inputTypeString = GetInputTypeString(inputType);
var tagBuilder = new TagBuilder("input");
tagBuilder.TagRenderMode = TagRenderMode.SelfClosing;
tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.MergeAttribute("type", inputTypeString);
tagBuilder.MergeAttribute("name", fullName, replaceExisting: true);
We can see here, the problem is that, regardless of whatever name property you provide, it will be overridden by the last call to MergeAttribute, which will use whatever logic it is that assigns to the variable fullName from the GetFullHtmlFieldName method.
I sort of understand why they enforce this behavior, guessing it has something to do with controlling the names used in the postback to guarantee it works with the model binder.
In any case, to make this happen, I say just manually construct the input element and don't use the razor view helper.
never worked for me (aspnet.core)
I used plain
<input type="hidden" id="#myid" name="#myname" value="#Model.prop" />
and worked like a charm. No need for HtmlHelper HiddenForModel.
For reasons that are questionable but practical, I'd like to create LabelTemplate defaults, just like EditorTemplates or DisplayTemplates.
So instead of this:
#Html.LabelFor(x => x.PropertyName, "Property Name")
or instead of this(the better way to do it in a View Model):
[DisplayName("Property Name")]
public string PropertyName{ get; set; }
I want this:
#Html.LabelFor(x => x.PropertyName)
With this (in a folder like this: /Views/Shared/LabelTemplates)
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.String>" %>
//Display logic here
Can you help a coder out?
Create your own custom html helper.
http://develoq.net/2011/how-to-create-custom-html-helpers-for-asp-net-mvc-3-and-razor-view-engine/
This is the code you can use to convert your property names:
Regex.Replace("PropertyName", "[a-z][A-Z]", m => m.Value[0] + " " + m.Value[1]);
I know this isn't strictly an answer to your question, but since I still want to suggest a plan of action, I'll post it like this rather than in a comment.
Are you sure you want this?
If you manage to do this, you will set the label of a field to some value based on its type. This might seem tempting at first glance - you could possibly save yourself some key strokes every here and there.
But what happens if you e.g. have a type Address containing some properties for street name, number, zip code etc, and then want the user to fill in the home address and the work address in the same form - how would you label them differently and still use the same type? And even worse - do you really want the same label on all your strings? In order to avoid these two scenarios, you'll need to resort to Html.DisplayFor(m => m.PropertyName, "TemplateName") anyway, which means you'll be in just as sorry a situation as you already are. Furthermore, you'll have at least two places you have to look to find the correct display logic for your label, rather than just one.
Remember that there is no absolute requirement to use the LabelFor() helper - you can just as well just roll your own extension method on HtmlHelper, or even ignore them and output plane HTML:
<label for="Person_HomeAddress">Home address</label> <!-- the ID might be wrong -->
<%: Html.EditorFor(m => m.HomeAddress) %>
Since the EditorFor() outputs an ID matched to the name of the model and property names, you'll be fine.
I have something like:
<input type="text" name="TerrMng" id="TerrMng"/>
in HTML. What is the equivalent of the above using #Html.Display?
I tried using: #Html.Display("TerrMng", TerrMng)
but was not successful. Note that I like to use #Html.Display but not sure how to translate the ID value so that it shows up.
The Display method is not for creating input boxes. You'd want to use:
#Html.TextBoxFor(m => m.TerrMng);
or the templated helper method:
#Html.EditorFor(m => m.TerrMng);
I'm assuming that you want to use modelbinding. If not, if you really just want to use a helper to simply make an input tag, use:
#Html.TextBox("TerrMng");
This would be sent to the client:
<input id="TerrMng" type="text" value="" name="TerrMng">
The first 2 methods above would result in the exact same html, if model.TerrMng was "" or String.Empty. If for some reason you don't want the value attribute, you'll need to type it out yourself.
This should do the trick if you are just wanting to display the data and not allow the user to edit the information.
#Html.DisplayFor(m => m.TerrMng);
Edit:
what-is-the-html-displayfor-syntax-for is another question on stackoverflow that may give you some more guidance.
Edit:
TerrMng does not exist on PageLoad so you cannot use the Html.Display in that way. You need to create it and fill its value with the value received from the jQuery. In this case where you would have to do the following:
HTML
#Html.Display("TerrMng"); // This creates the label with an id of TerrMng
jQuery
$("#TerrMng").val(TerrMng); // This puts the value of the javascript variable into the label
You could try something based on this. This is not exact but you could get some idea.
#Html.TextBoxFor(yourmodel => model.yourModelFieldname, null)
#Html.Display() is used instead of #Html.DisplayFor() when your model is not known at compile time, or if you prefer to work with strings, rather than with strong types. For example, these 2 are equivalents (given that your model is some class):
#Html.DisplayFor(m => m.MyProperty)
and
#Html.Display("MyProperty")
But the additional cool feature of the Display() method is that it can also do the lookup in the ViewData, and not just in your Model class. For example, here is a way to display the HTML for the property on a random object, given that we know it has a property named "Blah" (the type of the object doesn't really matter):
#{ ViewData["itsawonderfullife"] = SomeObject; }
<div>#Html.Display("itsawonderfullife.Blah")</div>
This way, we are telling HtmlHelper to look into the ViewData, instead of our Model, and to display the property Blah of a given SomeObject.
For some reason I'm stuck on this. I need to filter results from a View based on a DropDownList in the same view. The basic idea is this: I have a list of providers that belong to various partners, but the provider list contains ALL the providers together (for all partners). I need to be able to display the providers by partner when someone wants to see just that partner (otherwise, the default listing will be ALL providers). My view currently is the "default" (showing all), but for some reason Im sitting here staring at the monitor (for the last 2 hours!) trying to figure out how to filter these results.
Any suggestions where to start/how to do it?!
EDIT: If you want to do this with jQuery and AJAX (which will provide a better user experience because only the subdivisions list will refresh), see this tutorial.
If I understand correctly, you basically want to do a WebForms-style postback.
Let's say you have a control with countries and country subdivisions (e.g. states, provinces, etc). When the country changes, you want the appropriate subdivisions to display.
So this would be view:
<% using (Html.BeginForm()) { %>
<%=Html.DropDownList("Address.CountryId", new SelectList(Country.GetAll(), "Id", "Name"), new { onchange = "this.form.submit();" })%>
<%=Html.DropDownList("Address.CountrySubdivisionId", new SelectList(CountrySubDivision.GetByCountryId(Model.CountryId), "Id", "Name"))%>
<input type="submit" name="btnSubmit" value="Submit"/>
<%} %>
This is the key to getting the dependent list to filter:
new { onchange = "this.form.submit();" }
And in the controller, you'd have something like this:
[AcceptVerbs(HttpVerbs.Post)]
public ViewResult Index(string btnSubmit)
{
if (btnSubmit == null)
{
// return the view displayed upon GET
}
else
{
// process the submitted data
}
}
In the above code, if the form submission was triggered by changing the value in a dropdown, btnSubmit will be null. Thus, the action you are POSTing to can tell whether or not the user meant to finalize her changes.
To add upon the earlier answers.
To create a drop down (in ASP .NET MVC 3) I did the following:
Add code to Index.cshtml
#using (Html.BeginForm())
{
#Html.DropDownList("EmployeeId", (SelectList)ViewData["EmployeeId"])
<input type="submit" name="btnSubmit" value="Submit"/>
}
Add code to YourModelNameController.cs in the default ActionResult for Index()
public ActionResult Index()
{
//create a selectlist
var employeeList = from el in db.Employee select el;
ViewData["EmployeeId"] = new SelectList(employeeList, "EmployeeId", "TmName");
return View(modelName);
}
There are many ways to skin this cat. Here's one.
Enclose your DropDownList in a form with METHOD=GET.
<form action="" method="get">
<select name="provider">
<option>1</option>
<!-- etc -->
</select>
</form>
Then, in you controller, filter based on the value of provider that was passed in. Remember to treat it as a Nullable parameter so that you can have some kind of behavior when it's empty.
Without posting some of your current code, it's tough to get much more specific than that.
Let's assume that you're probably passing a model to the view and that model is a list or IEnummerable of partners. What you want to do is restrict the list. In order to do that add a drop down list in the view and fill it with some possible partners. This can be done either by putting a list in ViewData or expanding the model passed back to the view. Both have advantages. Now when you change the drop down reload the page but append a parameter which is the filter. In the controller check for that parameter in the action, if it isn't present then return an unfiltered list, if it is then apply a filter and return the list. The view will just dumbly display whatever you give it.
As for the filtering you might want to try using LINQ.
You probably want a parameter to your controller action, maybe a (nullable?) id of the provider, to filter the results already when you get them from DB. Then just use the same view to list them, and request a new list if the dropdownlist changes.
Best solution I know is that one.
http://gridmvc.codeplex.com/SourceControl/latest