I have 2 fields in a MVC view.
One is #Html.TextBox("txtFirstName")
Second is hidden - #Html.TextBoxFor(model => model.FirstName, new { #type = "hidden" })
The hiddenField is there for posting purposes (as the firstTextbox can be disabled as times).
My question is How do I retrieve the client ID of first Textbox in Javascript ?? I can easily access the client ID of second textbox by '#Html.FieldIdFor(m => m.FirstName)'
The client ID has the modelName prefixed and I dont want to do any hardcoding in Javascript code.
In this case it will be txtFirstName.
But you could explicitly set it:
#Html.TextBox("txtFirstName", "some sample value", new { id = "txtFirstName" })
and then access it as usual:
var value = document.getElementById('txtFirstName').value;
or if you are using jQuery:
var value = $('#txtFirstName').val();
Use HTML helper inside your Javascript:
Javascript & Razor:
var textboxId = '#Html.IdFor(m => m.FirstName)';
There are several extensions:
#Html.IdFor(m => m.FirstName)
#Html.NameFor(m => m.FirstName)
Here is the full list of HTML helper methods http://msdn.microsoft.com/en-us/library/system.web.mvc.htmlhelper_methods(v=vs.108).aspx
Good luck
Related
I have a problem when I want to bind a value from my model to a textbox, here is my MVC view code:
#Html.TextBox("SellerBroker", model => model.OutOfMarket.BuyerBroker.Name , new { #class = "control-label" })
I want my textbox to have a name or 'SellerBroker' and it's value to come from my model property model => model.OutOfMarket.BuyerBroker.Name and with HTML attributes of class = "control-label". However, I am receiving the following error:
Cannot convert lambda expression to type 'object' because it is not a delegate type
The #Html.TextBox() can be used for generating a textbox with an initial value (one way binding).
If you want to really bind the textbox to your class property (two ways binding), you should use the #Html.TextBoxFor() helper. This method take as parameter a lambda expression, as used in your example.
You can found more details on TextBox helpers at : Html.Textbox VS Html.TextboxFor
Helper #Html.TextBox() does not contain overloard that have lambda parameter. You should use it without lambda like this like #Stephen Muecke advice you:
#Html.TextBox("SellerBroker", Model.OutOfMarket.BuyerBroker.Name , new { #class = "control-label" })
If you want to use lambda you should use #Html.TextBoxFor() helper. But you should change name like this:
#Html.TextBoxFor(model => model.OutOfMarket.BuyerBroker.Name, new { Name = "SellerBroker", #class = "control-label"})
I am working on an MVC 5 application and have the following scenario.
The user clicks my registration link to create an account and is served with a view like so. Works as expected.
[HttpGet]
[AllowAnonymous]
public ActionResult RenderRegisterModal(string userType)
{
IList<UserTypesDto> userTypes = _userService.GetUserTypes();
var usersRegisterUserViewModel = new UsersRegisterUserViewModel {UserTypes = new List<SelectListItem>()};
usersRegisterUserViewModel.UserTypes.Add(new SelectListItem
{
Text = "Select a registration type",
Value = "0"
});
foreach (UserTypesDto userTypeDto in userTypes)
{
usersRegisterUserViewModel.UserTypes.Add(new SelectListItem
{
Text = userTypeDto.UserType,
Value = userTypeDto.UserTypeId.ToString()
});
}
return PartialView("_RegisterModal", usersRegisterUserViewModel);
}
Now based on the type of customer / userType they choose I need to present different views. Should not have any issue getting the view into the modal as it is ajax... So lets call this a pseudo wizard to collect data. The issue I am having and the basis for this probably simple question, that I am thinking too much about, is how do I save the data from each step?? Temp Table? InMemory Cache using the session id as the key? Cookies? "Gross"
The ActionMethod that the post goes to looks like this.
[AllowAnonymous]
[HttpPost]
public ActionResult Register(UsersRegisterUserViewModel usersRegisterUserViewModel)
{
//TODO Return a view for the next step based on the CustomerType contained in the viewModel
return View();
}
Any feedback would be greatly appreciated.
OPTION 1:
The easiest way, is that the NEXT view have a set of hidden fields with the information entered in the previous view and which was posted to the Action.
This way, once you post the second view, you will be posting all the information (previous one and the one you entered in the second view).
OPTION 2:
If you are not comfortable with the first approach, you can have several PartialViews that are shown or hidden in javascript on UserType combo changes. Your ViewModel should have all the propertied you need to hold the information before posting back to server.
This option came in 2 flavors: you render all your usertype partials at the begining (so you need to hide them at first), or you can get the partial via Ajax once the user selected one user type.
OPTION 3:
You can use Session to hold the sensitive data from the register form, redirect to the next view depending on user type, post the new form, and in the Action you retrieve the information from Session... and with all the information in your hands store it in database.
If you're using razor, persist the different parts of your model like this
#Html.EditorFor(model => model.data1)
#Html.EditorFor(model => model.data2) #*Wizard part 1*#
then in the next view for your wizard
#Html.HiddenFor(model => model.data1)
#Html.HiddenFor(model => model.data2)
#Html.EditorFor(model => model.data3)
#Html.EditorFor(model => model.data4) #*Wizard part 2*#
and then
#Html.HiddenFor(model => model.data1)
#Html.HiddenFor(model => model.data2)
#Html.HiddenFor(model => model.data3)
#Html.HiddenFor(model => model.data4)
#Html.EditorFor(model => model.data5) #*Wizard part 3...*#
and so on...
I have in my edit form displayed: Username, TimeZone, Customer...
I don't whant to be able to edit username, just display his name.
This code I use in View:
<label>Username </label>
<div class="editor-field">
#Html.EditorFor(model => model.username)
</div>
So what to put instead EditorFor, that will display username (just for reading, not for editing).
Why not just use #Html.DisplayFor instead? This will just display the username as a label. Or, if you wish to use #Html.EditorFor or #Html.EditorForModel, you can create a custom editor template for your username property, and in the editor template, just display the content instead of enabling editing.
Also, I would recomment you exclude this property during model binding by using [Bind(Exclude="username")] with your model parameter in your POST action method, to protect from injection attacks. More about this here.
find solution:
#Html.TextBoxFor(model => model.username, new {disabled = "disabled", #readonly = "readonly" })
I've done this a hundred times but not sure what is going on here. I have a DropDownListFor that I populate in the controller like so
var mktsegments = from p in db.ChannelMarketSegment
where (p.ChannelCode != "0")
select p;
ViewBag.Pendist = new SelectList(mktsegments, "Pendist", "Pendist");
And in the view, I am attempting to set the default value of this drop down list with the Pendist value.
EDIT: Pendist is a field that exists in each item pulled into mktsegments via the Linq query.
<div class="M-editor-label">
#Html.LabelFor(model => model.Pendist)<span class="req">*</span>
</div>
<div class="M-editor-field">
#Html.DropDownListFor(model => model.Pendist,
(SelectList)ViewBag.Pendist, new { onchange = "ChangeChannel()" })
</div>
However, all this does is set the first value in the list as the default value. If I try to add model => model.Pendist or Model.Pendist as the third paramter in the DropDownListFor like this
#Html.DropDownListFor(model => model.Pendist,
(SelectList)ViewBag.Pendist, model => model.Pendist, new { onchange = "ChangeChannel()" })
I either get the following errors
(for model => model.Pendist)
Cannot convert lambda expression to type 'string' because it is not a delegate type
(for Model.Pendist)
'Model' confilcts with the declaration 'System.Web.Mcv.WebViewPage<TModel>.Model'
You are conflicting with the MVC ModelState. When creating Drow down lists, make sure that your property that holds the selected value is not named the same thing as your list of objects. Also, do not use a lambda for the default value, but rather just use the model item directly.
#Html.DropDownListFor(model => model.Pendist, (SelectList)ViewBag.PendistList,
Model.Pendist, new { onchange = "ChangeChannel()" })
I can do this easily using a TextBoxFor but how do I do it with an EditorFor?
I figured using the DataAnnotation [DataType(DataType.EmailAddress)] but that doesn't do it.
I don't quite understand what the DataType annotation actually does because it doesn't seem to do anything at all at first glance.
You can override the HTML Attributes, to which a browser will fallback to type='text' if they do not support it:
#Html.TextBoxFor(m => m.Email, new { #type = "email" })
it seems to be supported now.
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control", #type = "email" } })
The EditorFor helper method is somewhat limited out of the box and doesn't yet appear to support the HTML5 type="email" attribute.
Your options right now seem to be either using TextBoxFor or creating a custom template that will allow you to set the input's type attribute. Here's another thread that reviews some of the options for creating your own templates.
The DataAnnotation [DataType(DataType.EmailAddress)] is actually quite useful. It sets the id and name of your form field to email, which you can use with jQuery validation to show the user client-side validation messages. Applying the DataAnnotation to your model class also means that the email property on your model will be automatically validated on the server side. If you enable unobtrusive validation in your app, you get client- and servers-side validation almost for free.
As an addition to jortizromo's answer, you have now at least two options:
Specifying #type in the htmlAttributes parameter for method EditorFor() as in
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #type = "email" } })
Using the EmailAddress annotation attribute from System.ComponentModel.DataAnnotations namespace in the model class definition for the corresponding Email property and a simple call to method EditorFor() (this provides HTML validation data tags which could be a good or bad idea depending on your task) as in
ViewModel
[EmailAddress]
public string Email { get; set; }
Razor View
#Html.EditorFor(model => model.Email)