Can't bind checkbox in partial view to the main model (MVC) - asp.net-mvc

I've been running into to issue and I've been searching for an answer but nothing helped.
I have a Model:
public class Filters
{
public bool Filter1 { get; set; }
public bool Filter2 { get; set; }
public bool Filter3 { get; set; }
etc...
}
I have a partial view with multiple checkboxes and tried multiple things:
<input id="Filter1" name="Filter1" type="checkbox" value="true">
<input type="hidden" value="false" name="Filter1" />
and
#Html.CheckBoxFor(model => model.Filter1)
Then I have a main model:
public class Dashboard
{
...
public Filters FiltersDashboard { get; set; }
}
And somewhere in the main view I insert the partial view like this:
#Html.EditorFor(model => model.FiltersDashboard, "Filters")
In a jquery, I execute an alert when the checkbox is clicked and shows the value of the checkbox. This value remains unchanged.
<script>
$("#Filter1").click(function () {
alert(" #Model.FiltersDashboard.Filter1 ")
});
</script>
EDIT: Also tried it in the .submit function but model value remains unchanged:
<script>
$("#searchform").submit(function (event) {
alert(" #Model.FiltersDashboard.Filter1 ")
event.preventDefault();
});
</script>
This tells me that something isn't correctly bound but I have no clue what I'm doing wrong.
Also, the reason I'm not using a checkboxlist is because I need to execute a different query for each filter so I need specific names and bindings for them.

#Model.FiltersDashboard.Filter1 is razor code and is executed on the server before its sent to the view, so it will only ever return the initial value of the property (if you inspect the source code, you will see the initial value has been hard coded in your script).
However, if your script is being executed, then it means that you are using the manual <input> tags in your 2nd code snippet, in which case your view is not binding to your model because the correct name attribute would be name="FiltersDashboard.Filter1" and the associated id attribute would be id="FiltersDashboard_Filter1".
Always use the strong typed #Html.CheckBoxFor() which will generate the correct html for 2-way model binding and client side validation.
Note also that it just needs to be #Html.EditorFor(model => model.FiltersDashboard) - the 2nd parameter is unnecessary.
Then the script should be
<script>
$('#FiltersDashboard_Filter1').click(function () {
var isChecked = $(this).is(':checked');
alert(isChecked);
});
</script>

Related

Kendo Observable binding for checkbox is always showing ticked

I am using ASP.NET MVC application with Kendo framework. For some reason, i am always getting the checkbox "#IsInterestDeemed" in ticked state. Although, the viewmodel property "IsInterest" is false under the controller action method.
Please suggest where am i making the mistake.
<div id="RunModelDiv" style="min-width:300px">
<div>
<input type="checkbox" id="IsInterestDeemed" value="IsInterestDeemed" data-bind="checked: IsInterestDeemed, disabled: IsReadOnly" />
<label for="IsInterestDeemed"> Interest</label>
</div>
<div>
<script>
var myViewModel;
$(document).ready(function(){
myViewModel = kendo.observable({
IsReadOnly: #Html.Raw(Json.Encode(Model.IsReadOnly)),
IsInterestDeemed : '#Html.Raw(Json.Encode(Model.IsInterest))'});
kendo.bind($("#RunModelDiv"), myViewModel);
});
</script>
ViewModel Property:-
public bool IsInterest { get; set; }
public bool IsReadOnly { get; set; }
Why are the values for IsReadOnly and IsInterestDeemed in the Javascript handled differently (one is a string, the other is raw text)? Perhaps this is what is causing a syntax error on the page when it loads, and so the page will not behave as expected.
More specifically, these two lines are inconsistent:
IsReadOnly: #Html.Raw(Json.Encode(Model.IsReadOnly))
IsInterestDeemed : '#Html.Raw(Json.Encode(Model.IsInterest))'
Check the HTML output and verify your solution.

Get dynamic radio buttons values

I'm doing survey system on asp.net mvc 4. How can i get all radio buttons data in Controller ?
Example
$(document).ready(function(){
var AnswerCounter = 0;
$("#answer-add").click(function(){
var answertext = $("#answer-text").val();
var answerContent = $('<p>', {
class:'external',
});
var inputAnswer = $('<input>',{
id:'answer-'+AnswerCounter,
name:'rb',
class:'answer-radio'
}).attr("type","radio").appendTo(answerContent);
var labelAnswer = $('<label>').attr('for','answer-'+AnswerCounter).text(answertext).appendTo(answerContent);
$('#answers').append(answerContent);
AnswerCounter++;
});
});
You can see in the example buttons created by jquery. so i can use model binding.
Thanks.
The HTML typically geneated for MVC3 radiobuttons look like this
<input name="FeedingTime" id="FeedingTime" type="radio" value="Morning"/>
<input name="FeedingTime" id="FeedingTime" type="radio" value="Afternoon" checked="checked"/>
and when the radio button group posts, it will bind to the variable that matches the name.
[HttpPost]
public ActionResult Index (string FeedingTime){
//feeding time here is "Afternoon"
}
so to make your code bind correctly,
set the value of the input 'value' attribute in your script, and
have a variable in the ActionResult that matches the 'name' attribute in the html input element
EDIT: This answer is no longer relevant to the question being asked.
to get the value from radio buttons you can bind to them like you would a string variable; suppose in your view you have
#Html.LabelFor(m => m.FeedingTime,"Morning")
#Html.RadioButtonFor(m => m.FeedingTime, "Morning")<br />
#Html.LabelFor(m => m.FeedingTime,"Afternoon")
#Html.RadioButtonFor(m => m.FeedingTime, "Afternoon")<br />
#Html.LabelFor(m => m.FeedingTime,"Night")
#Html.RadioButtonFor(m => m.FeedingTime, "Night")
when you post back, you would capture this in a string variable
public ActionResult(..., string FeedingTime, ...){
}
normally this variable is embedded in a viewmodel such as
public class AnimalViewModel
{
public string Name { get; set; }
public string Type { get; set; }
public string FavoriteColor { get; set; }
public string FeedingTime { get; set; }
}
so that when you post
[HttpPost]
public ActionResult Index(AnimalViewModel viewModel){
...
}
it binds the viewmodel to the data automagically.
To answer your question more directly. I dont think theres a way to detect all radiobutton inputs on a page, you can only detect the results from that are posted from the radio button. There is no indication that the string posted was once the answer to a radiobutton. So, if you want to know the values of all radiobuttons on the page, you will simply have to check the values of the strings which are posted.

Partial editor to show single property of model

I have my model as follows
public class PlaceOrder
{
public int orderCode { set; get; }
public string Order_ID { set; get; }
public int orderDetailCode { set; get; }
[Required]
public string Topic { set; get; }
//50 more fields are there
}
Using editorforModel displays all the fields in the model. I want to have a editor helper which takes the property name and only shows editor for that specific property.
I wrote a create/edit/details actions for my model and working fine. What my final goals is that I want to have edit button next to every field on the details view. As soon I click on edit it allows to update and validate the input as well
EDIT
I am using following snippet for edit link
#(Html.Awe().PopupFormActionLink()
.LinkText("Edit")
.Name("editP")
.Url(Url.Action("PropertyEdit", "PlaceOrder", new
{
PropertyName = Html.NameFor(model => model.SubjectCategoryCode),
propertyValue = Html.IdFor(model => model.SubjectCategoryCode),
ordercode = Model.orderCode
})
)
.Title("Editor for " + Html.NameFor(model => model.SubjectCategoryCode))
and I want something that I pass the field name and it dispalys the relevant fields and do the validation
You could just use an EditorFor and a form for each field:
#using Html.BeginForm("action", "controller")
{
#Html.EditorFor(m => m.ordercode)
<input type="submit" />
}
#using Html.BeginForm("action", "controller")
{
#Html.EditorFor(m => m.orderDetailCode)
<input type="submit" />
}
Of course, you would need a different action for each item and you need a way to get the other values as well, since you're only posting one value to the controller. To achieve this you could include a hidden field with the id and retrieve the other values on the server.
There's the Html.EditorFor(m => m.Property) method for this (your model should be set to PlaceOrder to use this helper, as with any statically typed helpers).
Edit: Bah, Kenneth was faster :-).

ASP.NET MVC, passing Model from View to Controller

I'm having trouble with ASP.NET MVC and passing data from View to Controller. I have a model like this:
public class InputModel {
public List<Process> axProc { get; set; }
public string ToJson() {
return new JavaScriptSerializer().Serialize(this);
}
}
public class Process {
public string name { get; set; }
public string value { get; set; }
}
I create this InputModel in my Controller and pass it to the View:
public ActionResult Input() {
if (Session["InputModel"] == null)
Session["InputModel"] = loadInputModel();
return View(Session["InputModel"]);
}
In my Input.cshtml file I then have some code to generate the input form:
#model PROJ.Models.InputModel
#using(Html.BeginForm()) {
foreach(PROJ.Models.Process p in Model.axProc){
<input type="text" />
#* #Html.TextBoxFor(?? => p.value) *#
}
<input type="submit" value="SEND" />
}
Now when I click on the submit button, I want to work with the data that was put into the textfields.
QUESTION 1: I have seen this #Html.TextBoxFor(), but I don't really get this "stuff => otherstuff". I concluded that the "otherstuff" should be the field where I want to have my data written to, in this case it would probably be "p.value". But what is the "stuff" thing in front of the arrow?
Back in the Controller I then have a function for the POST with some debug:
[HttpPost]
public ActionResult Input(InputModel m) {
DEBUG(m.ToJson());
DEBUG("COUNT: " + m.axProc.Count);
return View(m);
}
Here the Debug only shows something like:
{"axProc":[]}
COUNT: 0
So the returned Model I get is empty.
QUESTION 2: Am I doing something fundamentally wrong with this #using(Html.BeginForm())? Is this not the correct choice here? If so, how do I get my model filled with data back to the controller?
(I cannot use "#model List< Process >" here (because the example above is abbreviated, in the actual code there would be more stuff).)
I hope someone can fill me in with some of the details I'm overlooking.
Change your view to some thing like this to properly bind the list on form submission.
#using(Html.BeginForm()) {
for(int i=0;i<Model.axProc.Count;i++){
<span>
#Html.TextBoxFor(model => model.axProc[i].value)
</span>
}
<input type="submit" value="SEND" />
}
In #Html.TextBoxFor(stuff => otherstuff) stuff is your View's model, otherstuff is your model's public member.
Since in the View you want to render input elements for the model member of a collection type (List), you should first create a separate partial view for rendering a single item of that collection (Process). It would look something like this (name it Process.cshtml, for example, and place into the /Views/Shared folder):
#model List<PROJ.Models.Process>
#Html.TextBoxFor(model => p.value)
Then, your main View would look like this:
#model PROJ.Models.InputModel
#using(Html.BeginForm()) {
foreach(PROJ.Models.Process p in Model.axProc){
#Html.Partial("Process", p)
}
<input type="submit" value="SEND" />
}
Also, check that the loadInputModel() method actually returns something, e.g. not an empty list.

MVC3 using CheckBox with a complex viewmodel

Right guys. I need your brains as I can't find a way to do this properly.
I have a view model:
public class EditUserViewModel
{
public User User;
public IQueryable<ServiceLicense> ServiceLicenses;
}
User is unimportant as I know how to deal with it.
ServiceLicenses has the following implementation:
public class ServiceLicense
{
public Guid ServiceId { get; set; }
public string ServiceName { get; set; }
public bool GotLic { get; set; }
}
Getting a checked list of users is cool. It works like a charm.
<fieldset>
<legend>Licenses</legend>
#foreach (var service in Model.ServiceLicenses)
{
<p>
#Html.CheckBoxFor(x => service.GotLic)
#service.ServiceName
</p>
}
</fieldset>
The problem I'm having is getting the updated ServiceLicenses object with new checked services back to the HttpPost in my controller. For simplicity lets say it looks like this:
[HttpPost]
public ActionResult EditUser(Guid id, FormCollection collection)
{
var userModel = new EditUserViewModel(id);
if (TryUpdateModel(userModel))
{
//This is fine and I know what to do with this
var editUser = userModel.User;
//This does not update
var serviceLicenses = userModel.ServiceLicenses;
return RedirectToAction("Details", new { id = editUser.ClientId });
}
else
{
return View(userModel);
}
}
I know I am using CheckBox the wrong way. What do I need to change to get serviceLicenses to update with the boxes checked in the form?
i understand that ServiceLicenses property is a collection and you want MVC binder to bind it to you action parameters property. for that you should have indices attached with inputs in your view e.g
<input type="checkbox" name = "ServiceLicenses[0].GotLic" value="true"/>
<input type="checkbox" name = "ServiceLicenses[1].GotLic" value="true"/>
<input type="checkbox" name = "ServiceLicenses[2].GotLic" value="true"/>
Prefix may not be mandatory but it is very handy when binding collection property of action method parameter. for that purpose i would suggest using for loop instead of foreach and using Html.CheckBox helper instead of Html.CheckBoxFor
<fieldset>
<legend>Licenses</legend>
#for (int i=0;i<Model.ServiceLicenses.Count;i++)
{
<p>
#Html.CheckBox("ServiceLicenses["+i+"].GotLic",ServiceLicenses[i].GotLic)
#Html.CheckBox("ServiceLicenses["+i+"].ServiceName",ServiceLicenses[i].ServiceName)//you would want to bind name of service in case model is invalid you can pass on same model to view
#service.ServiceName
</p>
}
</fieldset>
Not using strongly typed helper is just a personal preference here. if you do not want to index your inputs like this you can also have a look at this great post by steve senderson
Edit: i have blogged about creating master detail form on asp.net mvc3 which is relevant in case of list binding as well.

Resources