I'm trying to add a required to my TextAreaFor, but it won't give the error message when i post it. I'm trying to do it on the followinng line:
#Html.TextAreaFor(model => model.Content, new { htmlAttributes = new { #class = "form-control", required = "" } })
And this is my full code:
#using (Html.BeginForm("_Create", "Comments", FormMethod.Post))
{
#Html.HiddenFor(m => m.ThreadId)
<div class="form-group">
<div class="col-md-10">
#Html.TextAreaFor(model => model.Content, new { htmlAttributes = new { #class = "form-control", required = "" } })
#Html.ValidationMessageFor(model => model.Content, "", new { #class = "text-danger"})
</div>
</div>
<div class="form-group">
<div>
<input type="submit" value="Post" class="btn btn-default" />
</div>
</div>
}
If anyone wanst to do it with html attribute,
#Html.TextAreaFor(model => model.Content, new { required = "required", htmlAttributes = new { #class = "form-control"} })
You don't need required as a html attribute. It should be a data annotation on the model.
[Required]
public string Content { get; set; }
#Html.TextAreaFor(model => model.Content, new { htmlAttributes = new { #class = "form-control", required = "" } })
Should be:
#Html.TextAreaFor(model => model.Content, new { #class = "form-control", required = "required" })
Or if you want to explicitly name the parameter your anonymous object is for:
#Html.TextAreaFor(model => model.Content, htmlAttributes: new { #class = "form-control", required = "" } })
But, if you do not use data-annotation, it could be even easier this way:
<textarea id="Content" name="Content" required class="form-control">#Model.Content</textarea>
(id attribute may be optional, depending on your usages.)
Side note: I tend to minimize uses of html helpers methods. For me, MVC is also about letting you control very precisely the browser client code, which is imo better done by writing it yourself. WebForm is, on this subject, about hiding most of browser client code handling.
Using extensively html helpers, built-in validation logic, and so on, may cause you to lose the precise control of how your page should work.
Related
I would like to autofocus on an editorfor in my application, but I can't seem to do that. I have successfully used autofocus on a textbox, but I would like to use an editorfor to keep my application's look universal.
Any solutions to this would be much appreciated, thank you.
My attempt:
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control" }, autofocus = "" })
This s because you are using EditorFor instead of something specific like TextBoxFor.
#Html.TextBoxFor(model => model.Name, new { htmlAttributes = new {
#class = "form-control" }, autofocus="autofocus"})
Or you can do that using jQuery:
<div class="editor-field focus">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
$(function() {
$('.focus :input').focus();
});
Update:
As you know TextBoxFor always creates a textbox with type input, But EditorFor is a little bit smart, it renders markup based on the datatype of the property.
Using .Net Framework 4.5 and MVC 5, this works for me:
#Html.EditorFor(model => model.Description, new {
htmlAttributes = new {
#class = "form-control",
autofocus = true
}
})
You put the autofocus attribute in the wrong spot.
#Html.EditorFor(model => model.Description,
new { htmlAttributes = new { #class = "form-control" }, autofocus = "" })
Try this instead:
#Html.EditorFor(model => model.Description,
new { htmlAttributes = new { #class = "form-control", autofocus = "" } })
I've been following this thread and I may have stumbled on an answer to your question about autofocus on EditorFor - this is all Asp.Net 4.5 and MVC 5, not that it matters.
In the Scripts folder I have a jQuery script file:
$(function(){
$('.someclassname').focus();
});
I add the script name to the BundleConfig and render it in the view.
In the view I add the classname to the EditorFor <div class="col-md-10" someclassname">
I then add the type="text" autofocus="autofocus" to the EditorFor's #class. So, new{#class="form-control", type="text", autofocus="autofocus"
That's pretty much it, when the DOM loads the .someclassname field gets the cursor focus...
PS. In fact if you just do (3) it works also...
I have a text area where users have to write a description. I was wondering how to set a text box so that it is on multiple lines, allowing the user to see what they are writing. What I am looking for is similar to the environment that I am writing this question in.
<div class="form-group">
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
In your model you need to add MultilineText as below:
[DataType(DataType.MultilineText)]
public string Title { get; set; }
Or you code have just changed the EditorFor to TextAreaFor like Below
#Html.TextAreaFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
I have a disabled input-field displaying data from a model.
<div class="form-group">
#Html.LabelFor(model => model.first_name, "Förnamn", new
{
#for = "inputFirstname",
#class = "col-lg-3 control-label"
})
<div class="col-lg-9">
#Html.TextBoxFor(model => model.first_name, new
{
#type = "text",
#class = "form-control",
#id = "inputFirstname",
text = Html.DisplayNameFor(model => model.first_name),
disabled="disabled"
})
</div>
</div>
I can submit this data to a controlelr method:
[HttpPost]
public ActionResult Index(RegistrationModel RegistrationModelViewModel)
{}
When i add disabled="disabled" the first_name data is null, if i remove it i get the correct data.
What am i doing wrong?
You may want to use readonly property, if you want to also display the data:
#Html.TextBoxFor(model => model.first_name, new
{
#readonly = "readonly"
})
You need to add an <input type="hidden" name="whateverName" /> on the page which matches the disabled field. By default, it will not be sent to the server.
I'm trying to create a helper that will make my form controls in the whole website
Here is what i use till now
#helper editorField(System.Linq.Expressions.Expression<Func<Model, String>> o)
{
<div class="form-group">
#Html.LabelFor(o, new { #class = "col-md-4 control-label" })
#Html.ValidationMessageFor(o, "", new { #class = "col-md-6 col-xs-12 text-errer" })
<div class="col-md-5">
#Html.TextBoxFor(o, new { #class = "form-control" })
</div>
</div>
}
And the way i use it is
#editorField(model => model.Name)
#editorField(model => model.Email)
#editorField(model => model.PhoneNumber)
this make it really easy to change the style and layout of the whole website in 1 place
Now here is the problem
I need to make helper for each Model and data type
Im looking for a way to make it work something like this
#helper editorField(object o)
{
<div class="form-group">
#Html.LabelFor(o, new { #class = "col-md-4 control-label" })
#Html.ValidationMessageFor(o, "", new { #class = "col-md-6 col-xs-12 text-errer" })
<div class="col-md-5">
#Html.TextBoxFor(o, new { #class = "form-control" })
</div>
</div>
}
and it should work for all Models and datatypes
So basically what you are trying to achieve is a generic HTML helper. Unfortunately those are not supported directly in Razor views. But, you can use this workaround:
#functions
{
public HelperResult PasteEditorFor<TModel, TItem>(HtmlHelper<TModel> html, Expression<Func<TModel, TItem>> expr)
{
return editorField(
html.LabelFor(expr, new { #class = "col-md-4 control-label" }),
html.ValidationMessageFor(expr, "", new { #class = "col-md-6 col-xs-12 text-errer" }),
html.TextBoxFor(expr, new { #class = "form-control" }));
}
}
#helper editorField(MvcHtmlString label, MvcHtmlString validationMessage, MvcHtmlString textBox)
{
<div class="form-group">
#label
#validationMessage
<div class="col-md-5">
#textBox
</div>
</div>
}
// usage sample
#PasteEditorFor(Html, m => m.LongDescription)
But as it is still not easy reusable (can't tell at the moment how to make it visible though all views), so I would recommend you to write usual HtmlHelper with usual static class syntax ( look at Alundra the dreamwalker comment) and add it's namespace to list of default one in WebConfig.
I found some similar posts to mine, but I couldn't find an answer that suits my needs for this.
Problem is as follows:
I have a viewmodel like this:
public class PrefViewModel
{
public SelectList countries { get; set; }
public SelectList Provincies { get; set; }
public ApplicationUser user { get; set; }
public Preference MyPref{ get; set; }
public int mycountry { get; set; }
public int myprovince { get; set; }
}
my cshtml looks like this:
#using (Html.BeginForm("Index","Preferences", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(model => model.user.UserName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
<span class="textvak">
#Html.TextBoxFor(model => model.user.UserName, new { disabled = "disabled", #readonly = "readonly" })
</span>
#Html.ValidationMessageFor(model => model.user.UserName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
<span class="textvak">
#Html.TextBoxFor(model => model.user.Email, new { disabled = "disabled", #readonly = "readonly" })
</span>
#Html.ValidationMessageFor(model => model.user.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Unhashed, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.user.Unhashed, new { htmlAttributes = new { #class = "form-control", type = "password" } })
#Html.ValidationMessageFor(model => model.user.Unhashed, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Provincie.Land, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
#Html.DropDownListFor(model => model.mycountry, Model.countries, new { Name = "ddlLand", id = "ddlLanden", #class = "textvak" })
#Html.ValidationMessageFor(model => model.user.Provincie.Land, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.user.Provincie, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="control-label col-md-10">
#Html.DropDownListFor(model => model.myprovince, Model.Provincies, new { #class = "textvak" })
#Html.ValidationMessageFor(model => model.user.Provincie, "", new { #class = "text-danger" })
</div>
</div>
<br />
<table>
<tr>
<td>
<input type="submit" value=#Resources.Wijzig class="btn btn-default" />
</td>
</tr>
</table>
}
and in my controller I try to get the posted PrefViewModel back as follows:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(PrefViewModel TestMymodel)
{
if (ModelState.IsValid)
{
int myCountry = TestMymodel.mycountry;
int myprovince = TestMymodel.myprovince;
}
return View();
}
My problem is that the PrefViewModel TestMymodel never is filled with the values I thought i'm posting back. Even more strange to me is the fact that I do get the Unhashed password back, but all other values are 0 or null.
I can put values inside the PrefViewModel to load the page and that works, but on Posting it's almost entirely empty.
Any ideas?
edit: Would it make any difference that I did change the default model to one that I made up myself? Cause when I Call the Create action for example, I do get the values back in my post (from create offcourse). I'm getting a bit desperate
edit2: this is what was posted:
__RequestVerificationToken:-JYcw0CH2zZ7WrGUiYJM6-R6VxfL41ykTD5EHUjgtyyFcN01AaUU61BYuaRNr4oPdEvDq09aYsOFdb8fObJTXMnTKulADVkGY8CrBG3U71QXw0g7Th86WKl1up4059Zy7mW0SlrWGJpehed586v_5g2
user.Unhashed:Jonas1234-
user.Unhashed:Jonas1234-
ddlLand:1
ddlProvincie:3
(can't add picture with my reputation, so here a link to the full post: http://postimg.org/image/id95wjcxp/ )
Ok, when I change the name of the dropdownlists to the PrefViewModel property name those values get returned correct.
It appears that you have overriden the names of the drop down lists to some values which are different than the property names in your view model. That's why the values are not successfully bound back. Make sure that your input fields respect the same names as the properties on your view model if you want the default model binder to be able to bind them back to the view model.
Also your username textbox has the disabled flag:
#Html.TextBoxFor(model => model.user.UserName, new { disabled = "disabled", #readonly = "readonly" })
so it will not be submitted back to the server. You might need to add an additional hidden field if you want those values to travel back. Or simply use readonly without disabled attribute. Both attributes prevent the user from modifying the value in the corresponding input field but in addition to that the disabled attribute strips it from the POST payload when the form is submitted.
So you may use:
#Html.TextBoxFor(model => model.user.UserName, new { #readonly = "readonly" })