Data not binding to table using KnockoutJS - javascript

I am working on my first custom-built KO implementation and I had the data binding to the table in my page, but not it's not binding to it. I can verify that my web service is getting called and it's returning data. However, I don't know why the data isn't loading into the table since I am not getting any errors.
I am sure I am missing something simple since I am a newb to this. :)
I am using KO 3.1.0.
PAGE MARKUP
<table class="dnnGrid">
<thead>
<tr class="dnnGridHeader">
<th>Task ID</th>
<th>Name</th>
<th>Description</th>
<th>Date Updated</th>
</tr>
</thead>
<tbody data-bind="foreach: tasks">
<tr class="dnnGridRow">
<td data-bind="text: ID"></td>
<td data-bind="text: Name"></td>
<td data-bind="text: Description"></td>
<td data-bind="text: LastUpdatedDate"></td>
</tr>
</tbody>
</table>
PAGE SCRIPT
var sf = $.ServicesFramework(<%=ModuleId %>);
var userId = <%=UserId%>;
var serviceUrl = sf.getServiceRoot('POC');
var moduleId = sf.getModuleId();
$(document).ready(function() {
ko.applyBindings(TaskViewModel);
GetTasks();
$('#lnkSave').click(function() {
SaveTask();
GetTasks();
});
});
IMPORTED SCRIPT
var Task = function(data) {
data = data || {};
var self = this;
self.ID = ko.observable(data.ID);
self.ModuleId = ko.observable(data.ModelId);
self.ContentItemId = ko.observable(data.ContentItemId);
self.Name = ko.observable(data.Name);
self.Description = ko.observable(data.Description);
self.LastUpdatedDate = ko.observable(data.LastUpdatedDate);
self.LastUpdatedBy = ko.observable(data.LastUpdatedBy);
}
var TaskViewModel = function(items) {
var self = this;
var newTask = {
'ID': ko.observable(),
'ModuleId': ko.observable(),
'ContentItemId': ko.observable(),
'Name': ko.observable(),
'Description': ko.observable(),
'LastUpdatedDate': ko.observable(),
'LastUpdatedBy': ko.observable()
};
self.tasks = ko.observableArray(ko.utils.arrayMap(items, function (data) {
return new Task(data);
}));
self.updateTask = function (task) {
GetTasks();
}
}
function SaveTask() {
var task = {
'ModuleId': moduleId,
'LastUpdatedBy': userId,
'Name': $('#txtName').val(),
'Description': $('#txtDescription').val()
}
$.ajax({
type: 'POST',
url: serviceUrl + 'Task/CreateTask',
data: JSON.stringify(task),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
beforeSend: sf.setModuleHeaders,
success: function (data) {
var results = $.parseJSON(data);
ParseResults(results, viewModel);
},
error: function (xhr, ajaxOptions, thrownError) {
alert("STATUS: " + xhr.status + "\nERROR:\n" + thrownError);
}
});
}
function GetTasks() {
if (TaskViewModel) {
if (TaskViewModel.tasks) {
TaskViewModel.tasks.removeAll();
}
}
$.ajax({
type: 'GET',
url: serviceUrl + 'Task/GetTasks?ModuleId=' + moduleId,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
beforeSend: sf.setModuleHeaders,
success: function (data) {
var results = $.parseJSON(data);
TaskViewModel.tasks = results;
},
error: function (xhr, ajaxOptions, thrownError) {
alert("STATUS: " + xhr.status + "\nERROR:\n" + thrownError);
}
});
}

Try moving this line ko.applyBindings(TaskViewModel) to bottom of .ready function
$(document).ready(function() {
GetTasks();
$('#lnkSave').click(function() {
SaveTask();
GetTasks();
});
ko.applyBindings(TaskViewModel);
});
After this line, var results = $.parseJSON(data); add a debugger; statement and open chrome developer tools (F12 key), refresh the page and step through the code using F10 key.
At this point you should be able to see the parsed data in results. If it is not in required format, you may need to assign TaskViewModel.tasks like this
TaskViewModel.tasks = ko.utils.arrayMap(results, function (task) {
return new Task(task);
});

Related

Redirect to list view after updating list item using SPServices.js

I created a custom form to submit list item and attach multiple attachments.
And would need to redirect user to default list view after all the attachments are attached to a list item.
I tried adding window.location.href='default List url' but it redirects while the attachments are getting added.
It works fine for small file(s) but for large file(s), only 1 attachment gets added.
Here is the snippet:
HTML:
var ListTitle = "SubTask";
$( document ).ready(function() {
//$('#attachment').multifile();
$("#NewSaveItem").click(function() {
CreateNewItem();
});
});
function CreateNewItem() {
var data = {
__metadata: { 'type': "SP.Data.SubTaskListItem" },
Title: $('#Title').val()
};
$.ajax({
//_spPageContextInfo.webAbsoluteUrl get current SharePoint site url
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/GetByTitle('" + ListTitle + "')/Items",
type: "POST",
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-Type": "application/json;odata=verbose"
},
// to make sync calls.
async: false,
data: JSON.stringify(data),
success: function (data) {
if (data.d.ID != undefined && data.d.ID > 0){
//Uploads files to SharePoint List item
UploadFileToListItem(data.d);
}
else
{
console.log('Item added successfully');
}
},
error: function (error) {
console.log('Problem saving data');
}
});
// window.location.href = 'https://connect.sharepoint.com/sites/SpApps/Lists/SubTask/';
}
//Once the item is created now let’s try to upload documents to SharePoint list item.
function UploadFileToListItem(data) {
var element = document.getElementById("attachment");
lastFileName = element.files[element.files.length - 1].name;
for (var i = 0; i < element.files.length; i++) {
var file = element.files[i];
uploadFile(data, file);
}
alert('Done');
window.location.href = 'https://connect.sharepoint.com/sites/SpApps/Lists/SubTask/';
}
//uploads single file at a time.
function uploadFile(data, file) {
var getFileBuffer = function (file) {
var deferred = $.Deferred();
var reader = new FileReader();
reader.onload = function (e) {
deferred.resolve(e.target.result);
}
reader.onerror = function (e) {
deferred.reject(e.target.error);
}
reader.readAsArrayBuffer(file);
return deferred.promise();
};
getFileBuffer(file).then(function (buffer) {
var binary = "";
var bytes = new Uint8Array(buffer);
var i = bytes.byteLength;
while (i--) {
binary = String.fromCharCode(bytes[i]) + binary;
}
var fileName = file.name;
var error = ''
$().SPServices({
operation: "AddAttachment",
async: false,
listName: ListTitle,
listItemID: data.Id,
fileName: fileName,
attachment: btoa(binary),
completefunc: function (xData, Status) {
console.log(file.name + " uploaded");
}
});
});
}
<table align="left" border="1" cellpadding="0" cellspacing="0" >
<tbody>
<tr>
<td valign="top">
<h3> Name</h3>
</td>
<td valign="top" style="padding:9px;">
<input type="text" value="" maxlength="255" id="Title" title="Name" style="width: 96%;" ms-spellcheck-true">
</td>
</tr>
<tr >
<td >
<span style="font-family: " segoe ui" ,sans-serif; color: #444444">
Click here to attach file
</span>
<div id="attachFilesHolder ">
<input type="file" id="attachment" name="FileUpload" multiple/>
</div>
</td>
<td>
</td>
</tr>
</table>
<div>
<input name="SaveItem" style=" height: 40px; font-size: 15px;" id="NewSaveItem" accesskey="O" onclick="" type="button" value="Click here to submit " target="_self">
</div>
Please let me know where am i going wrong.
Define a uploadedCount variable in SPServices complete func and then when uploading file to list item, check if the files count in upload box is equal to the uploaded count, then use SetInterval to trace like this:
var ListTitle = "SubTask";
var fileCount=0;
var uploadCount=0;
$( document ).ready(function() {
//$('#attachment').multifile();
$("#NewSaveItem").click(function() {
CreateNewItem();
});
});
function CreateNewItem() {
var data = {
__metadata: { 'type': "SP.Data.SubTaskListItem" },
Title: $('#Title').val()
};
$.ajax({
//_spPageContextInfo.webAbsoluteUrl get current SharePoint site url
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/GetByTitle('" + ListTitle + "')/Items",
type: "POST",
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-Type": "application/json;odata=verbose"
},
// to make sync calls.
async: false,
data: JSON.stringify(data),
success: function (data) {
if (data.d.ID != undefined && data.d.ID > 0){
//Uploads files to SharePoint List item
UploadFileToListItem(data.d);
}
else
{
console.log('Item added successfully');
}
},
error: function (error) {
console.log('Problem saving data');
}
});
// window.location.href = 'https://connect.sharepoint.com/sites/SpApps/Lists/SubTask/';
}
//Once the item is created now let’s try to upload documents to SharePoint list item.
function UploadFileToListItem(data) {
var element = document.getElementById("attachment");
lastFileName = element.files[element.files.length - 1].name;
//file count
fileCount=element.files.length;
for (var i = 0; i < element.files.length; i++) {
var file = element.files[i];
uploadFile(data, file);
}
//alert('Done');
setInterval(function(){
if(fileCount!=0&&fileCount==uploadCount){
window.location.href = 'https://connect.sharepoint.com/sites/SpApps/Lists/SubTask/';
}
}, 1000);
}
//uploads single file at a time.
function uploadFile(data, file) {
var getFileBuffer = function (file) {
var deferred = $.Deferred();
var reader = new FileReader();
reader.onload = function (e) {
deferred.resolve(e.target.result);
}
reader.onerror = function (e) {
deferred.reject(e.target.error);
}
reader.readAsArrayBuffer(file);
return deferred.promise();
};
getFileBuffer(file).then(function (buffer) {
var binary = "";
var bytes = new Uint8Array(buffer);
var i = bytes.byteLength;
while (i--) {
binary = String.fromCharCode(bytes[i]) + binary;
}
var fileName = file.name;
var error = ''
$().SPServices({
operation: "AddAttachment",
async: false,
listName: ListTitle,
listItemID: data.Id,
fileName: fileName,
attachment: btoa(binary),
completefunc: function (xData, Status) {
console.log(file.name + " uploaded");
uploadCount++;
}
});
});
}

For loop issue in angualrjs and javascript

Hi i have an array in this 7 object are present and 3 invertors, means
accoding to the data im getting columns correctly but columns are
wrong, how many invertors have been created on the particular date
those many should come. if that present day 2 inverotrs are 2 columns
should come dynamically... which i am not getting can any one help me out.
var url = "http://52.9.55.95:91/api/ExcelDetails/ExcelExportForLog?Sid=1&FromDt=2017-02-21&ToDt=2017-02-22"
console.log(url);
var tabledata=[];
$scope.inventorarray=[];
http({
method: 'GET',
dataType: 'json',
contentType: "application/json; charset=utf-8",
url: url
}).
success(function (data, status, headers, config) {
// $scope.loaded = true;
$scope.data = data;
$timeout(function () { $scope.loaded = true; }, 500);
//console.log("reporting to data received : success");
console.log(data);
for(var i=0;i<data.length;i++){
var tdata={
"heading":"InvCount: "+i,
"Date":data[i].TimeofReading.substring(0,10)
}
tabledata.push(tdata);
}
$scope.tablearray=tabledata;
console.log($scope.tablearray)
for(var i=0;i<data.length;i++){
var Lastreadingkey=data[i].Lastreading;
var Readingbykey=data[i].Readingby;
debugger
var tdata={
"Lastreading":Lastreadingkey,
"Readingby":Readingbykey
}
$scope.inventorarray.push(tdata);
}
console.log($scope.inventorarray)
}).
error(function (data, status, headers, config) {
//$scope.loaded = false;
swal({ title: "Warning!", text: "Something went wrong!", type: "warning", confirmButtonText: "OK" });
$timeout(function () { $scope.loaded = true; }, 500);
//console.log("reporting to data received : failure");
//console.log(data);
});
var url = "http://52.9.55.95:91/api/ExcelDetails/ExcelExportForLog?Sid=1&FromDt=2017-02-21&ToDt=2017-02-22"
console.log(url);
var tabledata=[];
$scope.inventorarray=[];
http({
method: 'GET',
dataType: 'json',
contentType: "application/json; charset=utf-8",
url: url
}).
success(function (data, status, headers, config) {
$scope.data = data;
$timeout(function () { $scope.loaded = true; }, 500);
for(var i=0;i<data.length;i++){
var tdata={
"heading":"InvCount: "+i,
"Date":data[i].TimeofReading.substring(0,10)
}
tabledata.push(tdata);
}
$scope.tablearray=tabledata;
console.log($scope.tablearray)
for(var i=0;i<data.length;i++){
var Lastreadingkey=data[i].Lastreading;
var Readingbykey=data[i].Readingby;
debugger
var tdata={
"Lastreading":Lastreadingkey,
"Readingby":Readingbykey
}
$scope.inventorarray.push(tdata);
}
console.log($scope.inventorarray)
}).
error(function (data, status, headers, config) {
//$scope.loaded = false;
swal({ title: "Warning!", text: "Something went wrong!", type: "warning", confirmButtonText: "OK" });
$timeout(function () { $scope.loaded = true; }, 500);
});
$scope.tableToExcel=(function() {
var uri = 'data:application/vnd.ms-excel;base64,'
, template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>'
, base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }
return function(table, name) {
if (!table.nodeType) table = document.getElementById(table)
var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}
window.location.href = uri + base64(format(template, ctx))
}
})()
}]);
myhtml page
<table id="example1" class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th ng-repeat="data in tablearray" colspan="2">{{data.heading}}</th>
</tr>
</thead>
<tr>
<td>Date</td>
<td ng-repeat="data in inventorarray"> <p ng-if="$index%2==0"> Last Reading</p><p ng-if="$index%2>0"> Read By</p> </td>
</tr>
<tr ng-repeat="data in tablearray">
<td> {{data.Date}}</td>
<td ng-repeat="data in inventorarray"> <p ng-if="$index%2==0"> {{data.Lastreading}}</p><p ng-if="$index%2>0">{{data.Readingby}}</p> </td>
</tr>
</table>
can any let know the loop please im stuc here from past 2days.. i
need to be finish today please make fiddle and send me

Loop thru JSON response and return to Jquery

I'm almost there and on my first jquery autocomplete script... I just need some help to figure out how to return the founded elements has link so that we can click on them.
Here a part of my js code:
$(document).ready(function() {
var attr = $('#leseulsteve_lieuxbundle_lieutype_nom').attr('data-url');
var searchRequest = null;
$("#leseulsteve_lieuxbundle_lieutype_nom").autocomplete({
minLength: 3,
source: function(request, response) {
if (searchRequest !== null) {
searchRequest.abort();
}
searchRequest = $.ajax({
url: attr,
method: 'get',
dataType: "json",
data: {nom: request.term},
success: function(data) {
searchRequest = null;
console.log(data);
$.each(data, function (i, v) {
--- SOME VARIABLE I GUESS TO STORE THE RESULT ---
});
return THE 'SOME VARIABLE;
}
}).fail(function() {
searchRequest = null;
});
}
});
});
In the console I got this from the console.log(data) line:
Object {École secondaire De Rochebelle: "/GestigrisC/app_dev.php/lieux/voir/2", École secondaire la Camaradière: "/GestigrisC/app_dev.php/lieux/voir/3"}
I have control over how the JSON feed is built, so no worries there if it's helps to build that super mysterious for me now variable to return.
Thanks a lot for the help!
If you just want to build links and put them into your HTML then I think you're looking for something like this:
success: function(data) {
var html = '';
$.each(data, function (i, v) {
html += ''+i+'';
});
$('#container_id').html(html);
}
Got it right, thanks for your help :)
$(document).ready(function() {
var attr = $('#leseulsteve_lieuxbundle_lieutype_nom').attr('data-url');
var searchRequest = null;
$("#leseulsteve_lieuxbundle_lieutype_nom").autocomplete({
minLength: 3,
source: function(requete, reponse) {
if (searchRequest !== null) {
searchRequest.abort();
}
searchRequest = $.ajax({
url: attr,
method: 'get',
dataType: "json",
data: {nom: requete.term},
success : function(donnee){
reponse($.map(donnee, function(objet){
return {label: objet.type + ' | ' + objet.label, type: objet.type, id: objet.id};
}));
}
}).fail(function() {
searchRequest = null;
});
},
select: function (event, ui) {
$('#leseulsteve_lieuxbundle_lieutype_nom').val(ui.item.label);
$('#leseulsteve_lieuxbundle_lieutype_type').val(ui.item.type);
$('#leseulsteve_lieuxbundle_lieutype_id').val(ui.item.id);
$('#formulaire').submit();
}
});
});

data-bind not displaying data in view page

This is how I have my page set up, but no data is being displayed, and I'm not sure why:
JavaScript/knockout:
var getList = function () {
Ajax.Get({
Url: ...,
DataToSubmit: {id: properties.Id },
DataType: "json",
OnSuccess: function (roleData, status, jqXHR) {
bindModel(roleData);
}
});
};
// Binds the main ViewModel
var bindModel = function (data) {
var _self = viewModel;
ko.applyBindings(viewModel, $('#ListView')[0]);
};
var viewModel = {
ListRoleTypes: ko.observableArray([]),
.....
};
var roleViewModel = function (data) {
var _self = this;
_self.ContentRole = ko.observable(data.ContentRole);
_self.RoleName = ko.observable(data.RoleName);
_self.RoleRank = ko.observable(data.RoleRank);
_self.UserCount = ko.observable(data.UserCount);
};
This is my View page:
<div data-bind="foreach: ListRoleTypes">
<span data-bind="text: RoleName"></span>
</div>
Any thoughts on where I am going wrong?
you are calling bindmodel and passing in the roledata, but then in bindmodel, you dont do anything with it.
Ajax.Get({
Url: ...,
DataToSubmit: {id: properties.Id },
DataType: "json",
OnSuccess: function (roleData, status, jqXHR) {
bindModel(roleData);
}
});
};
// Binds the main ViewModel
var bindModel = function (data) {
// need to do something with viewmodel to handle the passed in data
viewmodel.initialize(data);
ko.applyBindings(viewModel, $('#ListView')[0]);
};

Refreshing ViewModel after deleting data in Knockout.js

I am using Knockout for binding data of a form to the table,now what i ma facing is that when i am deleting the data from the table it goes to server side and delete the data as well but that data remains there unless we refresh the page which not pratical.So what i tried that i am calling the index method on server side which gives me the list of the datas after refreshing the database but when i am doing this.that refreshed datas are appended to the data that remain on the view.i mean it shows the remaing datas and refreshed data both but pratically it shows only the refreshed datas.
My code:
<table id="table2" style="border: double">
<thead>
<tr>
<td>Ticket ID</td>
<td>Ticket Type</td>
<td>No of Tickets</td>
<td>Ticket Price</td>
<td>Start Date</td>
<td>End Date</td>
<td>Action</td>
</tr>
</thead>
<!--Iterate through an observableArray using foreach-->
<tbody id="ticketid" data-bind="foreach:TicketDatas">
<tr style="border: solid" data-bind="click: $root.getselectedTicket" id="updtr">
<td data-bind="text:TicketId">#*<span data-bind="text:No_Of_Ticket"></span>*#</td>
<td data-bind="text:SelectedTicketType">#*<span data-bind="text:No_Of_Ticket"></span>*#</td>
<td data-bind="text:No_Of_Ticket">#*<span data-bind="text:No_Of_Ticket"></span>*#</td>
<td data-bind="text:Ticket_Price">#*<span data-bind="text:Ticket_Price"></span>*#</td>
<td data-bind="text:Start_Date">#*<span data-bind="text:Start_Date"></span>*#</td>
<td data-bind="text:End_Date">#*<span data-bind="text:End_Date"></span>*#</td>
<td><button id="deletelink">Delete</button></td>
</tr>
</tbody>
</table>
<script type="text/javascript">
$("#deletelink").live('click', function () {
if (confirm('Are you sure to Delete this ticket ??')) {
var deleteLink = $(this);
var tableRow = deleteLink.closest('tr');
var firstCell = tableRow.find('td:first-child');
var tickid = firstCell.text();
//var tickid = $("#table2 tbody tr td:eq(0)").html();
$.ajax({
type: "POST",
data: { id: tickid },
url: "Ticket/DeleteTicket",
//data: "{id:" + ko.toJSON(id) + "}",
success: function (data) {
self.TicketDatas.remove(data);
alert("Record Deleted Successfully");
//ko.mapping.fromJS(self.TicketDatas, data)
//GetTickets();//Refresh the Table
},
error: function (error) {
alert(error.status + "<--and--> " + error.statusText);
}
});
// alert("Clicked" + employee.EmpNo)
}
});
function GetTickets() {
//Ajax Call Get All Employee Records
$.ajax({
type: "GET",
cache: false,
url: "Ticket/GetAllTickets",
contentType: "application/json; charset=utf-8",
data: {},
dataType: "json",
success: function (data) {
for (var i = 0; i < data.length; i++) {
self.TicketDatas.push(data[i]);
}
},
error: function (error) {
alert(error.status + "<--and--> " + error.statusText);
}
});
//Ends Here
}
</script>
In your ajax call, I notice you have a success handler like this:
success: function (data) {
self.TicketDatas.remove(data);
alert("Record Deleted Successfully");
//ko.mapping.fromJS(self.TicketDatas, data)
//GetTickets();//Refresh the Table
},
I can see where you're trying to remove the deleted item by calling self.TicketDatas.remove(data);. However, this isn't likely to remove anything from your client-side array of TicketDatas, because you're using the data from the response of the ajax call, and trying to remove that literal object from the array. That actual object isn't in the array, because it was just created from the ajax response.
When removing an object from an array, you either need to reference it by index, or by the an object reference which points to the same memory address as an object in the array.
Try something like this instead:
success: function (data) {
self.TicketDatas.remove(ko.dataFor(deleteLink));
...
},
http://knockoutjs.com/documentation/unobtrusive-event-handling.html
Why bother trying to remove a single ticket from your array when shortly after you ask for all tickets? Also I imagine you don't actually want to use a 'push' if GetTickets really is returning all tickets.
<script type="text/javascript">
$("#deletelink").live('click', function () {
if (confirm('Are you sure to Delete this ticket ??')) {
var deleteLink = $(this);
var tableRow = deleteLink.closest('tr');
var firstCell = tableRow.find('td:first-child');
var tickid = firstCell.text();
**DeleteTicket(tickid);**
}
});
function DeleteTicket(tickid) {
$.ajax({
type: "POST",
data: { id: tickid },
url: "Ticket/DeleteTicket",
success: function (data) {
alert("Record Deleted Successfully");
**GetTickets()**
},
error: function (error) {
alert(error.status + "<--and--> " + error.statusText);
}
});
}
function GetTickets() {
//Ajax Call Get All Employee Records
$.ajax({
type: "GET",
cache: false,
url: "Ticket/GetAllTickets",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
**self.TicketDatas(data);**
},
error: function (error) {
alert(error.status + "<--and--> " + error.statusText);
}
});
//Ends Here
}
</script>

Categories

Resources