Knockout observableArray not binding - ajax

I am trying to bind an observableArray from an ajax server read but not able to bind it to the html. The json data is returning but not sure how to parse or get it to bind. I am new to Knockout.
Code:
<html>
<head>
<title></title>
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js"></script>
<script type='text/javascript' src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.js"></script>
<script>
function SurnameViewModel() {
var self = this;
self.Surnames = ko.observableArray();
$.ajax({
crossDomain: true,
type: 'POST',
url: "http://localhost/GetSurnames/Name/CID",
dataType: 'json',
data: { "Name": "d", "CID": "17" }, // <==this is just a sample data
processdata: true,
success: function (result) {
self.Surnames= ko.mapping.fromJS(result.data);
alert(self.Surnames()); // <== able to see the json data
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Failure!");
alert(xhr.status);
alert(thrownError);
}
});
}
// Activates knockout.js
$(document).ready(function() {
ko.applyBindings(new SurnameViewModel())
});
</script>
</head>
<body>
<h2>Surnames</h2>
<table>
<thead><tr>
<th>ID</th><th>Surname</th>
</tr></thead>
<tbody data-bind="foreach: Surnames">
<tr>
<td data-bind="text: Surnames().id"></td>
<td data-bind="text: Surnames().homename"></td>
</tr>
</tbody>
</table>
</body>
</html>
Json Data Returned from the alert
data: "[{"id":3,"homename":"DCosta"}]"
What am doing wrong here?
Edit: Working code
This is what worked for me.
I change this
ko.mapping.fromJS(result.data, {}, self.Surnames);
to
ko.mapping.fromJSON(result.data, {}, self.Surnames);
and in the html from this
<tr>
<td data-bind="text: Surnames().id"></td>
<td data-bind="text: Surnames().homename"></td>
</tr>
to this
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: homename"></td>
</tr>

You have two problems:
In your view when using the foreach binding you are "inside" of the context of the array so you don't need to write out the array name (Surnames()) again:
<tbody data-bind="foreach: Surnames">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: homename"></td>
</tr>
</tbody>
When you are getting back the data from the server you are overriding the Surnames array, the correct way of using the mapping plugin here:
ko.mapping.fromJS(result.data, {} /* empty mapping options */, self.Surnames);
Or
self.Surnames(ko.mapping.fromJS(result.data)());
Note the () in the above code, you need this because the ko.mapping.fromJS(result.data) will return an ko.observableArray without getting its underlaying value with the () you would end up with your Surnames containing another ko.observableArray

Related

Datatable view is not in style/standard format

I am trying to figure out what I've missed during my coding on my project. My problem is my datatable format/style is not what it seems to look like from standard format. I'm using ASP.net MVC.
This is the output: Page numbers, search box is not in style
Page numbers, search box is not in style
Here is my code:
<div class="row">
<div class="col-sm-20c">
<div class="panel-body">
<table id="tbl-transaction" class="table table-bordered" cellspacing="0" width="100%" align="center">
<thead>
<tr>
<th>Transaction No</th>
<th>Purpose of Visit</th>
<th>Name of Host</th>
<th>Transacted By</th>
<th>Details</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
#section Scripts
{
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.dataTables.min.js"></script>
<script>
getall();
function getall()
{
$('#tbl-transaction').dataTable().fnDestroy();
$('#tbl-transaction').DataTable({
"ajax": {
"url": '/FSEWeb/Admin/GetAllTransactions',
"type": "get",
"datatype" : "JSON"
},
"columns" :
[
{ data :"TransactionNumber"},
{ data: "PurposeOfVisit" },
{ data: "NameOfHostFromST" },
{ data: "TransactedBy" },
{
data: null, "render" : function(data,type,row)
{
return '<button class= "btn btn-success" onclick = "get_details(' + data.id + ',' + data.TransactionNumber + ')"> Details </button>';
}
}
]
})
}
This table format is what I want to look like.
Desired output with styles
You have not incorporated JQuery Datatbles style sheet i.e.
<!-- Data table -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.10/css/dataTables.bootstrap.min.css " />
Incorporate it at layout level or page level.

KendoUI Template with Observable with NumericTextbox

I have the following KendoUI template bound to an observable. When I push a new item to the observable array, how do I apply the kendoNumericTextBox to only the new item in the template?
If I apply by class, it has a strange effect of doubling the spinners on the existing numeric textboxes.
<div id="slots">
<table class="table table-striped table-condensed" style="width:auto;">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Volunteers Needed</th>
<th>
Reservation Passcode <i class="icon-question-sign" title ="Only people with the reservation passcode can signup."></i>
</th>
</tr>
</thead>
<tbody data-template="row-template" data-bind="source: slots">
</tbody>
</table>
</div>
$(document).ready(function () {
var viewModel = kendo.observable({
slots: [{DateText:'1/8/1969', ShiftLabel: "3:00 to 5:00",Slots:2,ReservationCode:"ABC" }]
});
kendo.bind($("#slots"), viewModel);
$(".numeric").kendoNumericTextBox({
format: "n0"
});
viewModel.slots.push({DateText:'1/8/1969', ShiftLabel: "3:00 to 5:00",Slots:2,ReservationCode:"ABC" });
$(".numeric").kendoNumericTextBox({
format: "n0"
});
});
Thanks for any help!
Try defining your template as:
<script type="text/x-kendo-tmpl" id="row-template">
<tr>
<td>#= DateText #</td>
<td>#= ShiftLabel #</td>
<td class="numeric"><input data-role="numerictextbox" data-format="n0" data-bind="value: Slots"></td>
<td>#= ReservationCode #</td>
</tr>
</script>
and remove the $(".numeric").kendoNumericTextBox(...) initializations. Doing this you should have a NumericTextBox each time the template is run (one per row).
Your JavaScript is like this:
$(document).ready(function () {
var viewModel = kendo.observable({
slots: [
{DateText: '1/8/1969', ShiftLabel: "3:00 to 5:00", Slots: 2, ReservationCode: "ABC" }
]
});
kendo.bind($("#slots"), viewModel);
viewModel.slots.push({DateText: '1/8/1969', ShiftLabel: "3:00 to 5:00", Slots: 3, ReservationCode: "ABC" });
});
See it running here http://jsfiddle.net/OnaBai/BV48W/
Why:
The fact that you use a CSS class (.numeric) causes you end up having a KendoUI Numeric Text Box inside the other.
Example: You have the following HTML:
<label>Number 1: <input id="number1" class="numeric"/></label>
<label>Number 2: <input id="number2" class="numeric"/></label>
And the JavaScript
$(document).ready(function () {
$(".numeric").kendoNumericTextBox({
format: "n0"
});
$(".numeric").kendoNumericTextBox({
format: "n0"
});
});
You will see what you called strange effect of doubling the spinners on the existing numeric textboxes.
Each time that you invoke kendoNumericTextBox using .numeric selector you add one extra spinner to the element. If it does not have a spinner (data just added to viewModel) it gets one but if then you add data and invoke kendoNumericTextBox using .numeric selector, that previous element gets another.

How to retrieve multiple records from Jquery to my RazorView page

I have a button "btnGetAddress" on my razor page .On clik of this button,I am calling a Jquery to get my addressItmes object to be displayed on to my View page.
On clicking "btnGetAddress" I am able to hit my "JsonResult GetAddresses()" and retrieve records within my Jquery (success: function (data)).and this data has multiple address records. But I do not know how to take this data to my view .Please help me to get my data to be displayed on to my View
When my page get loaded,the user will see only the "btnGetAddress" button .When the user click on the btnGetAddress, it will call the Jquery Click function to fetch all address records from database and display each set of records on the page
$("#btnGetAddress").click(function () {
debugger;
var selected = $("#ddlType").val();
if (selected == "")
{ selected = 0; }
var dataToSend = {
SelectedTypeId: selected
};
$.ajax({
type: "GET",
url: '#Url.Action("GetAddresses", "Content")',
data: { SelectedTypeId: selected },
success: function (data) {
debugger;
},
error: function (error) {
var verr = error;
alert(verr);
}
});
pasted below is my JsonResult GetAddresses() which gets called to retrieve addressItems
public JsonResult GetAddresses()
{
model.AddressItems = AddressService.RetrieveAllAddress();
// My AddressItems is of type IEnumerable<AddressItems>
return Json(model.AddressItems, JsonRequestBehavior.AllowGet);
}
Here is my razor View Page where the address records are to be displayed.
........................
<input type="submit" id="btnGetAddress" name="btnSubmit" value="Show Addresses" />
if (!UtilityHelper.IsNullOrEmpty(Model.AddressItems))
{
foreach (var AddressRecord in Model.AddressItems)
{
<fieldset >
<legend style="padding-top: 10px; font-size: small;">Address Queue(#Model.NumRecords)
</legend>
<table>
<tr>
<td>
<span>Index</span>
</td>
<td>
</td>
<td>
<input type="submit" id="btnDelete" name="btnSubmit" value="X" />
<br />
</td>
</tr>
<tr>
<td>
<span>Address1</span>
<br />
</td>
<td>
#Html.EditorFor(model => AddressRecord.Address )
#Html.ValidationMessageFor(model => AddressRecord.Address)
</td>
</tr>
<tr>
<td>
<span>Description</span>
<br />
</td>
<td>
#Html.EditorFor(model => AddressRecord.Description)
#Html.ValidationMessageFor(model => AddressRecord.Description)
</td>
</tr>
<tr>
<td>
<input type="submit" id="btnSave" name="btnSubmit" value="Save" />
</td>
<td>
<input type="submit" id="btnDelete" name="btnSubmit" value="Delete" />
</td>
</tr>
</table>
</fieldset>
}
}
<fieldset>
Or is there any better way to achieve my objective?
Since you are getting the data via ajax you should use a jquery template engine. Basically get the data the way you are and on success you do something like
<script language="javascript" type="text/javascript">
$(function () {
$.getJSON("/getprojects", "", function (data) {
$("#projectsTemplate").tmpl(data).appendTo("#projectsList");
});
});
</script>
<script id="projectsTemplate" type="text/html">
<section>
<header><h2>Projects</h2></header>
<table id="projects">
<th>Name</th>
{{tmpl(items) "#projectRowTemplate"}}
</table>
</section>
</script>
<script id="projectRowTemplate" type="x-jquery-tmpl">
<tr>
<td>${name}</td>
</tr>
</script>
<div id="projectsList"></div>
Now each template engine is different but the above gives you an idea of what you can do
If you want to return JSON object in your controller, you are going have to turn your view into a string and return it as part of the message. If you google there are some methods out there that can do this.
However, I really think that's the hard way, why not take the data you get from the JSON in the controller and put it in a MODEL and then return your VIEW with the model data passed in. I think that's the easier way.

jquery error this.source is not a function

Hi I am trying to catch an array of string from a class called AjaxFacade using DWR and I am using jquery to autocomplete a text box snippetof my jsp code is as follows
<%
String path = request.getContextPath();
%>
<script type='text/javascript' src='<%=path%>/dwr/interface/ajaxFacade.js'></script>
<script type='text/javascript' src='<%=path%>/dwr/engine.js'></script>
<script type='text/javascript' src='<%=path%>/dwr/util.js'></script>
<script>
$(function()
{
var countries ;
countries = ajaxFacade.getCountries();
$("#tags").autocomplete({source : countries});
});
</script>
<tr>
<td align="left" valign="top" bgcolor="e3ddc7">
<div align="right"><strong> <font color="red">*</font>Old E-mail Address:</strong></div>
</td>
<td align="left" valign="top" bgcolor="#FFFFFF">
<html:text name="amsUserRequestForm" property="oldEmail" size="20" styleClass="ui-widget" styleId="tags">
</html:text></td>
</tr>
Function in AjaxFacade class is as follows
public String[] getUsers() {
String[] countries = {
"India",
"Iran",
"Iraq",
"Indoneshia",
"Ireland"
};
return countries;
}
No matter what I do it keeps me giving error this.source is not a function. Any help is greatly appreciated
make sure that the countries are filled with data make sync json call if needed.

ajax gif loader

can you tell me where and how to put an ajx loading.gif?
my html code is below
<div class="searchbox">
<input id="Search" onkeyup="searchKeyUp(event)
" name="Search" class="searchtextbox"/>
</div>
</td>
<td width="57"><br> <img onclick="search(); return false;" style=" cursor:pointer" eight="30" onmouseover="this.src='images/j3.jpg'" type="image" src="images/j1.jpg" onmouseout="this.src='images/s1.jpg';" alt="" width="57" ></td>
</tr>
</table>
<div>
<table cellspacing="0" cellpadding="0" border="0">
<tr valign="left">
<td><div class="resultCss" content="tableId" id='resultDiv'>
</div></td>
</tr>
</table>
Before your AJAX request starts , display the ajax_load.gif and after it ends, remove it.
Tip: Make sure you have only 1 AJAX request sent to your server at a time like https://www.buxfer.com
build in on the position you want to have it and give display:none on it. In search() before AJAX Call edit the display:none to block and hide the image onSuccess off the AJAX function again.
You need to place gif file to any proper place and set "display:none;"
You can use my function based on jQuery. It automatically shows or hide the spinner on every ajax call.
function simpleAjax(pageUrl , divId , spinnerId , formId , isFormEnabled)
{
var dataVar ='';
var d = new Date();
if(isFormEnabled)
dataVar = $('#'+formId).serialize();
$.ajax(
{
type: 'GET',
url: pageUrl,
cache:false,
data:dataVar,
success: function(response){ $('#'+divId).html(response); $('#'+spinnerId).hide(); },
beforeSend: function(){ $('#'+spinnerId).show();},
error: function(m){ alert(m); },
complete: function(){}
});
}

Resources