#html.dropdown onchange event MVC5 - asp.net-mvc-5

I have a View with a dropdownlist. I would like to select a value from the dropdownlist and depending on that value pull into the View a form related to that selection.
Looks like this:
I would like the form to appear below this ddlist and if the user changes the value in the ddlist, it would change the form.
Here's my "Add" View:
<div id="matSelContainer">
#Html.Action("SelectMaterial", "Materials", "Materials")
</div>
Here's the "SelectMaterial" View:
#model Procurement.Models.Material.MaterialType
#Html.Label("Select a Material Type: ")
#Html.DropDownListFor(
x => x.MaterialTypeList,
new SelectList(Model.MaterialTypeList, "MaterialTypeId", "Name")
)
Here's my Controller:
public ActionResult Add()
{
return View();
}
public ActionResult SelectMaterial()
{
materialTypes.LoadMaterialTypes();
return PartialView(materialTypes);
}
I would like to have a separate View for each Material Type and just call that View based on the selection in the ddlist.
Can someone show me how to achieve this?
Would I add a separate #Html.Action to the "Add" View and then in the Controller have another action return a PartialView?
But how to connect this with the Onchange event?
Update<<
Here's what is almost working for me:
"SelectMaterial" View:
#model Procurement.Models.Material.MaterialType
#Html.Label("Select a Material Type: ")
#Html.DropDownListFor(
x => x.MaterialTypeList,
new SelectList(Model.MaterialTypeList, "MaterialTypeId", "Name"),
new { #onchange="CallChangefunc(this.value)" })
<script>
function CallChangefunc(val) {
//alert("i am a " + obj.options[obj.selectedIndex].text);
//alert(obj.options[obj.selectedIndex].text);
window.location.href = "/Materials/MyMethod/" + val;
}
</script>
In my Controller I have this ActionResult:
public ActionResult MyMethod(string value)
{
return PartialView();
}
My controller is getting called when I change selection but the value coming in is null. I can see on the browser address bar that the expected selected value is being passed. Why is it null in controller? (I tried adding an [HttpPost] to ActionResult with no luck.)

Related

How Using tempdata to pass data entered by user in a data field from view to another view

I am new to MVC. I one please help me on how to assign value entered by user (for instance table column such as username) in a view to TempData.
I also want to pass the assigned data to a column in another view
In your view, add a form field:
<input name="myfield" type="text" />
In your controller's action, get the field and store it in TempData:
public ActionResult ProcessIt(string myfield)
{
TempData["yourkey"] = myfield;
return RedirectToAction("SomeOtherAction");
}
Now you can use it in the SomeOtherAction view:
<div>Entered data: #TempData["yourkey"]</div>
Thanks, I am creating web test, the controller for the question
public async Task Create([Bind(Include = "QuestionID,Question")]
TestQuestion testQuestion, string command, FormCollection QuestionData)
{
if (ModelState.IsValid)
{
db.TestQuestions.Add(testQuestion);
await db.SaveChangesAsync();
return RedirectToAction("Create", "TestOptions");
}
The controller for the options:
public async Task Create([Bind(Include = "OptionID,QuestionID,OptionA")] TestOption testOption)
{
if (ModelState.IsValid)
{
db.TestOptions.Add(testOption);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.QuestionID = new SelectList(db.TestQuestions, "", "", testOption.QuestionID);
return View(testOption);
}
I desire to display the question just entered by the user in the Create method of the option controller so that the user would enter the options for question.
The program create a dropdownlist of all the questions l've enter before, but I want only the last question should show in the redirected view.

Pass #Html.DropDownList selection using #Html.ActionLink with ViewModel to Controller

I've been reading through posts for two days regarding this, and still have not figured out the answer. I want to capture the DropDownList selection within my ModelView, pass this to a #Html.ActionLink, which will send it back to a specific Action within the Controller.
My ViewModel:
public class ViewModelShipments
{
public ViewModelShipments()
{
tblShipments = new tblShipments();
}
public tblShipments tblShipments;
public IEnumerable<SelectListItem> ShipmentIDsList;
public string SelectedShipmentID;
}
My Controller:
public ActionResult SelShipment(string SelectedShipmentID)//for ShipmentID change via DropDownList
{
int id = db.tblShipments.Max(p => p.ShipmentID); // find last ShipmentID
if (SelectedShipmentID != null)
{
id = Int32.Parse(SelectedShipmentID);//convert text to int
}
My View:
#Html.DropDownListFor(expression: model=>model.SelectedShipmentID,selectList: Model.ShipmentIDsList) #* render DropDownList object*#
#Model.SelectedShipmentID #* display value of SelectedShipmentID *#
<!-- Upon Click, send selected ID to controller -->
<!-- the ActionLink is working, but the routeValues: always contain NULL -->
#Html.ActionLink(linkText: "Submit", actionName: "SelShipment", controllerName: "Shipment", routeValues: Model.SelectedShipmentID, htmlAttributes: null)
Why does the ActionLink(..., routeValues: Model.SelectedShipmentID,...) always return NULL to the Controller ? The Model.SelectedShipmentID is not updated with the DropDownList selected id. Please help as I'm running out of time on this.
Razor code is parsed on the server before its sent to the view, so the value of your route parameter will be the initial value of SelectedShipmentID. Selecting a value from a dropdownlist does not change the url you have already rendered.
You could use javascript/jquery to handle the dropdownlist's .change() event (or the links .click() event) to update the url, however the better way to handle this is by using a form that makes a GET to your controller method
#model ViewModelShipments
#using (Html.BeginForm("SelShipment", "Shipment", FormMethod.Get))
{
#Html.DropDownListFor(m => m.SelectedShipmentID, Model.ShipmentIDsList, "-Please select-")
<input type="submit" />
}
Note the last parameter of DropDownListFor() add a label option allowing you to post back null but not sure if this is appropriate for you.
Since your binding to a value which is int then both your model property and method parameter should be int? not string. In additiona you should change the logic in the controller so that you are not making unnecessary database calls when a valid value is passed to the method.
public ActionResult SelShipment(int? SelectedShipmentID)
{
if (!SelectedShipmentID.HasValue)
{
// only necessary to call database if SelectedShipmentID is null
SelectedShipmentID = db.tblShipments.Max(p => p.ShipmentID)
}
....
}
Side note: From your view model properties, I assume you wanting to display some data in the view based on the value of the selected ShipmentID. If so you should consider using ajax to post the selected value to a controller method that returns the tblShipments data based on the value, either as a partial view or as json, and update the current page, rather than doing a complete page refresh each time.

How to attach an existing View to a controller action?

How can I attach an existing View to an Action?
I mean, I've already attached this very View to an Action, but what I want is to attach to a second Action.
Example:
I've an Action named Index and a View, same name, attached to it, right click, add view..., but now, how to attach to a second one? Suppose an Action called Index2, how to achieve this?
Here's the code:
//this Action has Index View attached
public ActionResult Index(int? EntryId)
{
Entry entry = Entry.GetNext(EntryId);
return View(entry);
}
//I want this view Attached to the Index view...
[HttpPost]
public ActionResult Rewind(Entry entry)//...so the model will not be null
{
//Code here
return View(entry);
}
I googled it and cant find an proper answer...
It's possible?
you cannot "attach" actions to views but you can define what view you want be returned by an action method by using Controller.View Method
public ActionResult MyView() {
return View(); //this will return MyView.cshtml
}
public ActionResult TestJsonContent() {
return View("anotherView");
}
http://msdn.microsoft.com/en-us/library/dd460331%28v=vs.98%29.aspx
Does this help? You can use the overload of View to specify a different view:
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Index()
{
ViewBag.Message = "Hello I'm Mr. Index";
return View();
}
//
// GET: /Test/Index2
public ActionResult Index2()
{
ViewBag.Message = "Hello I'm not Mr. Index, but I get that a lot";
return View("Index");
}
}
Here is the View (Index.cshtml):
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>#ViewBag.Message</p>

open a MVC4 view inside a jquery Dialog

I want to take a view and instead of opening a new page I want to just open that view inside a Jquery dialog. I was just wondering how it's done or if possible.
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Jquery_Dialog.Models;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
namespace Jquery_Dialog.Controllers
{
public class HomeController : Controller
{
private IEnumerable<Product> Products
{
get
{
return new List<Product>
{
new Product {ProductID = 1, Name = "Train", Category = "Toy", Price = 29.99M},
new Product {ProductID = 2, Name = "Truck", Category = "Toy", Price = 19.99M},
new Product {ProductID = 3, Name = "Bread", Category = "Food", Price = 2.49M},
new Product {ProductID = 4, Name = "Cookies", Category = "Food", Price = 2.99M}
};
}
}
public ActionResult Index()
{
IEnumerable<Product> productList = Products;
return View(productList);
}
public ActionResult Details(int id)
{
Product model = Products.Where(p => p.ProductID == id).SingleOrDefault();
return Request.IsAjaxRequest() ? PartialView(model) : PartialView(model);
}
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}
Index.cshtml
#model IEnumerable<Jquery_Dialog.Models.Product>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css " />
<script src="http://code.jquery.com/jquery-1.8.2.js "></script>
<script src="http://code.jquery.com/ui/1.9.1/jquery-ui.js "></script>
<table> #foreach (var item in Model) {
<tr>
<td>
#Html.ActionLink(item.Name, "Details", new { id = item.ProductID }, new { #class = "ajax-details" })
</td>
</tr>
}
</table>
<div id="dialog" title="Title of dialog">
<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
</div>
<script>
$(function () {
$('.ajax-details').on('click', function (e) { // bind to click event
// go get the page using the link's `href`
$.get($(this).prop('href'), function (response) {
$(response).dialog(); // take the response and throw it up in a dialog
// optional: Use jQuery UI's options to specify buttons and other
// settings here as well. It's also probably a good idea to
// bind the close event and $().remove() this element from
// the page on close since the user can click links over and
// over. (prevent DOM overload of hidden elements)
});
e.preventDefault(); // don't let it continue on
});
});
</script>
<script>
$("#dialog").dialog();
</script>
As you can see I have a simple dialog that opens a div but I want to be able to open the details view instead of clicking the ActionLink and going to a different page, I want to be able to click the ActionLink and have it open up in the dialog.
Assuming you make the ActionLink a little more accessible (by using a class name for instance):
#Html.ActionLink(item.Name, "Details", new { id = item.ProductID },
/* htmlAttributes: */ new { #class = "ajax-details" })
You also make a modification to the action so we can fetch partial contents when it's an ajax request:
public ActionResult Details(int id)
{
// this is another way of making sure that AJAX calls get partial content,
// but a normal visit would render the entire page.
return Request.IsAjaxRequest() ? PartialView(model) : View(model);
}
Optional You could also adjust your _ViewStart.cshtml file to do the same if this was common place on the website to render partial views/ajax supplementing:
#{
Layout = IsAjax ? null : "~/Views/Shared/_Layout.cshtml";
}
Now, we wire it up with AJAX. Again, reference the class name we game the link earlier (ajax-details):
$('.ajax-details').on('click',function(e){ // bind to click event
// go get the page using the link's `href`
$.get($(this).prop('href'), function(response){
$(response).dialog(); // take the response and throw it up in a dialog
// optional: Use jQuery UI's options to specify buttons and other
// settings here as well. It's also probably a good idea to
// bind the close event and $().remove() this element from
// the page on close since the user can click links over and
// over. (prevent DOM overload of hidden elements)
});
e.preventDefault(); // don't let it continue on
});
Don't have the opportunity to test it, but should get you in the ball park. if it doesn't get you close enough, let me know and I'll revisit the answer and adjust.

Why ViewData not work

I have MVC2 view in which there is a grid and image button. When image button is clicked, it will pass the data of grid's currentPage, filter and orderBy fields ... to another controller. The code is,
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MaintenanceEditableViewModel>" %>
"Image button"
<a href="<%: Url.Action("ExportToExcel", "ExportExcelButton", new { resourceId = ViewData["resourceId"], pagenum = ViewData["page"], orderBy = ViewData["orderBy"], filter = ViewData["filter"] }) %>">
<img src='<%: Url.Content("~/Content/Images/ExportExcelButton.gif") %>' /></a>
"Grid"
<%= Html.Telerik().Grid<MaintenanceAthletesResultsViewModel>()
.Name("Grid")
.TableHtmlAttributes(new { style = "font-size:8pt;" })
.HtmlAttributes(new { style = "height:335px" })
.DataKeys(k => k.Add(k2 => k2.ResultID))
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("AthletesResultsAjax", "Maintenance")
...
"Action to initialize the grid in Maintenance controller"
public ActionResult AthletesResults(string id, bool editable)
{
ViewData["resourceId"] = id;
this._resourceBL.PopulateMaintenanceResourcesViewData(id, this.SelectedSport());
MaintenanceEditableViewModel model = new MaintenanceEditableViewModel { Editable = editable };
return View(model);
}
[GridAction]
public ActionResult AthletesResultsAjax(string id, int page, string orderBy, string filter)
{
List<MaintenanceAthletesResultsViewModel> model = null;
if (!string.IsNullOrEmpty(id))
{
ViewData["page"] = page;
ViewData["orderBy"] = orderBy;
ViewData["filter"] = filter;
model = this._resourceBL.GetMaintenanceAthletesResultsViewModel(int.Parse(id));
}
return View(new GridModel(model));
}
public ActionResult ExportToExcel(string resourceId, string pagenum, string orderBy, string filter)
The strange thing is that only ViewData["resourceId"] (set in initialization of view) is able to be passed. The 3 parameters, ViewData["page"], ViewData["orderBy"], ViewData["filter"] (set in grid ajax action) can not be passed. All 3 are null in ExportToExcel and so I think they are not correctly stored in ViewData (I am not sure how to check ViewData when image button is pressed). I am confused and need help on this.
Thanks
I don't see how/where you're sending those arguments into the AthletesResultsAjax action. The signature of the dataBinding.Ajax().Select() function you're using only specifies the action and the controller name. How is it going to know what those values are? You need to specify a routeValues object to send the appropriate data to the controller action. If you debug the code and put a breakpoint in your ajax action, do the actual values come through? I could be quite off here but I think your problem is more on this end than on how the data is being stored in the ViewData.
I think the problem is that ViewData is mainly used pass data from Controller to View and in your case you have Controller -> View -> Controller. I think Telerik Knowledge Base has a good solution how to provide additional data to your export action. Telerik Knowledge Base
<%= Html.ActionLink("Export to Excel", "Export", new { page = 1, orderBy = "~", filter = "~"}, new { id = "exportLink" }) %>
<script type="text/javascript">
function onDataBound() {
var grid = $(this).data('tGrid');
var $exportLink = $('#exportLink');
var href = $exportLink.attr('href');
href = href.replace(/page=([^&]*)/, 'page=' + grid.currentPage);
href = href.replace(/orderBy=([^&]*)/, 'orderBy=' + (grid.orderBy || '~'));
href = href.replace(/filter=(.*)/, 'filter=' + (grid.filterBy || '~'));
$exportLink.attr('href', href);
}
</script>
The script dynamically updates Export-links url when data is received & rendered (OnDataBound) to the screen. It should then bind nicely on the Controller side.
If you're more familiar with JavaScript then you should probably put an click event to the export button and make GET request in the JavaScript side. Then you don't have make that ugly looking url modifications.
I hope this helps!

Resources