Strongly Typed ASP.NET MVC DropDownList Without SelectList - asp.net-mvc-3

Is there a way to remove the selectlist parameter below and still use the HTML Helper? I like the strongly typed option, but use knockout.js quite a bit.
#Html.DropDownListFor(m => m.ProgramId, new SelectList(Enumerable.Empty<ProgramModel>()), new { data_bind = "enable: programs().length > 0, value: programId, options: programs, optionsText: 'Name', optionsValue: 'Id', optionsCaption: ' -- Choose Program -- ', event: { change: function(_,event) { getLicenseProductsForProgram() } }" })

Since Drop down List actually needs to have list of options, it requires the selectlist parameter. You can always pass an empty list to it though:
#Html.DropDownListFor(m => m.ProgramId, new List<SelectListItem>(), new { [the rest of your stuff] })

No, that's not possible. The standard DropDownList/DropDownListFor helpers expect an IEnumerable<SelectListItem> as second argument. Obviously there should be nothing preventing you from writing a custom helper, or custom editor template.

Related

C# MVC3 Listbox callback

I am creating a ListBox in MVC:
#Html.ListBoxFor(model => model.SelectedItemIds, new SelectList(Model.Items, "Value", "Text"))
which works fine, I can see the ListBox appear in the view.
I want to add some kind of callback when a user clicks and selects an item in the list. How can I do this using MVC3?
You would probably be best served by adding an id parameter to your ListBox, and then doing whatever callback that you want by using jQuery. Your line of code would then be like this:
#Html.ListBoxFor(model => model.SelectedItemIds, new SelectList(Model.Items, "Value", "Text"), new {id = "MyListBox")
Afterwards you could easily hook up an event in jQuery as follows:
$('#MyListBox').change(function() { ...some function... } );
You can add javascript onChange handler with this overload:
#Html.ListBoxFor(model => model.SelectedItemIds, new SelectList(Model.Items, "Value", "Text"), new{onchange="onListBoxChanged(); return false;"})
where onListBoxChanged() is javascript function.
You can do something like this
#using(html.begainform( ........your action name........))
{
#Html.ListBoxFor(model => model.SelectedItemIds, new SelectList(Model.Items, "Value", "Text"))
}
& in jquery you can write something like this
$("<Id or class of your ListBox>").change(function() {
this.form.submit();
});

How to properly disable an Html Helper Textbox or TextBoxFor?

I have a razor display that is being used for entry. In one case, I would like the user to be able to populate the text box, in the other case, I would like to prevent the user from populating it. I am using code like:
#Html.TextBoxFor(model => model.Goop, new { #class = "text-box", maxlength = 2, onfocus = "javascript:this.select();" })
if (Model.Review.ReviewType.Equals("M"))
{
<script type="text/javascript">
$(function () {
$("#Goop").prop("disabled", true);
});
</script>
}
I have tried to do this several ways, jQuery (above), CSS attribs, javascript, ASP.NET... but all have the same issue: When the form is submitted, if the Goop textbox is disabled, the value for Goop in the model is Null. Ideas?
Thanks in advance!
Maybe it's not as cool without jQuery, but when I do this in my apps I do something along the lines of
if (Model.Review.ReviewType.Equals("M"))
{
#Html.DisplayFor(model => model.Goop)
#Html.HiddenFor(model => model.Goop)
}
else
{
#Html.TextBoxFor(model => model.Goop)
}
If a form element is disabled, it does not post a value. That's how it's supposed to work.
To work around this, you will need to do one of several things. You can enable the fields just before posting by intercepting the submit method. You can use a hidden field to store the data in addition to the disabled control. Or you can just assume the values on the controller side.
by the way, it should be .prop("disabled", "disabled"), which renders as disabled="disabled", that's standards compliant.

Populate listbox with associated entities

I'm building my first MVC(3) application which manages snippets.
Obviously I have an edit page for a snippet, which has a programming language (0.* to 0.1).
Now my question is, how can I build a listbox with all the present programming languages to show on my edit page for a snippet?
I think I can create a ViewModel and populate that with all the values by querying them manually and passing them as a list, but I have a feeling that the people who built MVC have a tidier solution to this? I have "Pro MVC 3" and "Pro Entity Framework" at hand by Apress but can't seem to find an answer to this.
When I try:
#Html.EditorFor(model => model.Language or model.Language.Name)
I get errors.
Thanks in advance, any help is appreciated!
I think I can create a ViewModel
Straight to the point! That's exactly what I would recommend you doing.
But if you want to stick with your domain models you could do some adaptations in the view in order to be able to use the ListBox helper (totally unrecommended solution, but since you asked for something more tidier according to your criteria):
#model Snippet
#Html.ListBox(
"SelectedIds",
new MultiSelectList(
Model.Languages.Select(l => new { Value = l.ID.Tostring(), Text = l.Name }),
"Value",
"Text"
)
)
Here is what I do in similar cases:
1) Create a View Model for editing language
public class LanguagesModel
{
public IEnumerable<int> SelectedLanguageIds { get; set; }
public MultiSelectList languages { get; set; }
}
2) Populate the model in the controller:
public ActionResult Index()
{
List<Language> languages = _languageService.GetLanguages();//however you get the languages from your datasource
var temp = new MultiSelectList(
languages.Select(l => new { Value = l.LanguageId.ToString(), Text = l.Name }),
"Value",
"Text");
LanguagesModel model = new LanguagesModel();
model.languages = temp;
return View(model);
}
3) Create a view that uses the DropDownListFor helper:
#model LanguagesModel
#using (Html.BeginForm(Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })))
{
#Html.ValidationSummary(true)
<fieldset>
#Html.ListBoxFor(m => m.SelectedLanguageIds, Model.languages)
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
be carefule to replace "Index" and "Home" by the Action and Controllers that you are actually using.
Edit Changed code to use ListBox instead of DropDownList. Inspired by Darin Dimitrov's answer

Telerik MVC specifying your own action router within a template column

I am using the latest version of Telerik MVC with ASP.NET MVC 3 and the Razor view engine.
I have the following column declaration:
column.Bound(x => x.Id)
.Template(x => Html.ActionLink("Edit", "Edit", new { id = x.Id }))
.Title("Action")
.Width(100);
I have created my own method that routes to this Edit action method which I would like to use but not sure how to?
public static object AdministrationCategoryEdit(this UrlHelper urlHelper, int categoryId)
{
Check.Argument.IsNotNull(urlHelper, "urlHelper");
return new { area = "Administration", controller = "Category", action = "Edit", id = categoryId };
}
How would I reference the above method in my column declaration and pass it through the category ID?
For example, if I want to use it with a button, then I would do something like:
$('#btnEdit').click(function () {
window.location = '#Url.RouteUrl(Url.AdministrationCategoryEdit(Model.Id))';
});
There is no perfect match for your requirement since all ActionLink methods have a separate parameter for the action. However, it should work with the following code even though the action is now specified twice.
column.Bound(x => x.Id)
.Template(x => Html.ActionLink("Edit", "Edit", Url.AdministrationCategoryEdit(x.Id)))
.Title("Action")
.Width(100);
An alternative would be to create an HTML helper similar to ActionLink that now only generates the route parameters but the complete code for a link.

HtmlHelper and htmlAttributes help

I'm fairly new to MVC 3 and am using the Razor view engine. I'm using the Html.Hidden extension method to output input elements of type hidden. What I woudl also like to do is add a custom attribute to hold a dynamic value. I was under the impression in HTML5 wee could write custom html element attributes that are prefixed with 'data-'. I'm trying to do something like below;
#Html.Hidden("hdnID", mymodel.somevalue, new { data-uniqueid = mymodel.somevalue })
hoping to render;
<input type="hidden" value="mymodel.somevalue" data-uniqueid="mymodel.somevalue"/>
The htmlAttributes part (new { data-uniqueid = mymodel.somevalue }) is giving the error,
"Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access".
Can I add user-defined attribute to html elements using the HtmlHelper classes?
Regards,
Use:
#Html.Hidden("hdnID", mymodel.somevalue, new { #data_uniqueid = mymodel.somevalue })
The underscore gets automatically converted to a dash.
Doh! I was being silly. You can't have '-' in the anon type declaration:
data-uniqueid = ...it must be
datauniqueid = ....
In that case, your best best is to write out the hidden input by hand:
<input type="hidden" value="#mymodel.somevalue" data-uniqueid="#mymodel.somevalue"/>
You can step around the member validation by constructing a dictionary object. As follows:
#Html.TextBoxFor(model => model.Phone, new Dictionary<string, object>
{
{
"data-call-results-target", "#search-results-area"
},
{
"data-action-path", "/Controler/Method"
}
})

Resources