Working on MVC 5 app.
I have a table with a bunch of columns. One column contains a radio button list of items. Since this is an "edit" view I need to pre-populate the selected radio button properly. (ie select the item that's in the db)
Part of my controller code...
newVmRecord.SurveyAnswerOption =
new SelectList(db.SurveyAnswerOptions,
"AnswerOptionText", "AnswerOptionText", ar.SurveyAnswer);
Here's the razor:
#foreach (SelectListItem item in
(IEnumerable<SelectListItem>)Model[i].SurveyAnswerOption)
{
#Html.RadioButtonFor(modelItem => Model[i].SelectedSurveyAnswer,
Model[i].SurveyAnswerOption, new { #Checked =
Model[i].SelectedSurveyAnswer}) #item.Text
}
The available options are 'yes', 'no' and 'n/a'. In the database, for example, if 'no' was already selected then it should be pre-selected when this view loads. The radio buttons appear correctly, but, the #Checked doesn't work correctly.
By the way, I am sure there is existing data because I put this line of code as the first line the foreach....
#Html.DisplayTextFor(modelItem => Model[i].SelectedSurveyAnswer);
Any suggestions? Thanks!
Please try this:
#foreach (SelectListItem item in (IEnumerable<SelectListItem>)Model[i].SurveyAnswerOption)
{
#Html.RadioButtonFor(modelItem => Model[i].SelectedSurveyAnswer,#item.Value, Model[i].SelectedSurveyAnswer == item.Value ? new {Checked = "checked"} : null) #item.Text
}
Related
I have built a mutli-select checkbox list
foreach (var item in Model)
{
#Html.HiddenFor(i => item.SectionID)
#Html.CheckBoxFor(i => item.IsChecked)
#Html.LabelFor(i => item.IsChecked, item.SectionTitle)
<br />
}
While this generates a checkbox for each item and the proper text lable next to each box the problem comes that no matter which label you click it only toggles the first check box. How can I tie each label to the appropriate checkbox for this setup?
#Html.CheckBoxFor(i => item.IsChecked,new{id=item.SectionID})
As I am new to MVC framework, I have been spending a couple of hours to generate a check box list in a View file. Finally, I could figure it out well. Here is my code:
#foreach (var item in Model.GetRoleNames)
{
#Html.CheckBox("chk_" + item.Value, new { value = item.Value })#item.Text<br />
}
But, I need to detect which of them is selected and if all the ckeckboxes are left unchecked, then preventing some operations.
Question: How can I get the checked items when I am within a controller action?
As the others said, you should use a Boolean value as the second parameter to CheckBox to indicate the checked status. A bit of string manipulation should help you get the ids of the selected check boxes..
First lets change the way the checkbox helper is used
<div id='myCheckboxDiv'>
#foreach (var item in Model.GetRoleNames)
{
#Html.CheckBox("chk_" + item.Value, false)#item.Text<br />
}
</div>
As you can see, I have set the second parameter to false and wrapped the mix in a div
And, when you want to get the ‘values’ associated with the selected checkboxes
var values = $(‘# myCheckboxDiv’).find('input:checkbox:checked').map(function () {
// get the name ..
var nameOfSelectedItem = this.attr('name');
// skip the ‘chk_’ part and give me the rest
return nameOfSelectedItem.substr(4);
}).get();
I am assuming item.Value to be a number. If its is not, please remove the white spaces using C#
I have 5 dropdowns, which are basically displaying "Select", "Yes" and "No". Initially they are set to "Select". Once he user chooses something, I am storing the data in a cookie (with Jquery) and eventually passing this to the ViewModel so that I can use it in the Controller.
When the user refreshes the page, I want these dropdown lists to be populated again with the value I have in the ViewModel.
At the moment I have the following code :-
Inside the View I have
<%: Html.DropDownList("FirstQuestYesNo", ViewData["FirstQuestYesNoData"] as SelectList, new { #class = "normalDropdowns" })%>
and in my controller I have the following :-
var ddlYesNoData = new SelectList(new[]
{
new {ID="",Name=#Resources.GeneralTerms.GeneralTerms_Select},
new {ID="Yes",Name=#Resources.GeneralTerms.GeneralTerms_Yes},
new{ID="No",Name=#Resources.GeneralTerms.GeneralTerms_No},
},
"ID", "Name", 1);
//Refresh the YesNo dropdown with the correct vals
Dictionary<string, string> YesNoData = new Dictionary<string, string>();
YesNoData.Add("FirstQuestYesNoData", viewModel.FirstQuestYesNoValue);
YesNoData.Add("SecondQuestYesNoData", viewModel.SecondQuestYesNoValue);
YesNoData.Add("ThirdQuestYesNoData", viewModel.ThirdQuestYesNoValue);
YesNoData.Add("FourthQuestYesNoData", viewModel.FourthQuestYesNoValue);
YesNoData.Add("FifthQuestYesNoData", viewModel.FifthQuestYesNoValue);
foreach (var item in YesNoData)
{
ViewData[item.Key] = ddlYesNoData;
if (item.Value != null)
{
var selected = ddlYesNoData.Where(x => x.Value == item.Value).First();
selected.Selected = true;
}
}
So basically what I am doing is get the value of each dropdown from the viewModel, and then try to set that value inside my View. As a result of what I am doing, I am getting all the DropdownLists option as "Select" instead of the value inside my viewModel.
The problem is that I do not know how to "target" the specific DropDownList. How can I target the DropDown (in this case "FirstQuestYesNo") from the Controller using my code?
Thanks for your help and time.
In your controller action simply set the FirstQuestYesNo property to the corresponding value. For example:
ViewData["FirstQuestYesNo"] = "Yes"; // this value might come from a cookie
This will automatically preselect the option with value="Yes". Obviously this value will come from the cookie. You don't need any foreach loops.
I have two combo boxes and a grid in my MVC View:
<div id="Products" class="products maintField">
#Html.Label("something", "Product:")
#(Html.Telerik().ComboBox().Name("productList")
.AutoFill(true)
.DataBinding(c => c.Ajax().Select("GetProducts", "Maintenance").Enabled(true).Cache(true))
.Filterable(c => c.FilterMode(AutoCompleteFilterMode.StartsWith).Enabled(true))
.HighlightFirstMatch(true)
.ClientEvents(eb =>
{
eb.OnChange("productChanged");
})
)
</div>
<div id="Layouts" class="layout maintField">
#Html.Label("something", "Layout:")
#(Html.Telerik().ComboBox().Name("layoutList")
.ClientEvents(eb =>
{
eb.OnChange("layoutChanged");
})
)
</div>
<div style="clear: both;"/>
<div class="fields">
#(Html.Telerik().Grid<MaintenanceModel>().Name("fieldList")
.DataBinding(bc =>
{
bc.Ajax().Select("GetProductFields", "Maintenance", new { prodID = 0, layoutID = 0 }).Enabled(true);
})
.ClientEvents(c =>
{
c.OnDataBound("fieldGridBound");
})
.Columns(c =>
{
c.Bound(mm => mm.Field_ID).ClientTemplate("<input id='Field_ID_<#= Field_ID #>' type='checkbox' name='checkedRecords' class=\"checkBoxGroup\" value='<#= Field_ID #>' />")
.Title("<input id='mastercheckbox' type='checkbox' style='display:none;' />")
.HeaderHtmlAttributes(new { style = "text-align: center;" })
.Width(36)
.HtmlAttributes(new { style = "text-align:center" });
c.Bound(fld => fld.Field_Name).Title("Field Name").Width(225);
c.Bound(fld => fld.Field_Description).Title("Field Description");
}).Scrollable(c =>
{
c.Enabled(true);
c.Height(700);
}).Footer(false).Sortable(c =>
{
c.Enabled(false);
c.OrderBy(oc =>
{
oc.Add(fld => fld.SeqNbr);
});
})
)
</div>
And with some less than beautiful JS the comboboxes cascade and eventually populate the grid:
function productChanged(e) {
clearLayout();
var layoutCombo = $("#layoutList").data('tComboBox');
if (layoutCombo == null) {
alert("Can't find layoutList");
return;
}
if (e.value == "" || e.value == null) {
clearLayout();
return;
}
layoutCombo.loader.showBusy();
$.get('#Url.Action("GetProductLayouts", "Maintenance")', { prodID: e.value }, function (result) {
layoutCombo.dataBind(result);
layoutCombo.loader.hideBusy();
});
}
function layoutChanged(e) {
var prodCombo = $("#productList").data('tComboBox');
var fieldGrid = $("#fieldList").data('tGrid');
if (fieldGrid == null) {
alert("Can't find fieldList");
}
if (prodCombo == null) {
alert("Can't find prodCombo");
}
if (e.value == "" || e.value == null) {
clearGrid();
return;
}
fieldGrid.rebind({ prodID: prodCombo.value(), layoutID: e.value });
$("#mastercheckbox").css("display", "block");
}
function fieldGridBound(e) {
var prodCombo = $("#productList").data('tComboBox');
var layoutCombo = $("#layoutList").data('tComboBox');
$.get('#Url.Action("GetLayoutFields", "Maintenance")', { prodID: prodCombo.value(), layoutID: layoutCombo.value() }, function (result) {
var cbGroup = $(".checkBoxGroup");
$(cbGroup).each(function (i, e) {
if (result.indexOf(e.value) >= 0) {
$(e).attr('checked', 'checked');
} else {
$(e).removeAttr('checked');
}
});
});
}
This works beautifully except in the situation where the two combo boxes are filled, the grid is bound, and the user goes to select a different value from the first combo box. The second combo box rebinds as expected, but if the values bound to the combobox didn't change (in position or display value) and the user selects the same item again, the change event doesn't get fired.
Specific example
In the database I have a hierarchy of Products and Layouts:
Product A
Platinum Layout
Gold Layout
Silver Layout
Product B
Platinum Layout
Gold Layout
Silver Layout
Product C
Platinum Layout
Silver Layout
Scenario 1
User selects 'Product A' from the first drop down causing the second drop down to be populated with Platinum, Gold, and Silver Layouts.
User selects 'Platinum Layout' from the second drop down causing related information to show in the grid.
User selects 'Product B' from the first drop down causing the second drop down to again be populated with Platinum, Gold, and Silver Layouts.
User selects 'Platinum Layout' from the second drop down again, however the changed event doesn't fire because the combo box didn't forget what was selected from before being rebound.
Scenario 2
User selects 'Product A' from the first drop down causing the second drop down to be populated with Platinum, Gold, and Silver Layouts.
User selects 'Platinum Layout' from the second drop down causing related information to show in the grid.
User selects 'Product C' from the first drop down causing the second drop down to again be populated with Platinum, Gold, and Silver Layouts.
User selects 'Platinum Layout' from the second drop down, causing the same erroneous behavior described in step 4 of Scenario 1.
Scenario 3
User selects 'Product A' from the first drop down causing the second drop down to be populated with Platinum, Gold, and Silver Layouts.
User selects 'Silver Layout' from the second drop down causing related information to show in the grid.
User selects 'Product C' from the first drop down causing the second drop down to be populated with Platinum and Silver Layouts.
User selects 'Silver Layout' from the second drop down causing related information to show in the grid (as should have happened in the other 2 scenarios).
In order to try to force the combo box to forget which item was selected prior to being rebound, I've tried manually setting the selected item to -1 (nothing) before binding using:
layoutCombo.select(-1);
and I've also tried reloading the combo box after the bind using
layoutCombo.reload();
However neither of them worked for me.
Has anyone else seen this behavior under similar circumstances? Is there any way to clear the combo box's last selected item variable manually from within my page (without digging around in the Telerik source)?
After playing with it a little more and hoping it would just work, it looks like it works if I fire the change event manually after layoutCombo.select(-1) and before I force the dataBind on the second combo box. Here's what my productChanged code looks like now:
function productChanged(e) {
clearLayout();
var layoutCombo = $("#layoutList").data('tComboBox');
if (layoutCombo == null) {
alert("Can't find layoutList");
return;
}
if (e.value == "" || e.value == null) {
clearLayout();
return;
}
layoutCombo.loader.showBusy();
$.get('#Url.Action("GetProductLayouts", "Maintenance")', { prodID: e.value }, function (result) {
layoutCombo.select(-1);
layoutCombo.trigger.change(); //**** Trigger the change manually so the combobox knows its value has changed
layoutCombo.dataBind(result);
layoutCombo.loader.hideBusy();
});
//layoutCombo.reload();
}
It feels like a bit of a hack since the combo box should know it's own value already. Any other ideas to make this cleaner would be much appreciated.
My page view currently has a dropdownlist on it that is getting bound to a collection from the controller. This is working fine, However I want to insert an item to the top of the dropdownlist that is not in my collection e.g the list currently gets the following items
Open
Closed
I want to add a third option of "All" but I don't want to add this option to my database. In Webforms I would have just bound the control then inserted another item however it seems this is not possible with MVC, am I right in thinking I will need to add some Javascript to the view to add this new item once the dropdownlist has been bound?
Thanks
No. Construct your data as a list of SelectListItems and prepend in the controller.
var list = db.Table
.Select( t => new SelectListItem
{
Key = t.ID.ToString(),
Value = t.Name
} )
.ToList();
list.Insert( 0, new SelectListItem { Key = "-1", Value = "All" } );
ViewData["TableSelect"] = list;
On the view side:
<%= Html.DropDownList( "TableID",
(IEnumerable<SelectListItem>)ViewData["TableSelect"] ) %>
Simple
you can make it as you wish in controller.
and pass it in viewdata.
other option is directly in view page.
<%= Html.DropDownList("DropDown","all" )%>
But you can add only one option..
Make sure you are not storing added options in ur db, right?
so before you save it, check option value in action and apply your logic.
Newer implementation
var list = _db.Status.ToList();
list.Add(new Status(){DevelopmentStatusID = -1, DevelopmentStatusDesc = "All"});
var result = list.OrderBy(d => d.StatusID).ToList();
ViewBag.StatusID = new SelectList(result, "StatusID", "StatusDesc");
Then in the index.html
#Html.DropDownList("StatusID", null, htmlAttributes: new {#class = "form-control"})