This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Watermark for Textbox in MVC3
Im switching my HTML code from basic html to use html helpers and Html.TextBoxFor...
This is my old code
<input type="text" disabled="disabled" value="Phone" name="Phone" id="cust-cellphone" class="tonedDown" />
And this is the new version
#Html.TextBoxFor(x => x.Customer.Phone_Personal, new { #class = "text-adr-fld tonedDown", #value = "Phone", #disabled = "disabled" })
Everything is working fine, except that the Value property is gone. What I mean is that it's not showing as a default predefined value inside the textbox.
I read that you can use Placeholder, but it doesnt seem to work with IE9 (which is a requirement from my client).
So the question is, how do I add input Value property to the TextboxFor method that works with IE9?
Edit:
There might be a possible workaround somehow.
My original purpose with this is to display a "placeholder like value", ie a default value which shows what the user is supposed to type in the textbox. E.g. the textbox that handles phonenumber should display "Phone", until the user clicks and enters a value.
Does anyone know another way of doing this (except "placeholder" and "value")?
u can set the default value to your model, and then your piece of code will work, else you can try using
#Html.TextBox("Phone_Personal", "Phone", new { #class = "text-adr-fld tonedDown", #disabled = "disabled" }).
If u want to use TextBoxFor, then using
$(document).ready(function(){
$("#Phone_Personal").val("Phone"); // replace Phone_Personal with the ID of the textbox
});
I think you don't pass the model to View method :
return View(model);
Or,the model is null.
Related
I have a form with the autocomplete attribute set to off.
Inside this form, there is a hidden input element (generated using ASP.NET MVC's Html.HiddenFor() method, but, that should be irrelevant):
<input type="hidden" value="0" name="Status" id="Status" data-val-required="The Status field is required." data-val-number="The field Status must be a number." data-val="true">
When the form is submitted, this value is incremented by one and the model is returned to the view. If I write the status value to the page, I can see that the value was correctly incremented.
However, this hidden input field is always cached. It's never getting the correct value. I tried setting the autocomplete attribute directly on the input element, but without success.
How can I get this hidden field to get the correct value? I'd prefer not to use any Javascript.
Edit: Supplying more code...
Controller
//This code is being executed, and the status is being incremented.
shippingOrder.Status = (shippingOrder.Status != (int)OrderStatus.Closed) ? shippingOrder.Status + 1 : shippingOrder.Status;
View
#using (Html.BeginForm("Number", "Order", FormMethod.Post, new { id = "orderSummary", autocomplete = "off" })) {
...
#Html.HiddenFor(m => m.Status)
}
According to this post here html helpers such as HiddenFor will always first use the posted value and after that the value in the model.
As you said, when writing the value to the page you can see it incremented, yet the helper is using the previously posted value, which is the intended behaviour.
The link does suggest the use of ModelState.Remove("Status") or ModelState.Clear() before assigning the new value.
It also suggest that another option could be not using a HiddenFor helper but instead to build the hidden field yourself. Similar to this:
<input type="hidden" name="Status" value="#Model.Status" />
Either way it looks like your problem is based on similar circumstances.
I am using html.textbox for 2 of my datetime field because I need to format them in a specific format but i don't know how to do it by html.textboxfor.
However, I realise i need to have the textboxfor for the validation in my model class to work:
[Required(ErrorMessage = "Storage Date is required")]
[DataType(DataType.DateTime, ErrorMessage = "Please input a valid date")]
public DateTime StorageDate { get; set; }
Any idea how can I change my Html.Textbox below into Html.TextBoxFor with the same setting??
#Html.TextBox("expirydate", String.Format("{0:ddd, d MMM yyyy}", DateTime.Now), new { id = "expirydate" })
#Html.ValidationMessageFor(model => model.ExpiryDate)
Appreciate any help... Thanks...
You don't really need to use TextBoxFor() for validation to work. If your TextBox has the same id as a field in the model, the model binder will pick it up. If you're talking about to get the unobtrusive validation features, you can always manually add the data-* attributes to your TextBox.
However, in this case it sounds like what you really want is a custom editor, using EditorFor(). It's a bit more work, but it will allow you to actually enforce the date/time formatting by giving the user something like a date/time picker control. The basic idea is:
Create a partial view called DateTime.cshtml that is bound to model of type Nullable<DateTime>, and put it into the Shared/EditorTemplates view folder.
Use jQuery and jQueryUI to put an HTML textbox that is styled as a date/time picker into the partial view.
Decorate the property on your model with the [DataType(DataType.DateTime)] attribute
Use Html.EditorFor(model => model.WhateverProperty)
Fortunately, date/time pickers are probably the most popular custom MVC3 editor, so there are plenty of examples to pick from; the code from this question works fine, just make sure to note the suggestion in the answer and replace this line in the partial view:
#inherits System.Web.Mvc.WebViewPage<System.DateTime>
with this:
#model System.DateTime?
I have an controller which has check like that
if (form["submit"].ToString() == "Continue")
{
}
and i have button which is doing submit
<button name="submit" value="Continue">Continue</button>
It was all working well until i decided to disable Continue button on submit to prevent double click using this function:
$('form').submit(function () {
if ($(this).valid()) {
$(':submit', this).attr('disabled', 'disabled');
}
});
So now i don't get value form["submit"] posted on controller.
Any thoughts how may i fix that?
I want still prevent second click but be able to get form["submit"] value posted on controller.
Can you control the submit value in a hidden field in the form? I can't tell what other logic you might need, but when the form renders, you could set the hidden field's value to the submit button's value and change it when necessary using the first script below. As long as it has a name attribute and is enabled (which you'd rarely disable a hidden field) then it will post when the form is submitted.
$(function() {
// this assumes your button has id="myButton" attribute
$(':hidden[name="submit"]').val($('#myButton').val());
});
And of course in your form, you would need a hidden field with name="submit"
<input type="hidden" name="submit" value="Continue" />
Then, whenever the state of your form changes, modify the disabled state of the button and the value of the hidden field to reflect the value (if it changed at all).
There are also frameworks you may find useful for UI features like this. KnockoutJS comes to mind. It can be used to "value" bind input elements. It's probably overkill for this small example, but it could be useful if your UI expands. I've added markup, script and comments below if you're interested.
$(function () {
var viewModel = {
submitValue: ko.observable("Continue")
};
ko.applyBindings(viewModel);
$('form').submit(function() {
if($(this).valid()) {
// the following line will change the both the hidden field's value
// as well as the button's value attribute
viewModel.submitValue("some other value");
// I couldn't follow your selector here, but please note I changed
// the name of the submit button in the markup below.
$(':submit, this).attr('disabled', 'disabled');
}
});
});
KnockoutJS requires you use the data-bind attribute to setup your elements. In your case, you'd bind one property to multiple elements like this:
<button name="submitButton" data-bind="value: submitValue"/>Continue</button>
<!-- and bind the same value similarly in the hidden field-->
<input type="hidden" name="submit" data-bind="value: submitValue"/>
i have been playing around with MVC. I am currently stumped on with html helper methods. One thing i have noticed is that I cant really cant apply the ASP.NET Web Form logic into MVC. To explain further, in ASP.NET I could create a Label control and assign it some text data and then read the text data.
However, in MVC, I cant seem to do the same with #Html.LabelFor/#Html.Label, I have realised that once you do a POST from your form, the value from the Label is not bound back into my view model. However, if I use an EditorFor or TextBoxFor, I can get values bound to my viewmodel upon POST.
My question what html hlper method should I use to display text as readonly but yet be able to bind back to my viewmodel upon post ? I have tried TextBoxFor with its html attributes set to disabled and readonly but no luck.
Appreciate any pointers.
thanks
You should be able to bind the readonly attribute to the TextBox by passing in htmlAttributes as the 2nd parameter of the TextBoxFor method:
<%=Html.TextBoxFor(m => m.SomeProperty, new { #readonly = "readonly" }) %>
On MSDN: InputExtensions.TextBoxFor Method (HtmlHelper, Expression>, Object)
If you're trying to maintain the Label value you can use a combination of the LabelFor and HiddenFor methods.
I don't know why you would need to do this though, since you should be able to get the DisplayText attribute or the Property Name from the property.
<%=Html.LabelFor(m => m.SomeProperty) %>
<%=Html.HiddenFor(m => m.SomeProperty) %>
but this doesn't make a lot of sense since the usual syntax would be:
<%=Html.LabelFor(m => m.SomeProperty) %>
<%=Html.TextBoxFor(m => m.SomeProperty) %>
Note that if you use the disabled attribute the input will not be posted when the form is submitted
This is expected behaviour, only values form elements are added to your Model on POST so your label will be ignored. To get around this duplicate your label value in a hidden field
Html.HiddenFor(model => model.FieldName)
or
Html.Hidden("FieldName", model.FieldName)
Good evening everyone I have a question regarding validation of drop-down list values. I have a view that is bound to a view model type called ReservationData.
This object contains a property CustomerVehicles of type List<VehicleData>. VehicleData has two int properties VehicleMakeId and VehicleModelId.
On my view I am trying to loop over the number of items in the CustomerVehicles collection and displaying two dropdowns for each, a vehicle make dropdown and a vehicle model dropdown using DropDownListFor.
When I try to submit and validate I do not see any validation errors displayed on the screen.
Just in case you are wondering I have added a ValidationMessageFor for each dropdown as well. I am not sure if this is an issue with the structure of my view model and its complexity and how the controls need to be named or how the ids need to be set. Any help would be greatly appreciated.
Here is the code for the looping over the collection:
#for (var i = 0; i < Model.CustomerVehicles.Count(); i++)
{
var vehicleNumber = i + 1;
<div class="vehicle-selection-wrapper">
<div class="content-container">
<h3>
Vehicle #vehicleNumber</h3>
<img class="vehicle-image" alt="manufacturer image" src="#Url.Content("~/Content/images/default-vehicle.gif")" /><br />
#Html.LabelFor(m => m.CustomerVehicles[i].VehicleMakeId)
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
, new SelectList(Model.VehicleMakes, "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption, new { #class = "long-field" })<br />
#Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleMakeId)<br />
#Html.LabelFor(m => m.CustomerVehicles[i].VehicleModelId)
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleModelId
, new SelectList(new List<CWR.Domain.VehicleModel>(), "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption, new { #class = "long-field" })
#Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleModelId)
</div>
</div>
}
Ok so I also noticed that in the generated HTML the selects that are generated are missing the HTML5 data-val attributes that are associated to elements to handle validation. Here is the generated HTML
<select class="long-field" id="CustomerVehicles_0__VehicleMakeId" name="CustomerVehicles[0].VehicleMakeId"><option value="">-- Select --</option>
</select><br />
<span class="field-validation-valid" data-valmsg- for="CustomerVehicles[0].VehicleMakeId" data-valmsg-replace="true"></span><br />
<label for="CustomerVehicles_0__VehicleModelId">Model</label>
<select class="long-field" id="CustomerVehicles_0__VehicleModelId" name="CustomerVehicles[0].VehicleModelId"><option value="">-- Select --</option>
</select>
<span class="field-validation-valid" data-valmsg-for="CustomerVehicles[0].VehicleModelId" data-valmsg-replace="true"></span>
Additionally in my VehicleData class the VehicleMakeId and VehicleModelId properties are decorated with a Required attribute.
UPDATE:
Ok so I was testing and noticed that if I keep my code identical except I swap the Html.DropdownListFor calls with Html.TextboxFor calls then the validation works. What could be causing this? Could it be a framework bug with the unobtrusive validation?
UPDATE: Contains Fix
So after posting this same question on the ASP.NET Forums, I was able to get a solution. In the post you will be able to see that there is a bug in the unobtrusive validation framework and how it handles validation of dropdownlists. The user counsellorben does a good job in explaining the problem as well as a solution (including sample code) that will assist others in avoiding this issue in the future, or at least until Microsoft builds in a fix in to the framework.
Thank you everyone for your assistance.
I too have come across this obviously massive oversight regarding client side validation with dropdownlists in MVC 3 and the best solution I can offer is to put the missing HMTL attributes in yourself.
In your view model create a property like this.
public Dictionary<string, object> CustomerVechicleAttributes
{
get
{
Dictionary<string, object> d = new Dictionary<string, object>();
d.Add("data-val", "true");
d.Add("data-val-required", "Please select a Vechicle.");
return d;
}
}
Then in your code, enter
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
, new SelectList(Model.VehicleMakes, "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption,
**Model.CustomerVechicleAttributes** })
Just add the Model.CustomerVechicleAttributes as htmlAttributes to your dropdownlist.
This will inject the necessary attributes that are missing. You will of course need to add any other attributes you may need like your class attribute.
Hope this helps.
This is the simpliest way I found to do it, just adding data-val-*-* attributes in HtmlAttributes of DropDownListFor, inside the view. The following method works with RemoteValidation too, if you do not need remote validation, simply remove the elements containing data-val-remote-*:
#Html.DropDownListFor(m => m.yourlistID, (IEnumerable<SelectListItem>)ViewBag.YourListID, String.Empty,
new Dictionary<string, object>() { { "data-val", "true" },
{ "data-val-remote-url", "/Validation/yourremoteval" },
{ "data-val-remote-type", "POST" }, { "data-val-remote-additionalfield", "youradditionalfieldtovalidate" } })
I hope it may help. Best Regards!
you should try to add data annotations on your view model properties first so you could see the validation messages.
you might find what you need here
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx
or create custom ones if needed.
what exactly do you need to validate?
I had exactly the same problem with the field getting correctly validated in TextBoxFor but not in DropDownListFor.
#Html.DropDownListFor(m => m.PaymentTO.CreditCardType, Model.CreditCardTypeList, "Select Card Type", new { style = "width:150px;" })
Since I had another DropDownListFor working on the same page, I knew that it wasn’t a generic DropDownListFor problem. I also have a complex model and parent object PaymentTO wasn’t initialized. When I set viewTO.PaymentTO = new PaymentTO(); in the Controller, the validation for the DropDownListFor started to work. So there is probably a problem with DropDownListFor, but the fix can be as simple as initializing the object in the controller.