how to read date from calendar in MVC into Model property - asp.net-mvc

I have Model properties
public DateTime SelectedDate { get; set; }
public DateTime SelectedDateTo { get; set; }
The view has
<input id="Testdate-Field" type="text" style="width: 125px;" value="#Html.DisplayTextFor(m=>m.SelectedDate)" /> To
<input id="TestdateTo-Field" type="text" style="width: 125px;" value="#Html.DisplayTextFor(m=>m.SelectedDateTo)" />
To show the calendar in the view I have
$("#Testdate-Field").bind("click", function(event) {
$( "#Testdate-Field").datepicker();
});
$("#TestdateTo-Field").bind("click", function(event) {
$( "#TestdateTo-Field").datepicker();
});
Now, 2 problems
When I click in the input box for the first time, the calendar doesn't appear till I click somewhere else and then in the input box for date.
When I pick a date from the calendars my model properties SelectedDate and SelectedDateTo do not change and remain the default values when I read them. What do I need to do to read the input dates?
---Update---
Added this in ready as per the suggestion
$("#Testdate-Field").datepicker();
$("#TestdateTo-Field").datepicker();
and the first problem is solved! Now how do I bind what I have selected in the datefield to my model properties?

For question 1, do not put your .datepicker() code in the bind event. Simply execute those on document ready:
<script>
jQuery(document).ready(function ($) {
$( "#Testdate-Field").datepicker();
$( "#TestdateTo-Field").datepicker();
});
</script>
For your second question, use Html helpers to generate your inputs and then in your controller you can easily bind them: instead of using DisplayTextFor inside of input tags YOU generate, use TextBoxFor to generate the input tags for you:
ViewModel:
public class SampleViewModel
{
// other properties here
public DateTime SelectedDate { get; set; }
public DateTime SelectedDateTo { get; set; }
// other properties here
}
View:
#model SampleClassViewModel
#using(Html.BeginForm())
{
#Html.TextBoxFor(m => m.SelectedDate, new { class = "datepickers" })
#Html.TextBoxFor(m => m.SelectedDateTo, new { class = "datepickers" })
<input type="submit" />
}
<script>
jQuery(document).ready(function ($) {
$( ".datepickers").datepicker();
});
</script>
There are many way to bind your properties, here are a couple...
Controller option 1:
[HttpPost]
public ActionResult SomeControllerAction(SampleViewModel model)
{
// do work...
}
Controller option 2:
[HttpPost]
public ActionResult SomeControllerAction()
{
var model = SomeServiceMethodToBuildModel();
this.TryUpdateModel(model);
// do work...
}
Thanks!

Related

How to pass a selected object to a Controller using Html.DropDownListFor

I'm currently trying to pass a object called DropDown from a View to a controller action using HTML.DropDownFor() and a form.
The object looks like this:
public class DropDown
{
public int id { get; set; }
public string value { get; set; }
}
The view Model looks like this:
public class GraphViewModel
{
public DropDown SelectedGraphTypeDropDown { get; set; }
public IEnumerable<DropDown> GraphTypeDropDowns { get; set; }
}
The controller action looks like this:
[HttpPost]
public string GetTestData(DropDown SelectedGraphTypeDropDown)
{
// use above object here
}
And the view like so:
#using (Html.BeginForm("GetTestData", "Graph", FormMethod.Post))
{
#Html.DropDownListFor(m => m.SelectedGraphTypeDropDown, new SelectList(Model.GraphTypeDropDowns, "id", "value"))
<input type="submit" />
}
Rendered HTML
What I expect to happen is the selected GraphType will be passed to the GetTestData action and resolved as a whole object called "SelectedGraphTypeDropDown".
I have debugged through it and it seems that the selected GraphType id (int) is passed to the controller but the whole object is not. I have also tried to pass each field of the selectedGraphTypeDropDown but this wont work as the fields are set after the page is rendered.
Also is there a way to pass the full viewModel to the controller?
Any advice would be apricated thanks!
Firstly,dropdown cannot pass a model,but you can add hidden input to bind value.Here is a demo:
view:
#using (Html.BeginForm("GetTestData", "Graph", FormMethod.Post))
{
#Html.DropDownListFor(m => m.SelectedGraphTypeDropDown.id, new SelectList(Model.GraphTypeDropDowns, "id", "value"))
<input id="value" name="SelectedGraphTypeDropDown.value" hidden/>
<input type="submit" />
}
js(js will bind selected value to hidden input):
$(function () {
$("#value").val($(this).find("option:selected").text());
})
$("#SelectedGraphTypeDropDown_id").change(function () {
$("#value").val($(this).find("option:selected").text());
})
result:

Can't bind checkbox in partial view to the main model (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>

how to get partialview data in controller

I am using three partialview on a single view, I have a submit button on clicking of which I want to send information to database, I have to retrieve data from all the partialview.
Can You please provide me correct information to do it.
Darin I m using L2S so when I drag my stored procedure, I get code some thing like this in
[global::System.Data.Linq.Mapping.FunctionAttribute(Name="SP_Name")]
public int SP_Name(
[global::System.Data.Linq.Mapping.ParameterAttribute(Name="EmployeeID", DbType="Int")] System.Nullable<int> EmployeeID
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), EmployeeID);
encounterID = ((System.Nullable<int>)(result.GetParameterValue(293)));
return ((int)(result.ReturnValue));
}
}
Updated
<script language="javascript" type="text/javascript">
$(function () {
$('#Form1').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (data) {
var message = data.Result;
$('#Result').html(message);
}
});
return false;
});
});
</script>
In my Controller I am using
public ActionResult Index(FormCollection frm)
{
My Code ---------------------
return Json(new { Result = "Success" });
}
When I return this I m getting a file in post back and it ask me to save it.
I have checked using flidder, in URL it shows me that the path as / only
where as If I fill any particular partialview It shows something like /Controller Name/Partialview
Can You help me with this problem
Well, sending data to a controller action is usually done by performing an HTTP request to this controller action. There are different ways of performing an HTTP request:
Use a <form> tag pointing to this action
Use AJAX
So if you go with the first approach you could have a single <form> wrapping all the partials which would have multiple submit buttons (with different names). Then when you click on one submit buttons all the input fields will be sent to the controller action and then inside the controller action you could process the data based on which submit button was clicked.
If you use the second option, well, then simply harvest the values you need to be sent uipon button click and send them along the AJAX request.
UPDATE:
As requested in the comments section here's how the first technique could be put into action. It uses two partials instead of three but it could be easily extrapolated.
As always you start by defining a view model which will represent the data you would like to work with on this particular view:
public class MyViewModel
{
public Partial1ViewModel Model1 { get; set; }
public Partial2ViewModel Model2 { get; set; }
}
public class Partial1ViewModel
{
public string Foo { get; set; }
}
public class Partial2ViewModel
{
public string Bar { get; set; }
}
Then a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Model1 = new Partial1ViewModel { Foo = "foo" },
Model2 = new Partial2ViewModel { Bar = "bar" },
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// Here you have access to model.Model1.Foo and model.Model2.Bar =>
var button = "";
if (!string.IsNullOrEmpty(Request["submit1"]))
{
// submit1 button was used
button = "submit1";
}
else if (!string.IsNullOrEmpty(Request["submit2"]))
{
// submit2 button was used
button = "submit2";
}
var result = string.Format("thanks for submitting using {0}", button);
return Content(result, "text/plain");
}
}
and then a main view (~/Views/Home/Index.cshtml):
#model MyViewModel
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.Model1)
#Html.EditorFor(x => x.Model2)
}
and the two corresponding editor templates (or partials if you will):
~/Views/Home/EditorTemplates/Partial1ViewModel.cshtml:
#model Partial1ViewModel
<h2>Partial 1</h2>
<div>
#Html.LabelFor(x => x.Foo)
#Html.EditorFor(x => x.Foo)
<input type="submit" value="Submit me!" name="submit1" />
</div>
~/Views/Home/EditorTemplates/Partial2ViewModel.cshtml:
#model Partial2ViewModel
<h2>Partial 2</h2>
<div>
#Html.LabelFor(x => x.Bar)
#Html.EditorFor(x => x.Bar)
<input type="submit" value="Submit me!" name="submit2" />
</div>

MVC Radio Button Lists are not grouped when using the HtmlHelper class

Having trouble creating a list of radio buttons that are grouped together, in MVC 3 specifically, but this also applies to MVC 2.
The problem arises when radio buttons are generated using Html helpers and the model is part of an array.
Here is the cut down version of my code.
public class CollectionOfStuff {
public MVCModel[] Things { get; set }
}
/*This model is larger and represents a Person*/
public class MVCModel {
[UIHint("Hidden")]
public string Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
/*Assigned to new CollectionOfStuff property Things*/
var items = new[] {
new MVCModel() { Id="0" Name = "Name here" }, new MVCModel() { Id="1" Name = "Name there" }
}
My parent view
#model CollectionOfStuff
#for (int i = 0; i < Model.Things.Length; i++) {
#Html.EditorFor(m => m.Things[i]);
}
My view rendering individual MVCModel objects
#Model MVCModel
#{
var attr = new {
Checked = Model.IsSelected ? "checked=checked" : ""
};
}
#Html.RadioButtonFor(model => model, Model.Id, attr)
Produces this output:
<input type="radio" value="0" name="MVCModel[0]" id="MVCModel_0_" data-val-required="You need to choose" data-val="true" />
<input type="radio" value="1" name="MVCModel[1]" id="MVCModel_1_" data-val-required="You need to choose" data-val="true" />
The radio buttons are not grouped, however it has the obvious advantage of writing out the meta data for validation.
The other way is by calling:
#Html.RadioButton(name: "GroupName", value: Model.Id, isChecked: Model.IsSelected)
Produces:
<input type="radio" value="0" name="MVCModel[0].GroupName" id="MVCModel_0__GroupName">
<input type="radio" value="1" name="MVCModel[1].GroupName" id="MVCModel_1__GroupName">
Again, this doesn't produce the desired result. It's also missing the validation meta data.
Another other option is creating a custom template, but the problem with this approach is that all the meta data required for validation is not present.
Any ideas on how I can create grouped radio buttons or obtain meta data so I can create a template myself?
You haven't shown how does your view model look like but you could group them by some property. So let's take an example:
public class MyViewModel
{
[Required]
public string SomeProperty { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel());
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
View:
#model AppName.Models.MyViewModel
#using (Html.BeginForm())
{
<div>A: #Html.RadioButtonFor(x => x.SomeProperty, "a")</div>
<div>B: #Html.RadioButtonFor(x => x.SomeProperty, "b")</div>
#Html.ValidationMessageFor(x => x.SomeProperty)
<input type="submit" value="OK" />
}
Now if you want to preselect some radio simply set the property of the view model to the corresponding value of the radio instead of writing some ugly C# code in your views:
public ActionResult Index()
{
var model = new MyViewModel
{
SomeProperty = "a" // select the first radio
};
return View(model);
}
Obviously this technique works with any simple property type (not only strings) and with any number of radio buttons that could be associated to this property.

Understanding how DropDownListFor is working in MVC3

I'm new to MVC3 and have been working on a small site using EF and 'Code First'. I'm trying to do a few things in a view dealing with a drop down list and am wondering what the best way to go about them is. I want a user to be able to select a rule from the dropdownlist, and depending upon which rule was selected, I would like a label on the page to show the rule name (without posting). I also need to be able to send the selected rule onto the next page. I haven't added all of the necessary fields to the view yet because I'm really at a loss on how it should work. How should I go about trying to do this?
I've got my model:
public class D1K2N3CARule
{
public int ID { get; set; }
[Required]
public int Name { get; set; }
[Required]
public string Rule { get; set; }
public D1K2N3CARule(int name, string rule)
{
Name = name;
Rule = rule;
}
public D1K2N3CARule()
{
Name = 0;
Rule = "";
}
}
My ViewModel:
public class D1K2N3CARuleViewModel
{
public string SelectedD1K2N3CARuleId { get; set; }
public IEnumerable<D1K2N3CARule> D1K2N3CARules { get; set; }
}
My Controller:
public ActionResult Index()
{
var model = new D1K2N3CARuleViewModel
{
D1K2N3CARules = db.D1K2N3DARules
};
return View(model);
}
and my View:
'#model CellularAutomata.Models.D1K2N3CARuleViewModel
#{
ViewBag.Title = "Index";
}
<asp:Content id="head" contentplaceholderid="head" runat="server">
<script type="text/javascript">
</script>
</asp:Content>
<h2>Index</h2>
<table>
<tr>
<td>
#Html.DropDownListFor(
x => x.D1K2N3CARules,
new SelectList(Model.D1K2N3CARules, "ID","Rule")
)
</td>
</tr>
</table>'
I want a user to be able to select a rule from the dropdownlist, and depending upon which rule was selected, I would like a label on the page to show the rule name (without posting)
You will need javascript here. jQuery would be perfect for the job. I would start by providing a deterministic id for the dropdown because if you run this view inside a template there could be prefixes added to the id which would ruin our javascript id selectors (see below):
#Html.DropDownListFor(
x => x.D1K2N3CARules,
new SelectList(Model.D1K2N3CARules, "ID", "Rule"),
new { id = "ruleDdl" }
)
then provide some container which will receive the selected value:
<div id="ruleValue" />
and finally in a separate javascript file subscribe for the change event of the dropdown list and update the container with the selected value/text:
$(function() {
// subscribe for the change event of the dropdown
$('#ruleDdl').change(function() {
// get the selected text from the dropdown
var selectedText = $(this).find('option:selected').text();
// if you wanted the selected value you could:
// var selectedValue = $(this).val();
// show the value inside the container
$('#ruleValue').html(selectedText);
});
});
I also need to be able to send the selected rule onto the next page.
You could put your dropdown inside a form
#using (Html.BeginForm("NextPage", "Foo"))
{
#Html.DropDownListFor(
x => x.D1K2N3CARules,
new SelectList(Model.D1K2N3CARules, "ID","Rule")
)
<input type="submit" value="Go to the next page" />
}
and the NextPage controller action will receive the selected value.

Resources