How to give names for dynamically generated radiobuttonfor - asp.net-mvc-3

I am generating radiobuttonfor dynamically.
My code runs as,
#{int questionCount = 0;
}
#{foreach (SectionDetail sectionDetail in section.SectionDetails)
{
<table>
<tr>
<td>
#Html.Label(sectionDetail.Title)
</td>
#{count = 0;
}
#foreach (SectionScore sectionScore in Model.IndividualSections)
{
<td class="ColSupplier">
#Html.RadioButtonFor(model => model.IndividualSections[count].SectionScores[questionCount].score.pass, true)Pass
#Html.RadioButtonFor(model => model.IndividualSections[count].SectionScores[questionCount].score.pass, false)Fail
</td>
count++;
}
</tr>
</table>
questionCount++;
}
Here some radio buttons are having the same name. So I am unable to get the exact value. How to give different names for these radio buttons. Please help me in sorting this out.

Please try this
#(Html.RadioButtonFor(model => model.IndividualSections[count].SectionScores[questionCount].score.pass, true, new {#id=sectionDetail.Title + count.Tostring() }) ))

You can use HtmlAttributes to define unique IDs.
#Html.RadioButtonFor(model => model.IndividualSections[count].SectionScores[questionCount].score.pass, true, new { id= count.ToString()});
Hope this helps you.

Related

IEnumerable Model from view to Controller is NULL [duplicate]

This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 4 years ago.
I am trying to return table values of my view back to the controller to save on db but I keep getting null. I can post the values without problem and bind them to the view.
I cannot understand why, I am using a server side view model.
Is there any way to perform this?
View:
#model IEnumerable<MultiEdit.Models.TableViewModel>
#using (Ajax.BeginForm("Save", "UUTs", new AjaxOptions
{
HttpMethod = "Post",
}, new { id = "tableForm" }))
{
#Html.AntiForgeryToken()
<div class="row" style="padding-top:10px;">
<div class="col-lg-12">
<table class="table table-bordered table-striped ">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.IsChassis)
</th>
<th>
#Html.DisplayNameFor(model => model.Justification)
</th>
</tr>
</thead>
<tbody id="tblMultiEdit">
#foreach(var item in Model)
{
<tr>
<td>
#Html.CheckBoxFor(modelItem => item.CheckIsChassis)
</td>
<td>
#Html.EditorFor(modelItem => item.Justification)
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}
Controller:
public void Save(IEnumerable<TableViewModel> vm)
{
DoSomething();
}
You need to iterate through your collection with a for loop and index qualifier. Something like the below. The syntax is not exact but you should be able to see what I mean.
#for(var index = 0; index <= Model.Count - 1; index++)
{
<tr>
<td>
#Html.CheckBoxFor(modelItem => Model[index].CheckIsChassis)
</td>
<td>
#Html.EditorFor(modelItem => Model[index].Justification)
</td>
</tr>
}
This is required so the index can be used to create the unique id's of the Enumerable items and aids model binding
Hope that helps
I resolved it by using IList insead of IEnumerable.
View:
#model IList<MultiEdit.Models.TableViewModel>
#Html.CheckBoxFor(modelItem => modelItem[index].CheckIsChassis, new { #class = "form-control" })
Controller:
public void Save(IList<TableViewModel> vm)
{
var x = vm;
}

MVC 3 Razor - Form not posting back to controller

I am using MVC 3 and Razor, attempting to post a form back to a controller from a telerik window (telerik.window.create) that loads a partial view. Im not sure how to post this so ill just post the code in order of execution and explain it as I go.
First an anchor is clicked, and onClick calls:
function showScheduleWindow(action, configId) {
var onCloseAjaxWindow = function () { var grid = $("#SubscriptionGrid").data("tGrid"); if (grid) { grid.rebind(); } };
CreateAjaxWindow("Create Schedule", true, false, 420, 305, "/FiscalSchedule/" + action + "/" + configId, onCloseAjaxWindow);
}
And the CrateAjaxWindow method:
function CreateAjaxWindow(title, modal, rezible, width, height, url, fOnClose) {
var lookupWindow = $.telerik.window.create({
title: title,
modal: modal,
rezible: rezible,
width: width,
height: height,
onClose: function (e) {
e.preventDefault();
lookupWindow.data('tWindow').destroy();
fOnClose();
}
});
lookupWindow.data('tWindow').ajaxRequest(url);
lookupWindow.data('tWindow').center().open();
}
Here is the partial view that is being loaded:
#model WTC.StatementAutomation.Web.Models.FiscalScheduleViewModel
#using WTC.StatementAutomation.Model
#using WTC.StatementAutomation.Web.Extensions
#using (Html.BeginForm("Create", "FiscalSchedule", FormMethod.Post, new { id = "FiscalScheduleConfigForm" }))
{
<div id="FiscalScheduleConfigForm" class="stylized">
<div class="top">
<div class="padding">
Using fiscal year end: #Model.FiscalYearEnd.ToString("MM/dd")
</div>
<div class="padding Period">
<table border="0">
<tr>
<th style="width: 120px;"></th>
<th>Effective Date</th>
<th>Next Run</th>
<th>Start From Previous</th>
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.HasMonthly)
<label>Monthly</label>
</td>
<td>
#{ var month = Model.GetForFiscalPeriod(FiscalPeriodStatementSchedule.FiscalPeriod.Monthly);}
#month.BaseSchedule.StartDate.ToString("MM/01/yyyy")
</td>
<td>
#month.BaseSchedule.NextScheduleRun.ToString("MM/dd/yyyy")
</td>
<td class="previous">
#(month.HasRun ? Html.CheckBoxFor(m => month.BaseSchedule.StartFromPreviousCycle, new { #disabled = "disabled", #readonly = "readonly" }) : Html.CheckBoxFor(m => month.BaseSchedule.StartFromPreviousCycle))
</td>
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.HasQuarterly) Quarterly
</td>
<td>
#{ var quarter = Model.GetForFiscalPeriod(FiscalPeriodStatementSchedule.FiscalPeriod.Quarterly);}
#quarter.BaseSchedule.StartDate.ToString("MM/01/yyyy")
</td>
<td>
#quarter.BaseSchedule.NextScheduleRun.ToString("MM/dd/yyyy")
</td>
<td class="previous">
#(quarter.HasRun ? Html.CheckBoxFor(m => quarter.BaseSchedule.StartFromPreviousCycle, new { #disabled = "disabled", #readonly = "readonly" }) : Html.CheckBoxFor(m => quarter.BaseSchedule.StartFromPreviousCycle))
</td >
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.HasAnnual) Annual
</td>
<td>
#{ var annual = Model.GetForFiscalPeriod(FiscalPeriodStatementSchedule.FiscalPeriod.Annual);}
#annual.BaseSchedule.StartDate.ToString("MM/01/yyyy")
</td>
<td>
#annual.BaseSchedule.NextScheduleRun.ToString("MM/dd/yyyy")
</td>
<td class="previous">
#(annual.HasRun ? Html.CheckBoxFor(m => annual.BaseSchedule.StartFromPreviousCycle, new { #disabled = "disabled", #readonly = "readonly" }) : Html.CheckBoxFor(m => annual.BaseSchedule.StartFromPreviousCycle))
</td>
</tr>
<tr>
<td>
#Html.CheckBoxFor(m => m.HasSemiAnnual) Semi-annual
</td>
<td>
#{ var semi = Model.GetForFiscalPeriod(FiscalPeriodStatementSchedule.FiscalPeriod.SemiAnnual);}
#semi.BaseSchedule.StartDate.ToString("MM/01/yyyy")
</td>
<td>
#semi.BaseSchedule.NextScheduleRun.ToString("MM/dd/yyyy")
</td>
<td class="previous">
#(semi.HasRun ? Html.CheckBoxFor(m => semi.BaseSchedule.StartFromPreviousCycle, new { #disabled = "disabled", #readonly = "readonly" }) : Html.CheckBoxFor(m => semi.BaseSchedule.StartFromPreviousCycle))
</td>
</tr>
</table>
</div>
<div class="padding StartDay">
<span>Run on day:</span>
#Html.TextBoxFor(model => model.StartDay)
<span>of every period.</span>
</div>
</div>
<div class="bottom">
<div class="padding">
<div style="float: left;">
#if (Model.ShowSuccessSave)
{
<div id="successSave" class="label">Changes saved succesfully</div>
}
#Html.ValidationSummary(true)
#Html.HiddenFor(x => x.SubscriptionId)
#Html.HiddenFor(x => x.DeliveryConfigurationId)
#Html.HiddenFor(x => x.FiscalYearEnd)
</div>
<a id="saveSchedule" class="btn" href="">Save</a>
</div>
</div>
</div>
}
<script type="text/javascript">
$(function () {
$('a#saveSchedule').click(function () {
$(this).closest("form").submit();
return false;
});
});
</script>
And finally the controller method:
[HttpPost]
public ActionResult Create(FormCollection formValues, int subscriptionId, int deliveryConfigurationId, int startDay, DateTime fiscalYearEnd)
{
if (ModelState.IsValid)
{
var selectedSchedules = GetCheckedSchedulesFromForm(formValues);
var startFromPrevious = GetFromPreviouSelections(formValues);
this.AddModelErrors(_fiscalScheduleService.AddUpdateSchedules(selectedSchedules, subscriptionId, deliveryConfigurationId, startDay, startFromPrevious));
}
return new RenderJsonResult { Result = new { success = true, action = ModelState.IsValid ? "success" : "showErrors",
message = this.RenderPartialViewToString("_FiscalScheduleConfigForm",
BuildResultViewModel(deliveryConfigurationId, subscriptionId, fiscalYearEnd, ModelState.IsValid)) } };
}
As you can see I am using jQuery to post back to the controller, which I have done on several occasions in the applicaiton, this seems to work fine normally. But with this form, for some reason it is not posting back or stepping into the Create method at all. I am speculating that it has something to do with the parameters on the controller method. But I am fairly new to MVC (coming from ASP.NET world) so Im not really sure what I am doing wrong here. Any help would be greately appreciated!
I was able to get it to post to the controller by modifying the textboxfor for the startDay:
Changed from:
#Html.TextBoxFor(model => model.StartDay)
To:
#Html.TextBoxFor(model => model.StartDay, new { id = "startDay" })
My guess is that you're running on a virtual directory in IIS? That url you're generating is likely the culprit.
Hit F12, check out the network tab (and enable tracing) and see what it's trying to request.
Instead of building the link through text, why not use #Url.Action()? You could store this in an attribute on the a tag (like in an attribute called data-url, for example) and then use that info to make your call. It's pretty easy to pull out the attribute with jQuery, something like this:
$('.your-link-class').click(function(){
var url = $(this).attr('data-url');
// proceed with awesomesauce
});
Would something like that work for you?
[shameless self plug] As far as the controller action signature goes, you might want to look into model binding if you can. One simple class and many of your headaches will go away. You can read more here, read the parts on model binding. There are downloadable samples for different approaches.
Cheers.

I need a html helper for my view but not too sure what one to use

I am making an MVC3 web application.I have a table which is filled with data from my database but was wondering how i could make it show only the first three lines of my synopsis instead of all 10 lines.I think this has something to do with HTML Helpers but was wondering if any of you could help me find the right code?????
Any help would be greatful!
#model IEnumerable<TheatreGroup.Models.Show>
#{
ViewBag.Title = "Shows";
}
<h2>
Shows</h2>
<p>Below is a list of shows which will be avalible in the next couple of weeks</p>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm())
{
<p>
Find by name: #Html.TextBox("SearchString")
<input type="submit" value="Search" /></p>
}
<table>
<tr>
<th>
#Html.ActionLink("name", "Index", new { sortOrder = ViewBag.nameSortParm,})
</th>
<th>
#Html.ActionLink("writer", "Index", new { sortOrder = ViewBag.writerSortParm,})
</th>
<th>
#Html.ActionLink("synopsis", "Index", new { sortOrder = ViewBag.synopsisSortParm, })
</th>
<th>
</th>
</tr>
#foreach (var item in Model){
<tr>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.writer)
</td>
<td>
#Html.DisplayFor(modelItem => item.synopsis)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.showid }) |
#Html.ActionLink("Details", "Details", new { id = item.showid }) |
#Html.ActionLink("Delete", "Delete", new { id = item.showid })
</td>
</tr>
}
</table>
I'll divide my answer into two state:
You need the other 7 lines somewhere further down the flow of the page (like a 'show more results' link)
You don't need the rest of the list.
Solution 1:
Use what #Dangerous said.
#for (int i=0; i<3; i++)
{
#Html.DisplayFor(m => m[i].name) // And the rest of the data
}
please take note that if you don't have 3 elements this code will throw an exception.
what you can do is check if the count is smaller than 3 and then run to that number.
You might also like to run still on the foreach loop and just give the some sort of class that will hide it new { #class = 'hidden' } and then when you press some line, just use Javascript (jQuery) to show them.
Solution 2:
If you don't need the rest of the elements, when sending the model to the view just use take.
public ActionResult Action()
{
var model = GetListFromDatabase().Take(3); // LINQ
return View(model);
}
You might need a ToList() to make it work, it depends
that way you can keep your code as is, just shorten the number of elements sent to the View.
Hope it helps !
You are using #foreach (var item in Model) to display each line.
Try using #for (int i=0; i<3; i++) so that the loop just displays the first 3 items.
You will then need to reference the model as #Html.DisplayFor(m => m[i].name) etc for the Display For's. I believe that should work.

mvccontrib grid - How to add <tr> id

I want to add an id to the "tr" elements of the mvccontrib grid I build:
<tr id="0"/>
<tr id="1"/>
so if the table contains 10 rows, the ids are 0 through to 9.
One way is to add an additional item to my entity to store this value and then create this as a hidden column with the id as the value of this item - not very elegant.
Is there a more elegant way to do this?
Thanks
I've got this far but now it complains at the RenderUsing line, any ideas?
#model IEnumerable<Tens.Models.UserPreviousNamesView>
<div class="demo_jui">
#{
var userId = 0;
foreach (var item in Model)
{
userId = item.Id;
break;
}
#(Html.Grid(Model.Select((item,index) => new { Item = item, Index = index}))
.Columns(col =>
{
col.For(p => p.Item.Title);
col.For(p => p.Item.Name);
col.Custom(#<text>
#Ajax.ActionLink("Delete", "DeleteUserPreviousName", "Summary", null, null, new { id = item.Item.Id, #class = "deleteUserPreviousName" })
</text>).Encode(false);
})
.RowAttributes(p => new Hash(Id => "id"+p.Item.Index.ToString()))
.Attributes(Id => "userPreviousNamesTable")
.Empty("You currently have no Previous Names.")
.RenderUsing(new Tens.GridRenderers.UserPreviousNamesGridRenderer<Tens.Models.UserPreviousNamesView>()));
}
You could transform the model to add it a row index and then use the RowAttributes method:
#model IEnumerable<MyViewModel>
#(Html
.Grid(Model.Select((item, index) => new { Item = item, Index = index }))
.Columns(column =>
{
column.For(x => x.Item.Foo);
column.For(x => x.Item.Bar);
})
.RowAttributes(x => new Hash(id => string.Format("id{0}", x.Item.Index)))
)
Also I have pre-pended the id with the id keyword as ids in HTML cannot statr with a number as shown in your example.
Sample output:
<table class="grid">
<thead>
<tr>
<th>Foo</th>
<th>Bar</th>
</tr>
</thead>
<tbody>
<tr id="id0" class="gridrow">
<td>foo 1</td>
<td>bar 1</td>
</tr>
<tr id="id1" class="gridrow_alternate">
<td>foo 2</td>
<td>bar 2</td>
</tr>
<tr id="id2" class="gridrow">
<td>foo 3</td>
<td>bar 3</td>
</tr>
</tbody>
</table>
You can always show hide columns without adding id to particular row or columns like below
$(".mvcGridDollarHeader th:nth-child(16)").hide();
$(".mvcGrid td:nth-child(16)").hide();
Where mvcGrid is tableStyle and mvcGridDollarHeader is header style.
#grid1.GetHtml(
tableStyle: "mvcGrid",
displayHeader: true,
emptyRowCellValue: "",
headerStyle: "mvcGridDollarHeader",

Submitting a List<T> of Items

Just a quick question from a newbie to the pro's.
I am trying to implement a editable grid type form in my application. Here is the example.
#for (int i = 0; i < Model.Items.Count; i++)
{
<tr>
<td>#Html.CheckBoxFor(m => m.Items[i].fav_ind)
</td>
<td>
<a href="#" onclick="ShowDeals(#Model.Items[i].item_no);event.returnValue = false; return false;">
DEALS</a>
</td>
<td>#Html.DisplayFor(m => m.Items[i].item_no)
</td>
<td>#Html.DisplayFor(m => m.Items[i].item_desc)
</td>
<td>#Html.DisplayFor(m => m.Items[i].mfr_item)
</td>
<td>#Html.DisplayFor(m => m.Items[i].pack_size)
</td>
<td>#Html.DisplayFor(m => m.Items[i].purc_uom)
</td>
<td>#Html.DisplayFor(m => m.Items[i].purc_uom_conv)
</td>
<td>#Html.DisplayFor(m => m.Items[i].list_prc)
</td>
<td>
#Html.TextBoxFor(m => m.Items[i].nett_prc)
</td>
<td>
#Html.TextBoxFor(m => m.Items[i].Qty)
</td>
</tr>
}
This #for is inside a Html.BeginForm, because I want the user to be able to edit the last 2 fields (nett_prc and qty. There is also a submit bottom on the bottom of this grid(table).
Now for the question, when I submit, I get all the rows back in the controller, but on the items only the 2 fields where is is Html.TextBoxFor() has data in it. I want to get all the fields in the controller. I kwno I can use #Html.HiddenFor(), but I want to be able to display the other fields in labels, and when the user submits I want the values ass well.
Thanks in advance.
You can do both DisplayFor and HiddenFor at the same time:
<td>
#Html.DisplayFor(m => m.Items[i].item_no)
#Html.HiddenFor(m => m.Items[i].item_no)
</td>
However, why would you need HiddenFor? If the user is not supposed to edit some of the values, you can't trust the values that come from the form anyway. And if you can't trust them you will have to read the originals (e.g. from a database). What does HiddenFor buy you here?

Resources