I have a dropdown list in a View. And if I change the selection, I want to change immediately the values in the View. The textbox of Type and Description.
How do you do that?
#Model GenreModel
#using (Html.BeginForm("EditGenre", "Home", FormMethod.Post))
{
#model GenreModel
<div class="text-center">
<h1 class="display-4">Edit genre</h1>
<p> <input type="submit" value="submit" name="Save" /></p>
<p>
<label>Select genre: </label>
#Html.DropDownListFor(Model => Model.Description, new SelectList(ViewBag.GenreList, "Description", "Description"), new { onchange = "onChangeSelection(this.value);" });
</p>
<p>
<label>Type</label>#Html.TextBoxFor(Model => Model.Type)
</p>
<p>
<label>Description</label>#Html.TextBoxFor(Model => Model.Description)
</p>
</div>
}
This is the method in the Controller.
[HttpPost]
public IActionResult EditGenre(string description)
{
var dto = _genreService.GetGenreByName(description);
var model = _mapper.Map<GenreDto, GenreModel>(dto);
ViewBag.GenreList = _genreService.GetAllGenres().OrderBy(g => g.Description);
return View(model);
}
and finally:
<script>
function onChangeSelection(val) {
{
$.ajax({
url: #Url.Action("EditGenre", "Home"),
//type: "POST",
data: { description: val },
success: function (data) {
// put result of action into element with class "result"
$('.result').html(data);
},
error: function () {
alert(val + ' not found.');
}});
}
</script>
Change the DropDownList like this:
#Html.DropDownListFor(Model => Model.Description, new SelectList(ViewBag.GenreList, "Description", "Description"));
And submit the form in the onchange function:
<script>
$("#Description").on("change", function () {
$(this).closest("form").submit();
})
</script>
It seems my DropDownList didn't fire a Submit. I leave the javascript and using a hidden field.
And this solution works fine.
<p>
<label>Select genre: </label>
#Html.Hidden("#Discription")
#Html.DropDownListFor(Model => Model.Description, new SelectList(ViewBag.GenreList, "Description", "Description"), new { onchange = "this.form.submit();" });
</p>
Related
I have the following problem:
A collection of "Gifts" gets passed as a parameter to a view.
Each item inside this collection is a object from the Model class "Gift".
There are only two properties inside this class: name and price.
I put the class inside the controller for the sake of simplicity.
This is the action method:
// GET: Order/CreateGift
[HttpGet]
public ActionResult CreateGift()
{
var initialData = new[]
{
new Gift{ Name = "Tricycle", Price = 69.95 },
new Gift{ Name = "PS4 game", Price = 29.99 },
new Gift{ Name = "Lazergun", Price = 49.99}
};
return View(initialData);
}
On the view I can dynamically add new items to the collection, thanks to the BeginCollectionItem Html helper.
This is my View:
#model IEnumerable<DemoWebShop.Controllers.Gift>
<script src="~/Scripts/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) { $("#editorRows").append(html); }
});
return false;
});
}); // end document.ready function
</script>
<h2>Gift List</h2>
What do you want for your birthday?
#using (Html.BeginForm())
{
<div class="form-horizontal">
<div id="editorRows">
#foreach (var item in Model)
{
Html.RenderPartial("GiftEditorRow", item);
}
</div>
#Html.ActionLink("Add another...", "BlankEditorRow", null, new { id = "addItem" })
<input type="submit" value="Finished" />
#*<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Aanmaken" class="btn btn-default" />
</div>
</div>*#
</div>
}
This is the partial view called "GiftEditorRow" :
#using HtmlHelpers.BeginCollectionItem
#model DemoWebShop.Controllers.Gift
#{
Layout = null;
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="editorRow">
#using (Html.BeginCollectionItem("gifts"))
{
<label>Name: </label>
#Html.TextBoxFor(x => x.Name);
<label>Price: </label>
#Html.TextBoxFor(x => x.Price, new { size = 4 });
<br />
}
</div>
}
Inside my controller I also have this actionmethod:
public ViewResult BlankEditorRow()
{
return View("GiftEditorRow", new Gift());
}
Only the First item that already existed inside the collection, gets passed to the HTTP Post method in my controller.
I found my mistake.
The partial view "GiftEditorRow" still contains the following:
#using (Html.BeginForm()){.....}
If you remove this, it should work.
This is my partial view now:
#using (Html.BeginCollectionItem("gifts"))
{
<label>Name: </label>
#Html.TextBoxFor(Model => Model.Name);
<label>Price: </label>
#Html.TextBoxFor(Model => Model.Price, new { size = 4 });
<br />
}
Now I get all items instead of just the first one.
When I try to add Ajax to pass another data into my action controller my model parameter was affected the value was null and my Ajax parameter has a value. I do not think it is because I am using Html.beginform('index', 'payable') and I used Ajax url: '#Url.Action("index", "payable")', with the same ActionResult.
You can see the reference below.
#using (Html.BeginForm("index", "payable", FormMethod.Post, new { enctype = "multipart/form-data" }))<div class="col-md-2">
<div class="form-group">
#Html.LabelFor(x => x.Amount, new { #class = "form-label" })
#Html.TextBoxFor(x => x.Amount, new { #class = "form-control" })
</div>
</div>
<div class="col-md-2">
<div class="form-group">
#Html.LabelFor(x => x.ImagePath, new { #class = "form-label" })
<input type="file" name="file" id="files" />
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<button type="submit" id="btnUpload" class="btn btn-primary btn-sm" onclick="saveSelected()"><i class="fas fa-save"></i> Submit Payment</button>
</div>
</div>{
My Ajax
function saveSelected() {
$.ajax({
url: '#Url.Action("index", "payable")',
type: 'POST',
data: { ids: ids },
traditional: true,
success: function (data) {
alert("success");
}
});
}
My Controller
public ActionResult Index(PayableFormModel model, HttpPostedFileBase file, int[] ids)
{
return View();
}
Html.Beginform and ajax cannot use at same time,even you add a
onclick function. So the ajax won't work and all data are submitted
by form. If you want to submit model and any other data, put all them into form or only use ajax.
When you upload file, model cannot get file's name or path directly. You should store file into a folder or directory,then assign this path to model's imagepath.(Examle code is blew)
In index page, {} should follow using(), otherwise it will report error.
public ActionResult Index(PayableFormModel model,HttpPostedFileBase file,int[] ids)
{
string filepath = Server.MapPath("~/image/");
Directory.CreateDirectory(filepath);
file.SaveAs(Path.Combine(filepath, file.FileName));
model.ImagePath = filepath + file.FileName ;
return View();
}
This is how my view looks like currently.
#model DatePicker.Models.ViewModels.Appointment.CreateAppointmentSelectPersons
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
<link href="~/Content/themes/base/minified/jquery-ui.min.css" rel="stylesheet"/>
}
#*Main Form*#
#using(Ajax.BeginForm("Create","Appointment", new AjaxOptions{HttpMethod = "POST"}))
{
#Html.AntiForgeryToken()
<h4>Step 2</h4>
<hr />
#Html.ValidationSummary()
#Html.HiddenFor(m=>m.AppointmentId)
#*Child Form1*#
using (Ajax.BeginForm("AddAttendeeManual", "Attendee", new AjaxOptions { HttpMethod = "POST", OnSuccess = "doneSuperOffice" }))
{
#Html.HiddenFor(m=>m.SelectedManualEmail.AppointmentId)
<div class="form-group">
#Html.LabelFor(m => m.SelectedManualEmail.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedManualEmail.Email, new { id = "Email", #class = "form-control",PlaceHolder="Email"})
<input type='submit' id="btnEmail" class="btn btn-default" value="Add>>" />
</div>
</div>
}
if (Model.IsSuperOfficeConnected)
{
#*Child Form 2*#
using (Ajax.BeginForm("AddAttendeeSuperOffice","Attendee",new AjaxOptions{HttpMethod = "POST", OnSuccess = "doneManualEmail"}))
{
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.FirstName, new { id = "SelectedSuperOfficeEmail_FirstName" })
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.LastName, new { id = "SelectedSuperOfficeEmail_LastName" })
#Html.HiddenFor(m=>m.SelectedSuperOfficeEmail.AppointmentId)
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.SuperOfficePersonId, new { id = "SelectedSuperOfficeEmail_SuperOfficePersonId" })
<div class="form-group">
#Html.LabelFor(m => m.SelectedSuperOfficeEmail.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedSuperOfficeEmail.Email, new { id = "SelectedSuperOfficeEmail", #class = "form-control", PlaceHolder = "Search in SuperOffice" })
<input type='submit' id="btnSuperOffice" class="btn btn-default" value="Add>>" />
</div>
</div>
}
}
if (Model.IsInternalAddressBookEmpty)
{
#*Child Form3*#
using (Ajax.BeginForm("AddAttendeeInternalAddressBook", "Attendee", new AjaxOptions { HttpMethod = "POST", OnSuccess = "doneInternalAddressbook" }))
{
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.FirstName)
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.LastName)
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.AppointmentId)
<div class="form-group">
#Html.LabelFor(m => m.SelectedAddressBookPerson.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedAddressBookPerson.Email, new { id = "SelectedAddressBookPerson", #class = "form-control", PlaceHolder = "Search in AddressBook..." })
<input type='submit' id="btnAddressBook" class="btn btn-default" value="Add>>">
</div>
</div>
}
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input class="btn btn-default" value="<<Previous"/>
<input type="submit" class="btn btn-default" value="Next>>" />
</div>
</div>
}
<style>
.ui-autocomplete-loading {
background: url('/Content/themes/base/images/ui-anim_basic_16x16.gif') no-repeat right center;
}
</style>
#section Scripts{
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/Scripts/jquery-ui-1.10.4.min.js")
#Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
<script type="text/javascript">
$(function () {
$("#SelectedSuperOfficeEmail").
autocomplete({
source: '/Appointment/SuperOfficePerson',
minLength: 1,
select: function (event, ui) {
$('#SelectedSuperOfficeEmail').val(ui.item.value);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.FirstName)).val(ui.item.FirstName);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.LastName)).val(ui.item.LastName);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.SuperOfficePersonId)).val(ui.item.ExternalPersonId);
}
});
$("#SelectedAddressBookPerson").autocomplete({
source: '/Appointment/AddressBookPerson',
minLength: 1,
select: function(event,ui) {
$(#Html.IdFor((m=>m.SelectedAddressBookPerson.FirstName))).val(ui.item.FirstName);
$(#Html.IdFor(m=>m.SelectedAddressBookPerson.LastName)).val(ui.item.LastName);
},
});
});
function doneManualEmail() {
$("#Email").val('');
}
function doneSuperOffice() {
$("#SelectedSuperOfficeEmail").val('');
}
function doneInternalAddressBook() {
$("#SelectedAddressBookPerson").val('');
}
</script>
}
And the controller:
[HttpPost]
public void AddAttendeeSuperOffice(CreateAppointmentSelectPersons superOfficePerson)
{
_attendeeRepository.AddSuperOfficeAttende(superOfficePerson.SelectedSuperOfficeEmail.AppointmentId,
superOfficePerson.SelectedSuperOfficeEmail.FirstName,
superOfficePerson.SelectedSuperOfficeEmail.LastName,
superOfficePerson.SelectedSuperOfficeEmail.Email,
superOfficePerson.SelectedSuperOfficeEmail.SuperOfficePersonId);
}
[HttpPost]
public void AddAttendeeInternalAddressBook(CreateAppointmentSelectPersons internalAddressbookPerson)
{
_attendeeRepository.AddInternalAddressBookAttendee(
internalAddressbookPerson.SelectedAddressBookPerson.AppointmentId,
internalAddressbookPerson.SelectedAddressBookPerson.FirstName,
internalAddressbookPerson.SelectedAddressBookPerson.LastName,
internalAddressbookPerson.SelectedAddressBookPerson.Email);
}
[HttpPost]
public void AddAttendeeManual(CreateAppointmentSelectPersons manualEmail)
{
_attendeeRepository.AddManualAttendee(manualEmail.SelectedManualEmail.AppointmentId,
manualEmail.SelectedManualEmail.Email);
}
Here, Child Form2works perfectly, it calls my controller when button is clicked and OnSuccess textbox gets empty, exactly as I wanted.
Problem1: For the Child Form3 it calls the controller but OnSuccess, doesn't make the textbox empty.
Problem2: For the Child Form1 it doesn't call my controller at all, nothing happens when i click the button
For starters, you may want to either create a done() function for each of those forms, or pass it which form has completed (unless every form, after it's been executed, does the same thing). e.g.
#* Child Form 1 *#
new AjaxOptions { ... OnSuccess = "form1Done()" ... }
#* Child Form 2 *#
new AjaxOptions { ... OnSuccess = "form2Done()" ... }
#* Child Form 3 *#
new AjaxOptions { ... OnSuccess = "form3Done()" ... }
~OR~
#* Child Form 1 *#
new AjaxOptions { ... OnSuccess = "done(1)" ... }
#* Child Form 2 *#
new AjaxOptions { ... OnSuccess = "done(2)" ... }
#* Child Form 3 *#
new AjaxOptions { ... OnSuccess = "done(3)" ... }
Secondly, There are more options than OnSuccess for the AjaxOptions method. It may make sense (at least while debugging) to add methods to OnFailure or OnSuccess so you can get more insight as to what's happening. Also, make use of the debugger within your browser and see if the calls are being executed.
For now, there's not enough information to solve your issue, but hopefully you'll either end up solving it by using the above, or get more information to update the question with.
If you do end up updating the question, please leave a comment on this answer and I'll do my best to help.
I'll try to explain the issue I'm facing the best way
I've got a view, and inside it a partial view which basically displays an input field and a button. This partial view would look like this
<fieldset>
#Html.HiddenFor(model => model.AuctionId)
#Html.HiddenFor(model => model.AuctionEventId)
<div class="lotdetail-maxbid-row">
#Html.TextBoxFor(model => model.Amount, new { #class = "radius2 text-box single-line valid" })
#Html.ValidationMessageFor(model => model.Amount)
</div>
<input type="submit" id="autobidButton" value="Increase Max bid" class="btn btn-level2 btn-maxbid #disableButton" />
</fieldset>
And inside this partial view, I've put this script
<script type="text/javascript">
$(document).ready(function () {
$('#autobidButton').click(function () {
$.ajax({
url: "/Lot/AutobidConfirmationPartial",
data: {
amount: $("#Amount").val(),
auctionEventId: $("#AuctionEventId").val(),
auctionId: $("#AuctionId").val()
},
success: function (result) {
$("#autobidConfirmation").empty().append(result);
},
type: "POST"
});
return false;
});
});
</script>
With the intention of load the result, which is a partial view in a div in the parent page.
The problem is that amount is always 0 (default value), and never gets updated when calling the function inside the script.
Any idea of what to do or look?
Thanks,
Update: This is the generated html and controller method
<fieldset>
<input id="AuctionId" type="hidden" value="3" name="AuctionId">
<input id="AuctionEventId" type="hidden" value="1" name="AuctionEventId">
<div class="lotdetail-maxbid-row">
<input id="Amount" class="radius2 text-box single-line valid" type="text" value="0" name="Amount">
</div>
<input id="autobidButton" class="btn btn-level2 btn-maxbid " type="submit" value="Increase Max bid">
</fieldset>
public ActionResult AutobidConfirmationPartial(int auctionEventId, int auctionId, decimal amount)
{
var incorrectAmount = false;
var correctedAmount = amount;
if (!CheckMaxBidFitsIncrementTier(amount, auctionEventId))
{
incorrectAmount = true;
correctedAmount = CalculateNextBidAmountForWrongMaxAmount(amount, auctionEventId); ;
}
var model = new BidOnAuctionViewModel
{
AuctionEventId = auctionEventId,
AuctionId = auctionId,
Amount = correctedAmount,
IncorrectAmount = incorrectAmount,
};
//TotalPriceBreakdown(ref model, null);
return PartialView("BidConfirmationPartial", model);
}
the page has 2 DropDownLists + a Textbox + a Submit Button.
On Submit it's supposed to choose and fill a partial view depending on what value is selected in the first DropDownList. I got it somewhat working; however, it will always return the pv in a new window instead of rendering it in the main view's div.
I am using MVC 3 + Telerik.
The most Important parts of the code:
VIEW - Updated
<script type="text/javascript">
function onMainDDL1Change(e) {
var combo = $("#SubDDL1").data("tComboBox");
combo.value("");
combo.reload();
}
function onSubDDL1DataBinding(e) {
var combo = $("#MainDDL1").data("tComboBox");
e.data = $.extend({}, e.data, { mainDDL1ID: combo.value() });
}
</script>
#using (Ajax.BeginForm("PartialGrid", "DataSearch", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "result", InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace }))
{
<table>
<tr>
<td>
#(Html.Telerik().ComboBox()
.Name("MainDDL1")
.AutoFill(true)
.DataBinding(binding => binding.Ajax().Select("LoadMainDDL", "DataSearch"))
.HighlightFirstMatch(true)
.ClientEvents(events => events.OnChange("onMainDDL1Change"))
)
</td>
</tr>
<tr>
<td>
#(Html.Telerik().ComboBox()
.Name("SubDDL1")
.DataBinding(binding => binding.Ajax().Select("LoadSubDDL1", "DataSearch"))
.HighlightFirstMatch(true)
.ClientEvents(events => events.OnDataBinding("onSubDDL1DataBinding"))
)
</td>
<tr>
<td>
#Html.TextBoxFor(o => o.sSearch1)
</td>
</tr>
<tr align="center">
<td colspan="4">
<input type="submit" class="t-button" value="Search" name="submit" />
</td>
</tr>
</table>
}
<div id="result">
</div>
Controller - Updated
[HttpPost]
//PartialView
public PartialViewResult PartialGrid(DataSearchModel voModel)
{
voModel.dtResultSet1 = DLA.DataSearchContext.getResultSet1(voModel.MainDDL1, voModel.SubDDL1, voModel.sSearch1);
return PartialView("_TPRCL", voModel);
}
//Initial View
public ViewResult DataSearch(string text)
{
DataSearchModel oModel = new DataSearchModel();
oModel.alMainDDL = DLA.DataSearchContext.getMainDDL();
return View(oModel);
}
PartialView
#model ISC.Utilities.GISTransactionTools.Models.DataSearchModel
#(Html.Telerik().Grid(Model.dtResultSet1)
.Name("Grid")
.Footer(false)
.Columns(columns =>
{
columns.Bound(o => o.Row[0]).Title("T_PRCL");
}))
PartialView Grid has actually more columns, this is just to make it work.
I am not using Telerik, but here is how I am doing something similar:
In the initial view I have the following code:
#using (Ajax.BeginForm("PhoneForm", "Home", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "form-lead", InsertionMode = InsertionMode.Replace, OnSuccess = "HookupValidation" })) {
#Html.ValidationSummary(false, "Please address the following items:")
<div class="phone">
<div class="field">
#Html.LabelFor(model => model.Phone1)
#Html.EditorFor(model => model.Phone1)
#Html.ValidationMessageFor(model => model.Phone1)
</div>
<div class="button">
<input type="submit" value="Get Customer" name="submit" /></div>
</div>
}
<div id="form-lead">
</div>
Basically, when the "Get Customer" button is clicked, it will call, via AJAX, the "PhoneForm" method in my "Home" controller. This method generates the partial view which is then inserted (InsertionMode = InsertionMode.Replace) into the (UpdateTargetId = "form-lead"). The OnSuccess function is just to be sure that client side validation and jQuery events are hooked up on the partial view. If you don't do this, none of the client side validation or script will work for items in the partial view.
The controller code for "PhoneForm" is as follows:
[HttpPost]
public PartialViewResult PhoneForm(string Phone1) {
HomeViewModel viewModel = new HomeViewModel();
// ... get data and set up view model here ... //
// ... also choose which partial view you want to return ... //
return PartialView("LeadInfoPartial", viewModel);
}
Hope this helps you solve your issue.
Alright got it to work in Javascript.
View
<script type="text/javascript"> $('#btnSubmit').click(function () {
var time = new Date().getTime(); // #* unique random number to workaround IE cache issue - IE will cache the ajax if you
don't use this *#
var oMainDDL1 = $('#MainDDL1').data("tComboBox");
var oSubDDL1 = $('#SubDDL1').data("tComboBox");
var sSearch1 = $("#Search1").val();
var actionURL = '#Url.Action("getGrid1", "DataSearch", new { MainDDL1
= "PLACEHOLDER" })'.replace('PLACEHOLDER', oMainDDL1.value()) + "&SubDDL1=" + oSubDDL1.value() + "&Search1=" + sSearch1 + "&time=" +
time;
if (actionURL != null) {
$.get(actionURL, function (data) {
$('#result1').fadeOut('slow', 'linear', function () { $('#result1').empty(); $('#result1').append(data); });
$('#result1').fadeIn('slow', 'linear', function () {
if ($.browser.msie) {
this.style.removeAttribute('filter'); // #* Needed to fix IE7 cleartype bug with jQuery fade, but will crap out
on FF/Chrome *#
}
});
});
}
});
}); </script>
#(Html.Telerik().ComboBox()
.Name("MainDDL1")
.AutoFill(true)
.DataBinding(binding => binding.Ajax().Select("LoadMainDDL", "DataSearch"))
.HighlightFirstMatch(true)
.ClientEvents(events => events.OnChange("onMainDDL1Change"))
)
#(Html.Telerik().ComboBox()
.Name("SubDDL1")
.DataBinding(binding => binding.Ajax().Select("LoadSubDDL1", "DataSearch"))
.HighlightFirstMatch(true)
.ClientEvents(events => events.OnDataBinding("onSubDDL1DataBinding"))
)
#Html.TextBox("Search1")
<input type="button" class="t-button button1" value="Search"
id="btnSubmit" />
<div id="result1"> </div>
Controller
public PartialViewResult getGrid1(string MainDDL1, string SubDDL1, string Search1)
{
DataSearchModel voModel = new DataSearchModel();
voModel.dtResultSet1 = DLA.DataSearchContext.getResultSet1(MainDDL1, SubDDL1, Search1);
return PartialView(MainDDL1, voModel);
}
public ViewResult DataSearch(string text)
{
DataSearchModel oModel = new DataSearchModel();
oModel.alMainDDL = DLA.DataSearchContext.getMainDDL();
return View(oModel);
}