KnockoutJS - Observable Array of Observable objects with Data from SQL server - javascript

I am working on a simple proof of concept for a web app
I would like to know how to achieve the above please.
I have a class of items I am retrieving in a API from SQL server. The simple structure of the Class is
public partial class ReqsTest
{
public string ID { get; set; }
public string Requisition { get; set; }
public Nullable<System.DateTime> DateReqnRaised { get; set; }
public Nullable<decimal> ReqnValue { get; set; }
public Nullable<decimal> ApprovedValue { get; set; }
public decimal Line { get; set; }
public long INDX { get; set; }
public string ReqStatus { get; set; }
public string ReqBackground { get; set; }
}
I am populating a Knockout Observable Array with the data return from the server
My View Model code is
var self = this;
self.reqs = ko.observableArray();
self.error = ko.observable();
var reqsUri = '/api/ReqsTests/';
function ajaxHelper(uri, method, data) {
self.error(''); // Clear error message
return $.ajax({
type: method,
url: uri,
dataType: 'json',
contentType: 'application/json',
data: data ? JSON.stringify(data) : null
}).fail(function (jqXHR, textStatus, errorThrown) {
self.error(errorThrown);
});
}
function getAllReqs() {
ajaxHelper(reqsUri, 'GET').done(function (data) {
self.reqs(data);
});
}
The problem is that of course I now know the underlying object properties in the array are not observable as in this question here
I am trying to understand how to use this code here to bridge the gap but I do fully understand the calls
I believe I will need this sort of function to create the object with the Observable properties for updating later, such as something like this
function Item(ID, Requistion,DateReqnRaised,ReqnValue,ApprovedValue,Line,INDX,ReqStatus,ReqBackground) {
//Not editable properties
this.ID = ID;
this.Requistion = Requistion;//Not editable
this.DateReqnRaised = DateReqnRaised;//Not editable
this.ReqnValue = ReqnValue; //Not editable
this.Line = Line;
this.INDX = INDX;
//editable later properties
this.ApprovedValue = ko.observable(ApprovedValue);
this.ReqStatus = ko.observable(ReqStatus);
this.ReqBackground = ko.observable(ReqBackground);
}
But that maybe not quite right yet and I believe I need to change the code here to but I am not certain how to call the item function with it. It feels like I need to loop through each return in data to call the function item to add it to the observable array but I am not certain yet.
function getAllReqs() {
ajaxHelper(reqsUri, 'GET').done(function (data) {
self.reqs(data);
});
}
Can any one help please
****UPDATED CODE****
Index.cshtml code
<div class="page-header">
<h1>Chamberlin Requistions</h1>
</div>
<div class="row">
<div class="col-xs-4">
<div class="panel panel-default" >
<div class="panel-heading">
<h2 class="panel-title">Requistions</h2>
</div>
<div class="panel-body panel-info ">
<ul class="list-unstyled" data-bind="foreach: Reqs">
<li>
<div >
<strong>
<span data-bind="text: reqs().Requisition"></span>
: <span data-bind="text: reqs().Line"></span>
</strong>
</div>
</li>
</ul>
</div>
</div>
<div class="alert alert-danger" data-bind="visible: error"><p data-bind="text: error"></p></div>
</div>
</div>
As requested the update code for the View model
function ReqsTest(rt) {
rt = rt || {};
var self = this;
self.id = ko.observable(rt.ID || 0);
self.requisition = ko.observable(rt.Requisition || "");
self.dateReqnRaised = ko.observable(rt.DateReqnRaised || null);
self.reqnValue = ko.observable(rt.ReqnValue || null);
self.approvedValue = ko.observable(rt.ApprovedValue || null);
self.line = ko.observable(rt.Line || 0.00);
self.indx = ko.observable(rt.INDX || 0);
self.reqStatus = ko.observable(rt.ReqStatus || "");
self.reqBackground = ko.observable(rt.ReqBackground || ""); }
function ReqsViewModel (){
var self = this;
self.Reqs = ko.observableArray([]);
self.error = ko.observable();
var reqsUri = '/api/ReqsTests/';
function ajaxHelper(uri, method, data) {
self.error(''); // Clear error message
return $.ajax({
type: method,
url: uri,
dataType: 'json',
contentType: 'application/json',
data: data ? JSON.stringify(data) : null
}).fail(function (jqXHR, textStatus, errorThrown) {
self.error(errorThrown);
});
}
function getAllReqs() {
ajaxHelper(reqsUri, 'GET').done(function (data) {
// Build the ReqsTest objects
var reqs = ko.utils.arrayMap(data, function (rt) {
return new ReqsTest(rt);
});
self.Reqs(reqs);
});
}
// Load the reqs - Take this out if you don't want it
getAllReqs(); }
//Details
self.detail = ko.observable();
self.getReqDetail = function (item) {
ajaxHelper(reqsUri + item.INDX, 'GET').done(function (data) {
self.detail(data);
});
}
ko.applyBindings(new ReqsViewModel());
Thank you

First make a matching JavaScript function for your ReqsTest class.
function ReqsTest(rt) {
rt = rt || {};
var self = this;
self.id = ko.observable(rt.ID || 0);
self.requisition = ko.observable(rt.Requisition || "");
self.dateReqnRaised = ko.observable(rt.DateReqnRaised || null);
self.reqnValue = ko.observable(rt.ReqnValue || null);
self.approvedValue = ko.observable(rt.ApprovedValue || null);
self.line = ko.observable(rt.Line || 0.00);
self.indx = ko.observable(rt.INDX || 0);
self.reqStatus = ko.observable(rt.ReqStatus || "");
self.reqBackground = ko.observable(rt.ReqBackground || "");
}
Then make a viewmodel to bind to the page.
function ReqsViewModel {
var self = this;
self.reqs = ko.observableArray([]);
self.error = ko.observable();
var reqsUri = '/api/ReqsTests/';
function ajaxHelper(uri, method, data) {
self.error(''); // Clear error message
return $.ajax({
type: method,
url: uri,
dataType: 'json',
contentType: 'application/json',
data: data ? JSON.stringify(data) : null
}).fail(function (jqXHR, textStatus, errorThrown) {
self.error(errorThrown);
});
}
function getAllReqs() {
ajaxHelper(reqsUri, 'GET').done(function (data) {
// Build the ReqsTest objects
var reqs = ko.utils.arrayMap(data, function(rt) {
return new ReqsTest(rt);
});
self.reqs(reqs);
});
}
// Load the reqs - Take this out if you don't want it
getAllReqs();
}
And bind the viewmodel to the page...
ko.applyBindings(new ReqsViewModel());
You now have an observable array of objects with observable properties.
I hand typed this code in so there may be a few syntax errors

Related

.net Core Using razor function in Javascript

Hi i got to use c# code in js. My js and .cshtml page are separeted . I wrote a function in .cshtml page and gotta call it in .js file.
In Js file
DataList.forEach(function (item) {
...
var users = GetUsers(item.AssignedUsers);
It goes here
Index.cshtml
<script>
function GetUsers(userIdList) {
//it logs it, i can get theese values from here
console.log("userIdList");
console.log(userIdList);
#{ // but in here it says userIdList does not exist in current content
//also tryed this.userIdList
var users = userIdList.Split(",");
foreach (var item in users)
{
var user = _Manager.FindByIdAsync(item.UserId).Result;
}
}
}
</script>
You can pass list from ajax to controller action,and action return a list you want.
Here is a demo:
<button onclick="sendData()">
send
</button>
<script>
function sendData() {
//here is a sample list
var list = [];
var user1 = {};
user1.Id = 1;
user1.Name = "u1";
list.push(user1);
var user2 = {};
user2.Id = 2;
user2.Name = "u2";
list.push(user2);
$.ajax({
type: "POST",
url: '#Url.Action("SendData", "Test")',
contentType: "application/json",
data: JSON.stringify(list),
}).done(function (data) {
console.log(data);
//the data is you want
});
}
</script>
action:
public List<User> SendData([FromBody]List<User> list) {
//you can do something and return a list you want here
return list;
}
User:
public class User {
public int Id { get; set; }
public string Name { get; set; }
}
result:

ASP.Net MVC: How could i pass js array to mvc action by #Url.Action()

We know that we can pass js variable value to mvc action but how could i pass js array to mvc action ?
So my question is how could i pass js array to mvc action by #Url.Action() ?
please see my sample code
[HttpPost]
public ActionResult DoSomething(string id, string deptno, list<PdfInputs> PdfInputs)
{
// Some magic code here...
}
var id = "10";
var deptno = "C001";
var PdfInputs = [];
for(inti=0;i<=totalbol-1;i++)
{
var PdfInput = {
firstName: "John",
lastName: "Doe",
age: 46
};
}
PdfInputs.push(BOLPdfInput);
location.href = '#Url.Action("DoSomething", "Customer")?id=' + id + '&deptno=' + deptno;
my mvc action will download pdf at client and that is why i use
location.href = '#Url.Action("DoSomething", "Customer")?id=' + id + '&deptno=' + deptno;
please guide me.
Actually you can pass JSON string from array with #Url.Action() helper using query string parameter like this:
<script>
$(function() {
var id = "10";
var deptno = "C001";
var PdfInputs = [];
for (var i = 0; i < totalbol; i++)
{
PdfInputs.push({
firstName: "John",
lastName: "Doe",
age: 46
});
}
location.href = '#Url.Action("DoSomething", "Customer")?id=' + id + '&deptno=' + deptno + '&PdfInputs=' + JSON.stringify(PdfInputs);
})
</script>
However I strongly discourage this practice because passed JSON string may exceeds query string limit if the array has large amount of data. Additionally, you cannot use #Url.Action() helper for action method marked with [HttpPost] attribute (it only works for GET method), hence I recommend to use jQuery.ajax() to pass PdfInputs array as List<PdfInputs> & TempData/Session state variable to store file contents, then download PDF file using HttpGet controller action as provided below:
jQuery
<script>
$(function() {
var id = "10";
var deptno = "C001";
var PdfInputs = [];
for (var i = 0; i < totalbol; i++)
{
PdfInputs.push({
firstName: "John",
lastName: "Doe",
age: 46
});
}
$('#buttonid').click(function () {
$.ajax({
type: 'POST',
url: '#Url.Action("DoSomething", "Customer")',
// traditional: true,
data: $.param({ id: id, deptno: deptno, pdfInputs: PdfInputs }, true),
success: function (result) {
location.href = '#Url.Action("Download", "ControllerName")?id=' + id;
},
error: function (err) {
// error handling
}
});
});
})
</script>
Controller (DoSomething Action)
[HttpPost]
public ActionResult DoSomething(string id, string deptno, List<PdfInputs> pdfInputs)
{
// Some magic code here...
// Save file to TempData or Session state
byte[] fileContent = fileStreamInstance.ToArray();
TempData["FileToDownload"] = fileContent;
return Json("Success");
}
Controller (Download Action)
[HttpGet]
public ActionResult Download(string id)
{
string fileName = "yourfilename.pdf";
// other code here
if (TempData["FileToDownload"] != null)
{
byte[] content = TempData["FileToDownload"] as byte[];
return File(content, "application/pdf", fileName);
}
else
{
return new EmptyResult();
}
}
Click on this fiddle https://dotnetfiddle.net/RRwK1K
View
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Tut123</title>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(function () {
$("#theButton").click(function () {
var id = "10";
var deptno = "C001";
var PdfInputs = [];
var i;
for (i = 0; i <= 3; i++) {
PdfInputs.push({
firstName: "John",
lastName: "Doe",
age: 46
});
}
var json = JSON.stringify(PdfInputs);
location.href = '#Url.Action("theActionPassArray", "Home")?json=' + json;
})
})
</script>
</head>
<body>
<input type="button" id="theButton" value="Go" />
#*credit to https://stackoverflow.com/questions/15112055/passing-dynamic-javascript-values-using-url-action*#
#if (ViewBag.Data != null)
{
<span>The data sent to the server was:</span>#ViewBag.Data
}
</body>
</html>
Controller
public class PassArray
{
public string firstName { get; set; }
public string lasttName { get; set; }
public string age { get; set; }
}
public class HomeController : Controller
{
public ActionResult theActionPassArray(string json)
{
/turn json passed value into array
//You need to get NewtonSoft.JSON
PassArray[] arr = JsonConvert.DeserializeObject<PassArray[]>(json);
//put breakpoint here
ViewBag.Data = json;
return View("Tut123"); }
public ActionResult Tut123()
{
return View();
}

.net core Razor pages with JQuery AJAX

I am trying to call a Razor Page Handler using JQuery AJAX. Here is the sample code.
<script type="text/javascript">
$(document).ready(function () {
$("#SectionId").change(function () {
var options = {};
options.url = $(location).attr('href') + "/?SectionId=" + $("#SectionId").val() + "?handler=SelectByID";
options.type = "GET";
options.dataType = "json";
options.success = function (data) {
};
options.error = function () {
$("#msg").html("Error while making Ajax call!" + options.error.val);
};
$.ajax(options);
});
});
</script>
Razor Page cs code:
public class CreateModel : PageModel
{
private readonly ApplicationDbContext _context;
private readonly UserManager<ApplicationUser> _userManager;
private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);
[BindProperty]
public FileRecord FileRecord { get; set; }
public List<SelectListItem> UserList { get; set; }
public string SelectedSectionId { get; set; }
public CreateModel(ApplicationDbContext context, UserManager<ApplicationUser> userManager)
{
_context = context;
_userManager = userManager;
}
public IActionResult OnGetSelectByID(string SectionId)
{
return null;
}
public async Task<IActionResult> OnGetAsync()
{
//Prepare UserList
UserList = new List<SelectListItem>();
List<ApplicationUser> Users = await _context.Users.ToListAsync();
foreach (var item in Users)
{
string role = Enum.GetName(typeof(EmRoles), EmRoles.NormalUser);
if (await _userManager.IsInRoleAsync(item, role) && item.IsEnabled)
{
UserList.Add(new SelectListItem()
{
Text = item.FullName,
Value = item.Id
});
}
}
//Sections
ViewData["Sections"] = new SelectList(_context.Sections, "Id", "Name");
//FileNOs
ViewData["Files"] = new SelectList(_context.FileRegisters, "Id", "FileNo");
//ViewData["ReceiverUserId"] = new SelectList(_context.Users, "Id", "Id");
//ViewData["SenderUserId"] = new SelectList(_context.Users, "Id", "Id");
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
//Two File Records have to be created. One For Sender & One for receiver.
FileRecord SenderRecord = new FileRecord
{
//create unique file id
//FileId = Guid.NewGuid().ToString(),
OutDate = DateTime.Now,
};
FileRecord ReceiverRecord = new FileRecord
{
//create unique file id
//FileId = SenderRecord.FileId,
InDate = SenderRecord.OutDate,
};
//Current logged-in user
var user = await GetCurrentUserAsync();
SenderRecord.OwnerUserId = user.Id;
//Receiver
ReceiverRecord.OwnerUserId = FileRecord.ReceiverUserId;
ReceiverRecord.SenderUserId = SenderRecord.OwnerUserId;
//Sender Record
if (await TryUpdateModelAsync<FileRecord>(SenderRecord, "FileRecord", f => f.FileId, f => f.Remarks, f => f.Gist, f => f.ReceiverUserId))
{
//Receiver Record
if (await TryUpdateModelAsync<FileRecord>(ReceiverRecord, "FileRecord", f => f.FileId, f => f.Gist))
{
_context.FileRecords.Add(SenderRecord);
_context.FileRecords.Add(ReceiverRecord);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
//If it reaches here. that means some error occurred.
return null;
}
}
The Issue is am not getting a call to Razor Page Handler defined above. If i skip the SectionId parameter passed-in & call only the handler. it is working fine. but it is not working when parameter is sent to the handler, default OnGet() is being called.
Help plz.
You don't need to append your handler parameter
options.url = $(location).attr('href') + "/?SectionId=" + $("#SectionId").val();
You also need to decorate the method with the HttpGet attribute
[HttpGet("GetSelectByID")]
public IActionResult OnGetSelectByID(string SectionId)
{
return null;
}
Then your URL to call this method needs to be
http://localhost:xxxx/FileMovement/Create/GetSelectByID?SectionId=yyy
When you have more than one GET defined on a controller you must tag the additional GET methods with the HttpGet attribute and add a string to define the name of that method.
Finally i was able to solve the issue.
<script type="text/javascript">
$(document).ready(function () {
$("#SectionId").change(function () {
var options = {};
options.url = $(location).attr('href') + "?handler=SelectByID" + "&SectionId=" + $("#SectionId").val();;
options.type = "GET";
options.dataType = "json";
options.success = function (data) {
};
options.error = function (data) {
$("#msg").html("Error while making Ajax call!" + data.error.val);
};
$.ajax(options);
});
});
Everything was right except i have to use "&" in "&SectionId="

How can I prevent passing in multiple parameters to controller?

Right now I have a form that contains 6 security questions and 6 security answers. I've been trying to refactor my code and I'm running into an interesting situation that I'm not sure on how to proceed.
Here's my view:
var RequestSecurityQuestions_Submit = function () {
ValidationAttribute.BlankValue(true);
var form = $('form#RequestSecurityQuestions');
$.validator.unobtrusive.parse(form);
var d = $('form#RequestSecurityQuestions').serialize();
SecurityQuestionsValid = true;
var inputs = $('form#RequestSecurityQuestions').find('input[data-val]');
$.each(inputs, function (index) {
var input = inputs[index];
if (!$(input).valid()) {
SecurityQuestionsValid = false;
}
});
var dataObject = {}, dropdowns = $("input.customdropdownlist");
for (var i = 0; i < 6; i++) {
dataObject['question' + i] = $(dropdowns[i]).data("kendoDropDownList").value()
}
for (var i = 1; i < 7; i++) {
dataObject['answer' + i] = $('#idAnswer' + i).val();
}
var dataToPass = JSON.stringify(dataObject);
if (SecurityQuestionsValid) {
$.ajax({
url: Url.getFullUrl('Account/RequestSecurityQuestions_Submit'),
type: 'Post',
data: { securityInfo: dataToPass },
dataType: 'json',
cache: false,
success: function (data) {
//Next Dialog
},
error: AjaxLog.HandleAjaxCallFail
});
}
return SecurityQuestionsValid;
}
I get a dataObject which contains all the values from my view and I want to pass it to the controller.
Currently this works:
[AllowAnonymous]
[HttpPost]
public ActionResult RequestSecurityQuestions_Submit(string answer1, string answer2, string answer3, string answer4, string answer5, string answer6, string question1, string question2, string question3, string question4, string question5, string question6)
{
SecurityQuestions securityQuestions = new SecurityQuestions();
if (!string.IsNullOrEmpty(answer1))
{
securityQuestions.ChallengeA1 = answer1;
}
if (!string.IsNullOrEmpty(answer2))
{
securityQuestions.ChallengeA2 = answer2;
}
if (!string.IsNullOrEmpty(answer3))
{
securityQuestions.ChallengeA3 = answer3;
}
//etc....
}
However, I am passing in 12 parameters to my controller which sounds like a no-no to me. Is there another way to pass in my data from my view to my controller without having to pass in 12 parameters?
EDIT:
New controller attempt:
/*Problem: securityInfo array looks like: ""{\"question0\":\"2\",\"question1\":\"3\",\"question2\":\"4\",\"question3\":\"5‌​\",\"question4\":\"7\",\"question5\":\"1\",\"answer1\":\"fgfg\",\"answer2\":\"fgf‌​gf\",\"answer3\":\"fgfg\",\"answer4\":\"fgfgfg\",\"answer5\":\"fgfg\",\"answer6\"‌​:\"fggf\"}"" */
[AllowAnonymous]
[HttpPost]
public ActionResult RequestSecurityQuestions_Submit(string[] securityInfo)
{
SecurityQuestions securityQuestions = new SecurityQuestions();
}
There are multiple ways to achieve this of course, the following is one of them. A better one would be to restructure your code as per other answers/comments.
// Creating your array
var dataObject = [],
dropdowns = $("input.customdropdownlist");
//Populate your array. [0-5] will be questions and [6-11] will be answers .
for (var i = 0; i < 6; i++) {
if (i < 6){
dataObject[i] = $(dropdowns[i]).data("kendoDropDownList").value()
}
else {
var d = i - 5;
dataObject[i] = $('#idAnswer' + d).val();
}
}
// Your AJAX call with contentType
$.ajax({
url: Url.getFullUrl('Account/RequestSecurityQuestions_Submit'),
type: 'Post',
data: JSON.Stringify(dataObject), //Change data format to JSON array, will be received as array in backend
contentType: "application/json",
cache: false,
success: function (data) {
//Next Dialog
},
error: AjaxLog.HandleAjaxCallFail
});
And simply receive the array in your backend
public ActionResult RequestSecurityQuestions_Submit(List<String> data)
{
//Your code here
}
Mate, Well, I don't understand why you have N parameters which has the same type of data--- that's really where the class should come for.
Short Answer will be you can create a Model which contains these parameters, then on your controller, just RequestSecurityQuestions_Submit(Model postedModel)
then access your parameters inside like postedModel.parameter1 ... In you ajax call , it looks like
$.ajax({
url: Url.getFullUrl('Account/RequestSecurityQuestions_Submit'),
type: 'Post',
data: {parameter1:'',parameter2:''...},
cache: false,
success: function (data) {
//Next Dialog
},
Multiple parameter(n>3) on any function is bad in theory and practice,
You can simplify all this by correctly using a model, binding to a model and posting back you model.
View models
public class SecurityAnswerVM
{
[Required(ErrorMessage="Please select a question")]
[Display(Name = "Question")]
public int? QuestionID { get; set; }
[Required(ErrorMessage = "Please enter an answer")]
public string Answer { get; set; }
}
public class SecurityLoginVM
{
public SelectList QuestionList { get; set; }
public List<SecurityAnswerVM> SelectedQuestions { get; set; }
}
Controller
[HttpGet]
public ActionResult Index()
{
SecurityLoginVM model = new SecurityLoginVM();
// Populate SelectedQuestions and QuestionList from the database
return View(model);
}
[HttpPost]
public ActionResult Index(SecurityLoginVM model)
{
// model.SelectedQuestions contains the 6 objects containing the QuestionID and the users Answer
....
}
EditorTemplate (/Views/Shared/EditorTemplates/SecurityAnswerVM.cshtml)
#model yourAssembly.SecurityAnswerVM
#Html.LabelFor(m => m.QuestionID)
#Html.DropDownListFor(m => m.QuestionID, (SelectList)ViewData["options"], "Please select", new { #class = "question" })
#Html.ValidationMessageFor(m => m.QuestionID)
#Html.LabelFor(m => m.Answer)
#Html.TextAreaFor(m => m.Answer)
#Html.ValidationMessageFor(m => m.Answer)
Main view
#model yourAssembly.SecurityLoginVM
#using(Html.BeginForm())
{
#Html.EditorFor(m => m.SelectedQuestions, new { options = Model.QuestionList })
<button id="save type="submit">Save</button> // or type="button" is posting via ajax
}
And if you want to use ajax to post the data
var url = '#Url.Action("Index")';
$('#save').click(function() {
$.post(url, $('form').serialize(), function(data) {
// Next Dialog
});
});
Far less code, strongly typed model binding, client and server side validation and all the other beneficial features of using MVC!
Why not doing something like this -
public class QA {
public int QId {get;set;}
public string Answer {get;set;}
}
[AllowAnonymous]
[HttpPost]
public ActionResult RequestSecurityQuestions_Submit(QA[] answers)
{
for (var qa in answers){
//do what ever you like
}
}
and then in js -
// Creating your array
var dataObject = [],
var dropdowns = $("input.customdropdownlist");
for (var i = 0; i < 6; i++) {
dataObject[i] = {
'QId': $(dropdowns[i]).data("kendoDropDownList").value(),
'Answer': dataObject[i] = $('#idAnswer' + i).val();
};
}
$.ajax({
url: Url.getFullUrl('Account/RequestSecurityQuestions_Submit'),
type: 'Post',
data: JSON.stringify(dataObject),
contentType: "application/json",
cache: false,
success: function (data) {
},
error: function(data){
}
});

Knockout.js How should I add computed value to observaleArray?

I need to add to observableArray computed values, my current code is look like this:
self.prices = ko.observableArray();
.....
var pax = $("select#ticketsnumber option:selected").val();
var irt;
if ($("input[name='isrt']").is(":checked")) {
irt = 1;
} else {
irt = 0;
}
$.each(self.prices(), function (price) {
price.FinalPrice = ko.computed(function() {
return prices.Price * irt * parseInt(pax);
});
});
But I do not have any idea how should I call binding of this computed value (currently this way - <span name="totalprice" data-bind="text: ko.utils.unwrapObservable($data.FinalPrice)">) as well as this just seemed like computed value has not been added - binding result show 0.
Data model:
public class PriceItem
{
...
public string Price { get; set; }
...
public int FinalPrice { get; set; }
}
This is the way how I retrieve data to self.prices:
self.getprices = function () {
var destinationtypefrom = $("select#optionsfrom option:selected").attr("name");
var destinationtypeto = $("select#optionsto option:selected").attr("name");
var fromcode = $("select#optionsfrom").val();
var tocode = $("select#optionsto").val();
var json = { desttypefrom: destinationtypefrom, desttypeto: destinationtypeto, codefrom: fromcode, codeto: tocode, 'DepartureDate': $("#departure").val(), 'ReturnDate': $("#return").val() };
$.ajax({
url: "/Home/GetFlights",
data: json,
type: "post",
cache: false,
success: function (result) {
if (result.Error == null) {
self.prices(result);
ko.mapping.fromJS(result, {}, self.prices);
} else {
$("#modalerror").on("show.bs.modal", function () {
var modal = $(this);
modal.find("#errormsg").text(result.Error);
});
}
},
error: function (xhr) {
var err = eval("(" + xhr.responseText + ")");
alert(err.Message);
}
});
}
The main problem is that your $.each is wrong by assuming the first argument to be the actual element in the prices array. In fact, the first argument is the index, the second argument is the actual price you want to augment.
Also, you seem to have a typo in the computed function calculation, it's price.Price instead of prices.Price.
Try this:
$.each(self.prices(), function (index, price) {
price.FinalPrice = ko.computed(function() {
return price.Price * irt * parseInt(pax);
});
});
And in your HTML, something like:
<div data-bind="foreach: prices">
<span name="totalprice" data-bind="text: FinalPrice"></span>
</div>
See Fiddle

Categories

Resources