Reputation: 45
I'm developing (for the first time) an MVC application using ajax call and knockout MVVM to fill 2 cascading dropdown lists. The question is, How can I preserve the values I selected in the dropdown lists, when I post the web page? The web page I'm developing makes calculations when is posted to the controller and the controller must return the calculated result. When the result is returned, the values of the form must be preserved.
a part of the View
@using (Html.BeginForm("Calculate", "Entypo", FormMethod.Post, new { role = "form" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(false)
<fieldset>
<legend>Printers</legend>
<div class="row">
<div class="form-group col-md-6">
<select id="printers" name="printers" class="form-control" data-bind="options: printers, optionsValue: 'ID', optionsText: 'BrandModelName', value: selectedPrinter, optionsCaption: 'Choose Printer...'"></select>
</div>
<div class="form-group col-md-6">
<select id="sheets" name="sheets" class="form-control" data-bind="options: sheets, optionsValue: 'ID', optionsText: 'Description', optionsCaption: 'Choose Sheet...', enable: sheets().length, value: sheet">
</select>
</div>
</div>
</fieldset>
<div class="row">
<div class="col-md-12" style="padding-bottom:10px;">
<input type="submit" value="Calculate" class="btn btn-primary" />
</div>
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/knockout-3.0.0.js"></script>
<script>
$(document).ready(function () {
// MVVM
viewModel = {
printer: ko.observable(),
printers: ko.observableArray(),
sheet: ko.observable(),
sheets:ko.observableArray(),
paper: ko.observable(),
papers: ko.observableArray(),
weight: ko.observable(),
weights: ko.observableArray(),
size: ko.observable(),
sizes: ko.observableArray(),
lamA: ko.observableArray(),
lamAvalue: ko.observable(),
lamB: ko.observableArray(),
lamBvalue: ko.observable(),
chkCut: ko.observable(false),
chkFold: ko.observable(false),
chkPick: ko.observable(false),
chkPerfore: ko.observable(false),
standardSize: ko.observable(),
x: ko.observable(),
y: ko.observable(),
bleed: ko.observable(2.5),
qty: ko.observable(1)
};
viewModel.standardSize.subscribe(function () {
var st = viewModel.standardSize();
var res = st.split("x");
viewModel.x(res[0]);
viewModel.y(res[1]);
});
$.ajax({
url: '/Entypo/getPrinters',
type: 'GET',
dataType: 'json',
data: {},
success: function (data) {
viewModel.printers(data);
}
});
viewModel.selectedPrinter = ko.dependentObservable({
read: viewModel.printer,
write: function (printer) {
this.printer(printer);
$.ajax({
url: '/Entypo/getSheets',
type: 'GET',
dataType: 'json',
data: { id: viewModel.selectedPrinter() },
success: function (data) {
viewModel.sheets(data);
}
});
},
owner: viewModel
});
$.ajax({
url: '/PaperSize/getPapers',
type: 'GET',
dataType: 'json',
data: {},
success: function (data) {
viewModel.papers(data);
}
});
viewModel.selectedPaper = ko.dependentObservable({
read: viewModel.paper,
write: function (paper) {
this.paper(paper);
$.ajax({
url: '/Entypo/getWeights',
type: 'GET',
dataType: 'json',
data: { id: viewModel.selectedPaper() },
success: function (data) {
viewModel.weights(data);
}
});
},
owner: viewModel
});
viewModel.selectedWeight = ko.dependentObservable({
read: viewModel.weight,
write: function (weight) {
this.weight(weight);
$.ajax({
url: '/Entypo/getSizes',
type: 'GET',
dataType: 'json',
data: { id: viewModel.selectedWeight() },
success: function (data) {
viewModel.sizes(data);
}
});
},
owner: viewModel
});
$.ajax({
url: '/Entypo/getLamination',
type: 'GET',
dataType: 'json',
data: {},
success: function (data) {
viewModel.lamA(data);
viewModel.lamB(data);
}
});
ko.applyBindings(viewModel);
});
</script>
The Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using QVNet_v2.Models;
namespace QVNet_v2.Controllers
{
public class EntypoController : Controller
{
private QVNetEntities db = new QVNetEntities();
//
// Calc: /Entypo/
[HttpGet]
public ActionResult Calculate()
{
return View();
}
[HttpPost]
public ActionResult Calculate()
{
return View();
}
//GET PRINTERS
public JsonResult getPrinters()
{
var printers = db.Printers.Select(s => new { s.ID, s.BrandModelName }).OrderBy(s=>s.BrandModelName).ToList();
return Json(printers, JsonRequestBehavior.AllowGet);
}
//GET SHEETS USED FROM SELECTED PRINTER
public JsonResult getSheets(int id)
{
var sheets = db.Sheets.Select(s => new { s.ID, s.Description, s.PrinterID }).Where(s=>s.PrinterID ==id).OrderBy(s=>s.Description).ToList();
return Json(sheets, JsonRequestBehavior.AllowGet);
}
// GET PAPERS
public JsonResult getPapers()
{
var papers = db.Papers.Select(s => new { s.ID, s.Description }).OrderBy(s => s.Description).ToList();
return Json(papers, JsonRequestBehavior.AllowGet);
}
// GET WEIGHTS OF SELECTED PAPER
public JsonResult getWeights(int id)
{
var weights = db.PaperWeights.Select(s => new { s.ID, s.Weight, s.PaperID }).Where(s => s.PaperID == id).OrderBy(s => s.Weight).ToList();
return Json(weights, JsonRequestBehavior.AllowGet);
}
//GET SIZES OF SELECTED PAPER AND WEIGHT
public JsonResult getSizes(int id)
{
var sizes = db.PaperSizes.Select(s => new { s.ID, s.Description, s.PaperWeightID }).Where(s => s.PaperWeightID == id).OrderBy(s => s.Description).ToList();
return Json(sizes, JsonRequestBehavior.AllowGet);
}
//GET LAMINATION
public JsonResult getLamination()
{
var lam = db.SheetLaminations.Select(s => new { s.ID, s.Description }).OrderBy(s => s.Description).ToList();
return Json(lam, JsonRequestBehavior.AllowGet);
}
//Dispose db
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
When the user click the submit value, the controller must take the data from the form and return the results of a calculation while keeping intact the form fields.
Sorry for my English.
Upvotes: 0
Views: 1727
Reputation: 971
You have two possible ways.
Submit your form using ajax. You will keep your form
open thus all values will be unchanged. You can use @using
(Ajax.BeginForm)
or create knockout method that will call $.ajax
to save your data and
assing this method to submit button.
Second approach - make your form strongly typed. Create viewmodel
class that will hold all values needed to construct the form. In
your saving action (Calculate
method annotated with [HttpPost]
)
you shoud recreate viewmodel based on actual form values and send it
back to the view.
Upvotes: 1