MVC Editor with data- attribute from model attribute - c#

I'm trying to build in form hinting for a web application.
The form hints are stored in the "Description" attribute of my ViewModel.
public class ViewModel{
[Description("Field description for input hints")]
public string Name {get;set;}
}
I need to be able to pass these through to my form controls "data-content" field.
<input data-content="Field description for input hints" name="Name" class="guidance"/>
I'm unable to just use a simple EditorFor as I can't add additional HTML fields to it.
If I create an editor template, I'd obviously need to access the model metadata. I'm unsure how to do this if I'm passing a null model?

Is this what you are looking for? Sorry for the conformation in the form of answer due to shortage of rep.
In JQuery can you add Attributes like below
$('Some ID').attr('your attr', 'Some Val')

you can use like this:
#Html.EditorFor(m => m.ColName, new { #class = "abc" })

Related

Get data-id value of textbox on form submit

I have a textbox set-up, like so:
#Html.TextBoxFor(m => m.NewVehCode, new {data_id = "" })
When a user selects a vehicle, the description of the vehicle becomes the value of the textbox and the vehicle code (which is what I want to send to DB) becomes the data-id (not full code but I set the values like this):
$("#NewVehCode").val(vehDescription);
$("#NewVehCode").attr("data-id", vehCode);
This all works fine, except for the fact that when I submit, MVC grabs the value of the textbox.
Is there a way I can on submit, get the data-id of that textbox instead of the value?
Note that I'm not using .js to gather the data. Form calls a controller action that sends the model directly to the controller.
There is no way to submit values of "data" properties. I am not sure why you wanted to use data property (is that a requirement or not, not sure). But you can have a hidden property in the form so, when user selects a vehicle, along with data property of text box , update this hidden value. This hidden value will be submitted back to form.
Stephen Muecke's comment helped me trigger this solution:
I've added a hidden textbox to use for the vehicle code, and made the textbox that shows the description a standard textbox with no data binding.
<input id="newVehInput" readonly="readonly" class="longInput" type="text">
#Html.TextBoxFor(m => m.NewVehCode, new { style = "display: none"})
This way I can use the value with no issues:
$("#newVehInput").val(vehDescription);
$("#NewVehCode").val(vehCode);
(Will mark as answer in 2 days)
Add a hidden textbox to your html which you post back on submit
In your model:
public string Id {get;set;}
Render it in the view with a hidden class
And with js.
$("#vehicleList").on("change",function(){
$("#Id").val($vehCode)
})
When you submit the value of id should be set in your model
You can have a hidden field hold the Updated value.
HTML:
<input type="hidden" id="HiddenVehCode" name="HiddenVehCode" Value="0"/>
JS
$("#HiddenVehCode").val(vehDescription);
Note: you should have the model set up so that HiddenVehCode will reach the actionMethod on Form Submit.Something Like,
public int HiddenVehCode {get;set;}

BeginForm() take complex input value into routing

I have a little problem with binding <input> value into routing of the beginForm GET action when submitting.
Firstly, the relevant code :
[Route("Company/{companyID:int}/MarketOffers/{PagingParam.PageNumber=1}")]
public ActionResult MarketOffers(int companyID, PagingParam pagingParam)
* This is declaration of action that I am dealing with. PagingParam have property PageNumber of int type.
#using (Html.BeginForm(RouteDataHelper.ActionName, RouteDataHelper.ControllerName, FormMethod.Get, new { companyID = Model.Info.CompanyID }))
* In the BeginForm I am only using companyID because PageNumber will vary depending on what the user clicks on the website and because of that it's not supplied here.
<input id="PagingParam.PageNumber" name="PagingParam.PageNumber" type="hidden" value="1">
* This is input which value should be appended to URL. It's inside the form which generation code you see above. The value changes by javascript just before submitting the form.
When I input link like :
http://localhost:38120/Company/2037/MarketOffers/3
* Everything is ok. PagingParam.PageNumber sets its value to 3. This is desired behaviour.
But when I submit the form with PagingParam.PageNumber input field then my URL looks like :
http://localhost:38120/Company/2037/MarketOffers?PagingParam.PageNumber=2
Instead of
http://localhost:38120/Company/2037/MarketOffers/2
I exactly know that I could deal with that and change form action value using javascript+JQuery but I have a feeling that there is a way to do this automatically in MVC without writing JavaScript.
So the question is : Can I do something to automatically generate desired link when I am passing form which action is (for example) "/Company/2037/MarketOffers" and append PagingParam.PageNumber to generated URL without writing JavaScript?
All inputs inside a form that make a GET have their values added as query string parameters because a browser has no knowledge of the routes on your server.
Its not possible to generate ../Company/2037/MarketOffers/3 without using javascript to modify the action attribute of the form

How to edit a CSS class in the MVC Layout view using C#

I'm wondering how I can change the class that is assigned to an element in the layout view from the C# code within the controller?
In my nav bar I have a css class that is set as active when viewing the page but obviously I need to change this when I change views (pages) but i'm not sure on the best way to do this within mvc
Attempt to bind CSS values to model or viewbag
for example
#Html.TextBoxFor(model => model.Value1, new { #class = ViewBag.value1Class })
or may be
<div class="#Model.Class1 #Model.Class2"/>
You can inspect the current controller name and action as detailed in this post and use that information in your layout to choose which element should be "active".
Or in a simple application another common way to do this is to use the ViewBag and set a property with the name of the current page.
In your controller method include the following.
ViewBag.CurrentPageName = "HomePage";
Your Razor (MVC3+) view code can consume this information and set the appropriate class on an element.
#{
string pageName = ViewBag.CurrentPageName ?? "Unknown";
}
if(pageName == "HomePage"){
//Output your DOM element with the appropriate class name for the "active" link.
}
OR
<a href="#" class="#(pageName == "HomePage" ? "active" : string.Empty)>Home Page</a>
For MVC2 and older you'll need to use TempData, but the concept is similar.
Use jquery maybe?
$( document ).ready(function() {
$("#mainPageDiv").removeClass()
.addClass('newClass');
});
Put this in view, not layout.

MVC get a form control data- attribute value in a post ActionResult

i'm trying to recreate something i did back in winforms days with html data- attributes in mvc.
you could set an attribute on a form control using this:
txtTest.Attributes.Add("data-myattribute", "my value");
and then read it back once the form had been posted using:
txtTest.Attributes["data-myattribute"]
adding the attributes in mvc is a breeze:
#Html.TextBoxFor(m => m.FirstName, new { data_myattribute = "my value" })
just can't figure out how to read them in the action result once the form has been posted?!
been searching around and whilst i can find loadsa posts on how to set data- attribute values and read them in javascript, i can't find anything that'll tell me how to get them back in the code...
anyone out there know the magic answer?!
Data attributes are not included in the data that's posted with the form, so there is no way to read them in your controller action. Try using a hidden field instead:
<input type="hidden" name="FirstNameAttribute" value="my value" />
This'll bind back to a model property:
public string FirstNameAttribute { get; set; }

How do I edit the CSS of the Html.DisplayFor method in MVC 3?

I am using the following code to display text from my view model in my view:
#Html.DisplayFor(m => m.Name)
When I look at the HTML details in IE9 (which I have to use at work) there is no class associated with the name, it just uses the Body CSS styling instead of the display-field class styling. Does anyone know what might be causing this issue or how I might edit the CSS for the text created?
if it is a label, use proper helper for it as Nataka526 suggests
otherwise put it in a span with a class and update css for that class:
your html:
<span class="name">
#Html.DisplayFor(m => m.Name)
</span>
your css:
.name {
//custom css
}
UPDATE
Another option:
Update your Display Templates to handle a specific ViewData key:
in Views > Shared > DisplayTemplate (create this folder if you don't have it already):
add file String.cshtml:
#model string
#{
string myClass = ViewData["class"]
}
#if(string.IsNullOrEmpty(myClass))
{
#:#Model
}
else
{
<span class="#myClass">#Model</span>
}
you may need to add DisplayTemplates for other tipes as well besides string.
In the view you will write something like this:
#Html.DisplayFor(m => m.Name, new { #class= "name" })
This will add spans around it automatically.
UPDATE
Explanation:
There is an overload on Html.DisplayFor which accepts two parameters: expression and object additionalViewData. So the second parameter that I pass is that anonymous object additionalViewData. I create this object with property called class
Inside of the html helper I then check if there is a ViewData with a key class and if there is, I put output inside a span with that class value.
**
updated variable name from class to myClass since "class" is not appropriate variable name.
DisplayFor is used for templating reasons. If you aren't using a template, then you should just use the item like so: #Model.Name If you want to give it a class or id, then you need to wrap it in a span or div.
Your problem is that you're using the wrong method to output data, and expecting it to do something else. There is no built-in way to output raw data with class names.
So your choices are, wrap the raw item in a container that you can apply the css to, or create a template to use for these, then specify the template name in the DisplayFor like so:
#Html.DisplayFor(m => m.Name, "NameTemplate")

Categories

Resources