Display dynamic title for dropdown listitem using razor - asp.net-mvc

I have one dropdown in my MVC application.
I have a field in my model:
public IList<SexGenderModel> SexualOrientationList { get; set; }
class for SexGenderModel:
public class SexGenderModel
{
public int? MasterID { get; set; }
public string CodeDescription { get; set; }
public string SNOMED { get; set; }
}
In my view page I have used razor syntax
#Html.DropDownListFor(x => x.SexualOrientationList, new SelectList(Model.SexualOrientationList, "MasterID", "CodeDescription"), "--Select--", new { #class = "form-control input-sm"})
Every list item has their own SNOMED which I want to display in tooltip.
Please note I want to display tooltip for ListItem not for selected item of dropdown.
How can I achieve this with razor?
Any other option to map attributes to dropdownlist(Model.SexualOrientationList) from backend? How?

All you need to add attribute "title" to each item in dropdown
<select>
#foreach (var item in Model.SexualOrientationList)
{
<option title='#item.SNOMED' value="#item.MasterID">#item.CodeDescription</option>
}
</select>

Going further with #Khaled-Yosry 's answer:
#Ankita this DOES use Razor, so I'm not sure why you find yourself restricted.
If it's the <select> tag rendering you are worried about, you can append the necessary tags yourself:
All you need to add attribute "title" to each item in dropdown
<select name="#Html.NameFor(m => m.SexualOrientation)" id="#Html.IdFor(m => m.SexualOrientation)" class="form-control input-sm">
<option value="">--Select one--</option>
#foreach (var item in Model.SexualOrientationList)
{
<option title="#item.SNOMED" value="#item.MasterID" #(Model.SexualOrientation == item.MasterID ? "selected" : string.empty)>#item.CodeDescription</option>
}
</select>
Also, don't forget to include a property in your Model which will actually be bound to the selected value of the dropdown list:
public int SexualOrientation { get; set; }

Related

razor MVC Only the first element has been added to the controller?

I have the following code, When I select multiple departments, it's showing correctly in the front end,
but when it's passed to the back end only the first one has been selected, any idea?
<div class="form-control-container">
<select class="form-control " asp-for="Actioned_DepartmentName" asp-items="Model.Departments" multiple>
<option value="">Please select department(s)...</option>
</select>
</div>
public class ActionedReportRequestDto
{
public DateTime From { get; set; }
public DateTime To { get; set; }
public List<DepartmentType?> DepartmentName { get; set; }
}
Thanks just find out cannot pass a list of enum type, it will always select the first one, change it to list of string and split it works fine!

Unable to set value in dropdownlist

I have a dropdownlist,while editing i need to set the current value.But my codes are not working.
My view look like follow
#Html.DropDownListFor(m => m.id, Model.ddls, "Please Select", new { #class = "form-control" })
Model
public string id { get; set; }
public List<SelectListItem> ddls { get; set; }
Controller
public IActionResult editmaster(string id, string sec)
{
master m = new master();//here is my model
m.ddls = PopulateDDLDataSet(ds.Tables[1], "companyname", "companyid");//ddls is my object and populateddldataset is my methode to fill the list
return View(m);
}
ddls is the selectedlistitems that i have filled from controller,that work fine.But the value which in in id not set on the list
Checked the code and its working for me. Could you provide more details about your model?
Wanted to say that you can make similar things by using built-in razor tag helpers that is more clear.
Documentation for select
Example of using tag helper in your code:
<select class="form-control" asp-for="#Model.id" asp-items="Model.ddls">
<option selected>Please select</option>
</select>
please follow this, it may be this code help you.
Model Code
public class testmdl
{
public string id { get; set; }
public IEnumerable<SelectListItem> ddls { get; set; }
}
Controller Code
//------ without using entity for select list items
public IActionResult Test()
{
testmdl obj=new testmdl();
IEnumerable<SelectListItem> companyList = new List<SelectListItem>
{
new SelectListItem { Value = "001", Text = "StackOverflow1" },
new SelectListItem { Value = "002", Text = "StackOverflow2" }
};
obj.ddls =companyList ;
return View(obj);
}
//--- using entity framework for select list items
public IActionResult Test()
{
testmdl obj=new testmdl();
List<SelectListItem> companyList = new SelectList(db.yourcompanytable, "companyid", "comapnyname").ToList();
obj.ddls =companyList ;
return View(obj);
}
View Code
<select id="id1" name="id1" asp-for="id" asp-items="#Model.ddls" class="form-control">
<option value=#null>--- Select --- </option>
</select>
<span asp-validation-for="id" style="color:red;"></span>
In my case none of the above answers work(I don't clearly understand what went wrong for me) ,but finally i achieved in an alternative way.Below my codes.Thanks for all the supports.
<script>
document.getElementById("id").value =#Model.id;
</script>
Put this after binding the dropdownlist.

ASP.net MVC Html.RadioButtonFor Grouping within Html.DisplayFor

I'm having an issue getting a dynamic set of radio buttons (driven by a CMS) working with Model binding.
So far I've gotten the radios to render, but they behave more like checkboxes, which I believe is down to the name atribute on the input being different. I had thought I'd resolved this by using a parent id to group them, but that doesn't work. On save I want to bind the state (checked / not checked) to the IsSelected property on my Option model. If I pass in a name attribute as part of the RadioButtonFor I can get the radio to work as a group but lose the model binding.
I'm using the same setup with a different Display template for checkboxes which works fine, not sure where I'm going wrong here. Anyone get any suggestions?
Models
public class Question
{
public int QuestionId { get; set; } // 1044
public string QuestionText { get; set; } // Whats your favourite colour
public HelpText HelpText { get; set; }
public IEnumerable<Option> Options { get; set; } // colours
}
public class Option
{
public int OptionId { get; set; } //
public int ParentId { get; set; } // Set as QuestionId for radio button grouping :: 1044
public string Label { get; set; }
public string Value { get; set; }
public bool IsSelected { get; set; }
}
public class RadioOption : Option {} // derived classes to drive DisplayFor template matching
public class CheckboxOption : Option {}
Views
Simplified partial view, which is passed the Question model and is looping through all the options and rendering a display template
<fieldset>
#Html.DisplayFor(x => x.Options)
</fieldset>
Radio button Display Template
#model ViewModels.RadioOption
#Html.RadioButtonFor(m => m.ParentId, Model.Label, Model.OptionId)
#Html.LabelFor(m => m.ParentId, Model.Label)
#Html.HiddenFor(m => m.Value)
#Html.HiddenFor(m => m.OptionId)
#Html.HiddenFor(m => m.Label)
#Html.HiddenFor(m => m.ParentId)
Rendered HTML
<fieldset>
<input id="Questions_5__Options_0__ParentId" name="Questions[5].Options[0].ParentId" type="radio" value="Red">
<label for="Questions_5__Options_0__ParentId">Red</label>
<input id="Questions_5__Options_1__ParentId" name="Questions[5].Options[1].ParentId" type="radio" value="Green">
<label for="Questions_5__Options_1__ParentId">Green</label>
<input id="Questions_5__Options_2__ParentId" name="Questions[5].Options[2].ParentId" type="radio" value="Blue">
<label for="Questions_5__Options_2__ParentId">Blue</label>
<input id="Questions_5__Options_3__ParentId" name="Questions[5].Options[3].ParentId" type="radio" value="Yellow">
<label for="Questions_5__Options_3__ParentId">Yellow</label>
</fieldset>

Mapping a list of string key-value pairs with Razor / form post

I have some HTML in my Razor view that is basically 3 rows of a pair of Select and Input elements:
(There could be more than 3)
<select name="SocialNetwork[1]">
<option>Skype</option>
<option>Twitter</option>
<option>Facebook</option>
</select>
<input name="SocialNetworkUsername[1]" type="text" />
<select name="SocialNetwork[2]">
<option>Skype</option>
<option>Twitter</option>
<option>Facebook</option>
</select>
<input name="SocialNetworkUsername[2]" type="text" />
<select name="SocialNetwork[3]">
<option>Skype</option>
<option>Twitter</option>
<option>Facebook</option>
</select>
<input name="SocialNetworkUsername[3]" type="text" />
When the form is posted to my controller method:
public ActionResult SaveDetails(MyModel model)
{
}
How can I 'map' the values of SocialNetwork | SocialNetworkUsername to a model?
Something like:
public class MyModel
{
public string SomeProperty { get; set; }
public string SomeOtherProperty { get; set; }
public Dictionary<string,string> SocialNetworks { get; set; }
}
I'm not 'stuck' using a dictionary if there is something more appropriate
You can use an editor template to achieve this.
the editor template will allow you to loop through a list of social networks in your main view and use the #Html.EditorFor helper to render out your dropdown lists and make model binding easy.
To start with your model should represent a single Social Network
In your model you need properties to contain the dropdown list values, and a property for the selected value. You'll also need a property to contain the SocialNetworkUsername
public IEnumerable<SelectListItem> SocialNetworks { get; set; }
public string SelectedSocialNetwork { get; set; }
public string SocialNetworkUserName { get; set; }
To make your editor template add a new folder /Views/Shared/EditorTemplates
In the EditorTemplates folder create a new view with the name MyClass (or whatever your model class name is)
You need to follow these naming conventions as there is no other configuration required for the editor template to work.
In MyClass.cshtml you need to allow editing of a single social network
#model MyModel
#Html.DropDownListFor(m => m.SelectedSocialNetwork, Model.SocialNetworks)
#Html.TextBoxFor(m => m.SocialNetworkUserName)
Then in your main view you use a List of MyModel as the model for the view and use a for loop to render out your editor templates.
#model List<MyModel>
#using(Html.BeginForm())
{
for (var i = 0; i < Model.Count; i++)
{
Html.EditorFor(Model[i])
}
}
In your controller just change your action method parameter to accept a List of MyClass and model binding should just magically work ;)

Knockout.js bind array of objects to repeated <select>'s

I've got this Knockout.js view model:
{
"LanguageFromTos":
[{
"LanguageFromToId":0,
"LanguageFromId":2,
"LanguageFrom":null,
"AllLanguagesFrom":[
{"Selected":false,"Text":"English","Value":"1"},
{"Selected":false,"Text":"French","Value":"2"},
{"Selected":false,"Text":"Spanish","Value":"3"}
],
"LanguageToId":1,
"LanguageTo":null,
"AllLanguagesTo":[
{"Selected":false,"Text":"English","Value":"1"},
{"Selected":false,"Text":"French","Value":"2"},
{"Selected":false,"Text":"Spanish","Value":"3"}
],
"Users":null
}]
}
And these html <select>s:
<div class="LanguageFromToRow">
<input type="hidden" name="languageFromTos.index" autocomplete="off" value="c50532b0-65d2-4a81-baeb-59b768fd120f" />
<label for="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageFromId">From</label>:
<select data-bind="???" data-val="true" data-val-number="The field From must be a number." data-val-required="The From field is required." id="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageFromId" name="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageFromId">
<option value="1">English</option>
<option selected="selected" value="2">French</option>
<option value="3">Spanish</option>
</select>
<span class="field-validation-valid" data-valmsg-for="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageFromId" data-valmsg-replace="true"></span>
<label for="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageToId">To</label>:
<select data-bind="???" data-val="true" data-val-number="The field To must be a number." data-val-required="The To field is required." id="languageFromTos_c50532b0-65d2-4a81-baeb-59b768fd120f__LanguageToId" name="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageToId">
<option selected="selected" value="1">English</option>
<option value="2">French</option>
<option value="3">Spanish</option>
</select>
<span class="field-validation-valid" data-valmsg-for="languageFromTos[c50532b0-65d2-4a81-baeb-59b768fd120f].LanguageToId" data-valmsg-replace="true"></span>
delete
</div>
Can anyone tell me what I need to add to the data-bind attributes of each select to tie them up to the Knockout.js view model? The value of the first select should be bound to LanguageFromId in the view model and the value of the second select should be bound to LanguageToId in the view model.
LanguageFromTos in the view model is an array, so all of what you see inside may be repeated (2 LanguageFromTos would result in the LanguageFromToRow div being repeated twice, for example). The number of repeats is set both server-side (data posted by the controller may have multiple LanguageFromTos) and client-side (an 'add' button that allows the user to add another div with its contained selects) in different cases, so I presume Knockout's templating is a no-go as MVC needs to loop through and render each row so that it can catch them all on a 'normal' post back.
Any help much appreciated!
Edit
Here's the MVC model for the page:
public class DirectorySearchModel
{
[Display(Name = "User name contains")]
public string UserName { get; set; }
[Display(Name = "First name contains")]
public string FirstName { get; set; }
[Display(Name = "Last name contains")]
public string LastName { get; set; }
[Display(Name = "Languages translated")]
public IEnumerable<LanguageFromTo> LanguageFromTos { get; set; }
}
Here's the LanguageFromTo object:
public class LanguageFromTo
{
[Key]
public virtual int LanguageFromToId { get; set; }
[Display(Name = "From")]
public virtual int LanguageFromId { get; set; }
[ForeignKey("LanguageFromId")]
public virtual Language LanguageFrom { get; set; }
public virtual IEnumerable<SelectListItem> AllLanguagesFrom { get; set; }
[Display(Name = "To")]
public virtual int LanguageToId { get; set; }
[ForeignKey("LanguageToId")]
public virtual Language LanguageTo { get; set; }
public virtual IEnumerable<SelectListItem> AllLanguagesTo { get; set; }
public virtual ICollection<User> Users { get; set; }
}
And here's the cshtml code for the MVC view. This code sits in a partial that's repeated depending on how many LanguageFromTos there are in DirectorySearchModel that's passed to the MVC view:
<div class="LanguageFromToRow">
#using(Html.BeginCollectionItem("languageFromTos")) {
#: #Html.LabelFor(m => m.LanguageFromId): #Html.DropDownListFor(m => m.LanguageFromId, Model.AllLanguagesFrom, new { data_bind = "value: getLanguageFromToById(0).LanguageFromId" }) #Html.ValidationMessageFor(m => m.LanguageFromId)
#: #Html.LabelFor(m => m.LanguageToId): #Html.DropDownListFor(m => m.LanguageToId, Model.AllLanguagesTo, new { data_bind = "value: getLanguageFromToById(0).LanguageToId" }) #Html.ValidationMessageFor(m => m.LanguageToId)
delete
}
</div>
Your design here has some poor choices. Knockout's Templating is the right choice for this, but it is going to require you to start thinking in a different sort of pattern. You do not need to use partials to accomplish the repetition you are after.
Here is a fiddle demonstrating a templating solution. http://jsfiddle.net/tyrsius/XgwLD/3/
Some notes: to populate incomingData, an easy method will be to use #Html.Raw(Json.Encode(Model.DirectorySearchModel ));. This will turn your model into a JSON object, which the viewModel's constructor can easily use.
Now, I didn't use any MVC code in the fiddle because I can't, but you've obviously already found how you can put data-bind in the MVC helpers. This isn't always a bad idea, but for things like selects and DIVs that you want to use as templates, it will probably just makes things harder to read.

Resources