Lest say I got a view with this loop:
#foreach (var item in Model.Blogposts)
{
#item.Id
#Html.JQueryUI().Datepicker("Date")
}
So I got an Id and also a date choosen from the datePicker. Can someone show me how I can pass these two values to an Ajax that the loads a method?
$(".setDate").click(function () {
})
.load("/Home/Method?id=" + $(this).data("#itemID"));
});
Am I on the right way with what i´ve done so far? Help appreciated. Thanks!
EDIT:
Here is the method to which I want to pass the values:
public ActionResult SetDate(string valuefromDatePicker, string itemId)
{
//Code that updates the Time-property
//This I can figure out
return RedirectToAction("Test");
}
Which should mean that the view should look something like this:
#Html.JQueryUI().Datepicker("Date", new { data_url = Url.Action("SetDate", "Home", new { id = item.Id }) })
Should I also add a submit-button and give it the class .setDate?
You seem to be using some custom #Html.JQueryUI().Datepicker extension method that is not part of ASP.NET MVC. You should have at least mentioned the custom library you are using. In general most of the jQuery UI helper methods have overloads with an htmlAttributes parameter. This would allow you to add custom data-* attributes that you could use in your javascript code later. Consult the documentation of the library you are using about how to specify custom HTML attributes but your code might look something along the lines of:
#foreach (var item in Model.Blogposts)
{
#item.Id
#Html.JQueryUI().Datepicker("Date", new { data_url = Url.Action("Method", "Controller", new { id = item.Id }) })
}
and then in your javascript file:
$('.setDate').click(function () {
var url = $(this).data('url');
$('#result').load(url);
});
Related
So I have method in which I do some ajax:
function prodChange() {
console.log(this.value);
// ajax
var url = '#Url.Action("GetAdvProdList", "Contract")' + '?prod_id=' + this.value;
$.ajax({
url: url,
type: 'GET',
success: showAdvProd,
error: function() {
console.log("FAILSHAKUREHKGAHH");
}
});
}
The ajax returns successfully and calls this controller method.
public ActionResult GetAdvProdList(int prod_id) { // product id
// get advertising products for this product
OutlookMediaEntities1 db = new OutlookMediaEntities1();
var advsList = from printAdOption in db.print_ad_option
where printAdOption.print_product_id == prod_id
select printAdOption;
List<SelectListItem> adv_list = new List<SelectListItem>(); // list of ads
List<print_ad_option> advs = advsList.ToList(); // list from db
foreach (print_ad_option av in advs)
{
SelectListItem temp_item = new SelectListItem();
temp_item.Text = av.name;
temp_item.Value = av.print_ad_option_id.ToString();
adv_list.Add(temp_item);
}
ViewData["advproducts"] = new SelectList((IEnumerable<SelectListItem>)adv_list.ToList(), "Value", "Text");
return null;
}
I'm returning null because it doesn't work if I return View or PartialView, and I don't think I want it to return those things anyway. All I want is the viewdata stuff to be set.
The ajax worked well before I added code to use the view data. Unfortunately when I try to use the new ViewData in the ajax success method, I get this error:
"There is no ViewData item of type 'IEnumerable' that has the key 'print_ad_option_id'"
The thing is that I get this error when I first load the page, so it seems to be attempting to evaluate the "#Html.DropDownListFor..." before the showAdvProd function is called:
// called when the ajax returns a list of adv prods in a viewdata
function showAdvProd() {
// add drop down
$("#drdn1").append('#Html.DropDownListFor(m => m.print_ad_option_id, ViewData["advproducts"] as SelectList)');
}
The function that does ajax is called when an item is selected from a (different) dropdown menu, but with this error the page doesn't even load, so obviously the ajax function is never called and thus the controller method never called. So of course it won't recognize the viewdata...
I'm similarly creating a dropdown menu in another part of my form, using viewdata but without ajax, and it works fine. So I think something is wrong with my ajax or my controller method, not with how I'm using the viewdata.
Thank you in advance for any help!
The problem is that on your initial page load, the view engine will evaluate all the code blocks - anything with a '#' symbol in front of it. Thus it will try and look for a ViewData item called advproducts before it exists, even though that reference is within a javascript function that hasn't been called yet. Remember - code blocks (such as #Html.blahblahblah() are evaluated server side, while you are expecting your ajax to run on the client side, after the page has been sent to the client.
A couple of options: Returning a partial view should work. You could return a partialview that contains a dropdown and fill it from the ViewBag. That would look like this:
initial page:
...
<div id="advProductsSection"></div>
...
Your ajax would call the same function, but would return a partial view:
public ActionResult GetAdvProdList(int prod_id) { // product id
...
ViewData["advproducts"] = new SelectList((IEnumerable<SelectListItem>)adv_list.ToList(), "Value", "Text");
return View("_AdvProducts");
}
And then a partial view (Here named _AdvProducts.cshtml):
#Html.DropDownList("className", (IEnumerable<SelectListItem>) ViewBag["advproducts"])
Your ajax function would need to change to replace the div with the new partial:
success: function (result) {
$('#advProductsSection').html(result);
}
Or something like that..
A second alternative is to return JSON from the Action Method and populate a dropdown with that.
Your Controller:
...
return JSON(adv_list.ToList());
}
Then in your ajax success func:
success: function(list) {
// states is your JSON array
var $dropdown = $('#Dropdown');
$.each(list, function(i, product) {
$('<option>', {
value: list.Value
}).html(list.Text).appendTo($dropdown);
});
}
You'd need to cleat the dropdown again when prodchange is called.
I have a list of checkbox's and textbox's. I want to let the user add items to the list via a partial view modal popup.
After the user adds an item to the list, if any items on the original view have values in them, I want them preserved, and the page refreshed with the added items.
I want to send the full model back to the controller from the original view, I can then just add the new items to that model and pass the model back to the original page and have all my values preserved.
I could grab all the values and pass them via loops and such in javascript (very tedious), but I think the full model would be the easiest way.
I sawe a link from Laviak on a post from here..., but I can't get it to work.
it states....
If you need to send the FULL model to the controller, you first need the model to be available to your javascript code.
In our app, we do this with an extension method:
public static class JsonExtensions
{
public static string ToJson(this Object obj)
{
return new JavaScriptSerializer().Serialize(obj);
}
}
On the view, we use it to render the model:
<script type="javascript">
var model = <%= Model.ToJson() %>
</script>
You can then pass the model variable into your $.ajax call.
Has anyone got this to work???
Thanks
Bill
you can do something like this:
<script type="text/javascript">
var dataViewModel = #Html.Raw(Json.Encode(Model)); //Make sure you send the proper model to your view
function MethodPost(param1, param2, etc...) {
dataviewModel.Param1 = param1; //Or load a value from jQuery
dataviewModel.Param2 = $("#param2").val();
}
//Pass it to a controller method
$.post("#Url.Action(MVC.Home.PostMethodInController())", { viewModel: JSON.stringify(dataViewModel)} , function(data) {
//Do something with the data returned.
}
</script>
In the controller you get your class/model using Json.Net which is available on nuget.
public virtual ActionResult Index()
{
return View(new MyModelToView());//Send at least an empty model
}
[HttpPost]
public virtual JsonResult PostMethodInController(string viewModel)
{
var entity = JsonConvert.DeserializeObject<MyObject>(viewModel);
//Do Something with your entity/class
return Json(entity, JsonRequestBehavior.AllowGet);
}
Hope this helps.
I am developing an ASP.Net MVC 3 Web Application. One of my Razor Views contains a few Textboxes and a Drop Down List. When the User selects an option from the Drop Down List, I need a Partial View, or something like this, to appear below the Drop Down List preferable without a post back.
The thing is, it isn't as easy as a simply JQuery Hide and Show for the Partial View, when the User selects an option from the Drop Down List, I need their option to be sent to a method in the Controller, perform some logic based on this option, and then return some data to the Partial View.
I haven't really got much experience with AJAX, but I get the feeling this is the technology I need to use in order to fulfil my problem.
Has anyone ever had to code anything similar to what I have described above? And if so, is AJAX what I need to use?
Also, if anyone knows of any tutorials or code snipets I could look at to help, that would be greatly appreciated.
Thanks.
UPDATE
I have followed Ryan's answer, but unfortunately I am still having some problems. I have created the following JavaScript file which is then referenced in my View
$(document).ready(function () {
$("#myDDL").change(ChangeEventOfDDL);
function ChangeEventOfDDL(){
var dropDownValue = $('#myDDL').val();
//alert(dropDownValue);
$.ajax({ type: "GET",
url: '#Url.Action("SomePartialView","testAjax")',
data: {
id: dropDownValue
},
success: function(data) {
$('#someDivToLoadContentTo').html(data);
}
});
}
});
View
<select id="myDDL">
<option></option>
<option value="1">F1</option>
<option value="2">F2</option>
<option value="3">ST1</option>
<option value="4">ST2</option>
</select>
<div id="someDivToLoadContentTo">
</div>
My Controller then looks like this
public class testAjaxController : Controller
{
//
// GET: /testAjax/
LocumEntities context = new LocumEntities();
public ActionResult SomePartialView(int id)
{
var test = "Hello World";
return View(test);
}
}
However, my method 'SomePartialView' never gets hit. Does anyone know why?
Thanks.
Yes Ajax would be the easiest thing to use here. There are plenty of good Ajax tutorials around, just remember that what Ajax does is effectively a background POST, so you can do everything you would normally do with MVC, except within an existing page.
The way I would get this to work would be to have your code something like this:
public class SomeController{
public ActionResult SomePartialView(){
// Do some logic
return View("SomePartial");
}
}
Your Ajax would be something like:
function ChangeEventOfDDL(){
$.ajax({
url: '#Url.Action("SomePartialView","Some")',
success: function(data) {
$('#someDivToLoadContentTo').html(data);
}
});
}
I hope that helps at least a little bit.
Crucially with Ajax, you can add a data object to the function, which is passed as a querystring. This means you can send values from your page quite easily with ajax. Working with the above example, the Javascript would be:
function ChangeEventOfDDL(){
var dropDownValue = $('#ddl').val();
$.ajax({
url: '#Url.Action("SomePartialView","Some")',
data: {
id: dropDownValue
}
success: function(data) {
$('#someDivToLoadContentTo').html(data);
}
});
}
The Id value is linked with the parameters of the method in your MVC class:
public class SomeController{
public ActionResult SomePartialView(int id){
// Do some logic
var model = MakeModelWithSupplierId(id);
return View("SomePartial",model);
}
}
And there you have an interactive partial view that has been populated with the value from your drop down.
Since a controller can also return a partial view, you can do the following:
$('#idofyourdropdown').change(function () {
var theValue = $(this).val();
$.post('#Url.Action("Action","Controller")', {nameOfParameter: theValue, function(data) {
$('#divWhereYouWantToAttachData').html(data);
});
});
On the change event of your dropdown, send the selected value to your desired controller action, which will pass it to the partial view and return the rendered html. The html is received in the data var and can be attached to the dom, wherever you want it (see jQuery documentation for this).
This is a common use case.
What you need to do is
create a controller method that can take the parameters you need (read about MVC model binding before you do so)
write javascript that will harvest the data you want from your form and make a call to your new controller method and render the results below
In jQuery it goes something like this:
$("#yourDIV").load('/area/controller/method', { property1: 'asasd', property2: 'asdasdadfa'})
The second parameter of this call should be prepared based on the data you harvest from your form. (if you don't know how, then learn javascript)
I am becoming more familiar with MVC 3 and the RAZOR view engine. I have a question regarding layouts and shared controls on pages.
Let’s say I have a header section defined in my main layout. In that header is a dropdown I need to populate with project names. This dropdown will serve as a context for the entire site and is present on all pages. As an example, if the user selects “Project A” from the drop down, all of the views for the site will be based on “Project A”. Since this dropdown control is rather static and is used by the entire site, where is the best place to put the code to pull all the projects to display in the dropdown? In a Partial View? In a HTML helper? Another thought is, if a user selects a new value, they would be taken to a dashboard or similar page for that newly selected project. I am trying to figure out how to reuse this control on every page in the site without having to keep wiring it up in every possible controller.
You could use a child action along with the Html.Action helper. So you start by defining a view model:
public class ProjectViewModel
{
[DisplayName("Project name")]
public string ProjectId { get; set; }
public IEnumerable<SelectListItem> ProjectNames { get; set; }
}
then a controller:
public class ProjectsController: Controller
{
private readonly IProjectsRepository _repository;
public ProjectsController(IProjectsRepository repository)
{
_repository = repository;
}
public ActionResult Index(string projectId)
{
var projects = _repository.GetProjects();
var model = new ProjectViewModel
{
ProjectId = projectId,
ProjectNames = projects.Select(x => new SelectListItem
{
Value = x.Id,
Text = x.Name
})
};
return PartialView(model);
}
}
then the corresponding view (~/views/projects/index.cshtml):
#model ProjectViewModel
#Html.LabelFor(x => x.ProjectId)
#Html.DropDownListFor(
x => x.ProjectId,
Model.ProjectNames,
new {
id = "projects",
data_url = Url.Action("SomeAction", "SomeController")
}
)
Now all that's left is to render this widget inside the _Layout.cshtml:
#Html.Action("Index", "Products", new { projectid = Request["projectId"] })
And now we could put some javascript so that when the user decides to change the selection he is redirected to some other action:
$(function() {
$('#projects').change(function() {
var url = $(this).data('url');
var projectId = encodeURIComponent($(this).val());
window.location.href = url + '?projectid=' + projectId;
});
});
Another possibility is to put the dropdown inside an HTML form:
#model ProjectViewModel
#using (Html.BeginForm("SomeAction", "SomeController", FormMethod.Get))
{
#Html.LabelFor(x => x.ProjectId)
#Html.DropDownListFor(
x => x.ProjectId,
Model.ProjectNames,
new {
id = "projects",
}
)
}
so that inside the javascript we don't have to worry about building urls when the selection changes and simply trigger the containing form submission:
$(function() {
$('#projects').change(function() {
$(this).closest('form').submit();
});
});
We just did a similiar thing on a project.
First, you can't really put it in a section because you have to put that section on every view, you could put it in a partial but you would still have to call it from every view.
Second, you can't really put it in the Layout page because the layout page isn't passed any kind of model. So I created an html helper and referenced that in the layout page. There are lots of tutorials on creating html helpers so I won't put the code here. But essentially in your html helper you can make a database call to get all of your projects. Then you can create a select list using string builder in the html helper and return that to the layout page. We then used jquery to add an on change event to the select list. When the select list changed it loaded a new page. So for example, in your select list the value of each item could be the project id, then on change it redirects them to a page like /Projects/View?id=234 where 234 is your project id.
So things to research. 1. Creating HTML Helpers 2. JQUERY change event.
That should get you in the right direction. Let me know if you need any other help and I can post some code.
How do I actually get the JSON from a controller method using Ajax.ActionLink? I tried searching the website, but the closest thing I got was ASP.NET MVC controller actions that return JSON or partial html
And the "best answer" doesn't actually tell you how to get JSON from the SomeActionMethod in the ajax.actionlink.
Personally I don't like the Ajax.* helpers. In ASP.NET MVC < 3 they pollute my HTML with javascript and in ASP.NET MVC 3 they pollute my HTML with HTML 5 data-* attributes which are totally redundant (such as the url of an anchor). Also they don't automatically parse the JSON objects in the success callbacks which is what your question is about.
I use normal Html.* helpers, like this:
#Html.ActionLink(
"click me", // linkText
"SomeAction", // action
"SomeController", // controller
null, // routeValues
new { id = "mylink" } // htmlAttributes
)
which obviously generate normal HTML:
click me
and which I unobtrusively AJAXify in separate javascript files:
$(function() {
$('#mylink').click(function() {
$.post(this.href, function(json) {
// TODO: Do something with the JSON object
// returned the your controller action
alert(json.someProperty);
});
return false;
});
});
Assuming the following controller action:
[HttpPost]
public ActionResult SomeAction()
{
return Json(new { someProperty = "Hello World" });
}
UPDATE:
As requested in the comments section here's how to do it using the Ajax.* helpers (I repeat once again, that's just an illustration of how this could be achieved and absolutely not something I recommend, see my initial answer for my recommended solution):
#Ajax.ActionLink(
"click me",
"SomeAction",
"SomeController",
new AjaxOptions {
HttpMethod = "POST",
OnSuccess = "success"
}
)
and inside the success callback:
function success(data) {
var json = $.parseJSON(data.responseText);
alert(json.someProperty);
}