YUI Datatable - "Data Error." - javascript

I'm trying to make a datatable using YUI with JSON returned data.
Included is the json returned data, and the page data displayed.
JSON Data:
[{"supplier_id":"127","name":"Adams Farms","description":"","ofarm":"1","active":"1"},{"supplier_id":"141","name":"Barriger Farms","description":"","ofarm":"1","active":"1"}]
Javascript for YUI:
<script type="text/javascript">
YAHOO.util.Event.addListener(window, "load", function() {
YAHOO.example.JSON = function() {
var myColumnDefs = [
{key:"supplier_id", label:"ID"},
{key:"name", label:"Name"},
{key:"description", label:"Notes"},
{key:"ofarm", label:"Ofarm"},
{key:"active", label:"Active"}
];
var myDataSource = new YAHOO.util.DataSource("ajax/select/supplier");
myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
myDataSource.responseSchema = {
fields: ["supplier_id","name","description","ofarm","active"]
};
var myDataTable = new YAHOO.widget.DataTable("json", myColumnDefs,
myDataSource);
return {
oDS: myDataSource,
oDT: myDataTable
};
}();
});
</script>
Page View:
YUI Test (header)
This example populates a DataTable with data. (intro text)
ID - Name - Notes - Ofarm - Active (column titles)
Data error. (returned data)

According to YUI dataSource page, YUI dataSource expectes an JavaScript object, not an array of objects. And when using JSON, use must set a resultsList on the responseSchema property. Something as (Notice dataSourceSettings.responseSchema.fields property)
(function() {
var YdataTable = YAHOO.widget.DataTable,
YdataSource = YAHOO.util.DataSource;
var settings = {
container:"<DATATABLE_CONTAINER_GOES_HERE>",
source:"<URL_TO_RETRIEVE_YOUR_DATA>",
columnSettings:[
{key:"supplier_id", label:"ID"},
{key:"name", label:"Name"},
{key:"description", label:"Notes"},
{key:"ofarm", label:"Ofarm"},
{key:"active", label:"Active"}
],
dataSourceSettings:{
responseType:YdataSource.TYPE_JSON,
responseSchema:{
resultsList:"<DOT_NOTATION_LOCATION_TO_RESULTS>",
fields:[
{key:"supplier_id"},
{key:"name"},
{key:"description"},
{key:"ofarm"},
{key:"active"}
]
}
},
dataTableSettings:{
initialLoad:false
}
}
var dataTable = new YdataTable(
settings.container,
settings.columnSettings,
new YdataSource(
settings.source,
settings.dataSourceSettings),
settings.dataTableSettings);
})();

As a side note, I found this page when looking for the cause of "Data error" in a YUI datatable, and I eventually found out that I was missing the /build/connection/connection-min.js script reference on my web page.

Related

Databinding with Knockout JS not working

I'm trying to bind my JSON object to a HTML div but none of the bindings seem to work. This is my current try on the subject. But I have tried using the template binding already. That resulted in an undefined error , but the object is correctly loaded because i always get it in the console.
$(document).ready(function () {
var submissionViewModel = new SubmissionModel();
submissionViewModel.getSubmission().done(function () {
ko.applyBindings(submissionViewModel, document.getElementById("submission"));
})
});
var SubmissionModel = function () {
var self = this;
//self.loading = ko.observableArray();
self.Submission = ko.observable(null);
self.getSubmission = function () {
// Let loading indicator know that there's a new loading task that ought to complete
//self.loading.push(true);
return $.getJSON('/Submission/GetSubmission',
function (data) {
console.log("submission loading")
console.dir(data);
self.Submission = ko.mapping.fromJSON(JSON.stringify(data));
}
);
}
}
HTML
<div id="submission" data-bind="with: Submission">
<span data-bind="text: SubmissionTitle"></span>
</div>
JSON
"{"
SubmissionID":"1be87a85-6d95-43aa-ad3c-ffa047b759a5",
"SubmissionTitle":"nog wat sliden",
"SubmissionDescription":"////",
"SubmissionFile":"TESTFILE ",
"CreatedOn":"2015-09-02T21:10:54.913",
"SubmissionPoolID":"5af408f5-515c-4994-88dd-dbb2e4a242a2",
"SubmissionTypeID":1,
"CreatedBy":"a028a47d-3104-4ea4-8fa6-7abbb2d69bbd
"}"
I have been chewing on this problem for a few days now an I can't seem to get it to work. Could any of you point me in the right direction ?
In java-script to decode object inside string you need to use JSON.parse and make sure your object is not structured in such way double quote inside double quote .
viewModel:
var json = '{"SubmissionID":"1be87a85-6d95-43aa-ad3c-ffa047b759a5","SubmissionTitle":"nogwatsliden","SubmissionDescription":"--","SubmissionFile":"TESTFILE ","CreatedOn":"2015-09-02T21:10:54.913","SubmissionPoolID":"5af408f5-515c-4994-88dd-dbb2e4a242a2","SubmissionTypeID":1,"CreatedBy":"a028a47d-3104-4ea48fa67abbb2d69bbd"}'
var ViewModel = function () {
this.Submission = ko.observable();
this.Submission(ko.mapping.fromJS(JSON.parse(json)));
//you can also use ko.mapping.fromJSON(json) as jeroen pointed out
};
ko.applyBindings(new ViewModel());
working sample here

Inline editing - save new values on button click

I have following code for jQuery DataTables:
Contact.DataTable = $('#otable').DataTable( {
"ajax": {
"url" : '/Contact/' + Contact.id,
"dataSrc": function(check) {
return check.data;
},
},
"responsive": true,
"columns": [
{ "data": "id"},
{ "data": "category", "sClass": "category" },
{ "data": "name", "sClass": "name" },
{ "data": "lname" },
{
"render": function ( data, type, method, meta ) {
return Contact.saveContact(method);
}
},
]
} );
Datatable - dropdown - inline edit:
$('#otable tbody').on('click', '.category', function () { //second column
var row = this.parentElement;
if(!$('#otable').hasClass("editing")){
$('#otable').addClass("editing");
var data = Contact.DataTable.row(row).data();
var $row = $(row);
var thiscategory = $row.find("td:nth-child(2)");
var thiscategoryText = thiscategory.text();
thiscategory.empty().append($("<select></select>",{
"id":"category" + data[0],
"class":"in_edit"
}).append(function(){
var options = [];
$.each(Categories, function(key, value){
options.push($("<option></option>",{
"text":value,
"value":value
}))
})
return options;
}));
$("#category" + data[0]).val(thiscategoryText)
}
})
;
For changing values in dropdown
$('#otable tbody').on("change", ".in_edit", function(){ //Inline editing
var val = $(this).val();
$(this).parent("td").empty().text(val);
$('#otable').removeClass("editing");
});
Below code for saving new values(after inline edit) while clicking save:
$('#divsave').on("click", ".saveContact", function() {
var data = Contact.DataTable.row($(this).closest('tr')).data();
// Here I have to get new values after inline editing - but getting old values
});
My problem is : while clicking edit, in 'data', I am getting old values in the row of datatable, not the modified value after inline edit
datatable view - 1:
datatable - dropdown in column:
datatable after inline editing:
What I need: Save modified row while clicking 'save' image - currently it saves older value before inline editing(datatable view - 1)
When using dataTables it is generally a very bad idea to manipulate the DOM <table> or any content by "hand" - you should always go through the dataTables API.
Thats why you are getting "old values" - you have manipulated the content of the <table>, or so it seems - dataTables are not aware of those changes.
In a perfect world you should refactor the setup completely (i.e to use the API) but I guess you can solve the issue by using invalidate() on the row being changed in order to refresh the dataTables internals :
$('#otable tbody').on("change", ".in_edit", function(){ //Inline editing
var val = $(this).val();
$(this).parent("td").empty().text(val);
//add this line to refresh the dataTables internals
Contact.DataTable.row($(this).parent("tr")).invalidate();
//
$('#otable').removeClass("editing");
});

SAPUI5 Filling SmartTable with OData from XMII

I'm currently trying to fill a Smart Table (xml view) with OData from our MII server.
I keep getting the following errors:
Error: resource PATH/Component-changes.json could not be loaded from ./Component-changes.json. Check for 'file not found' or parse errors. Reason: Not Found -
'getChanges' failed: -
This is my Main.controller.js:
sap.ui.controller("PATH.view.Main", {
/**
* Called when a controller is instantiated and its View controls (if available) are already created.
* Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
* #memberOf sapui5.Main
*/
onInit: function() {
var oModel, oView;
this.oUpdateFinishedDeferred = jQuery.Deferred();
this.getView().byId("main").attachEventOnce("updateFinished", function(){
this.oUpdateFinishedDeferred.resolve();
}, this);
sap.ui.core.UIComponent.getRouterFor(this).attachRouteMatched(this.onRouteMatched , this);
var oModel, oView;
oModel = new sap.ui.model.odata.ODataModel("http://server:port/XMII/IlluminatorOData/QueryTemplate?QueryTemplate=MessageMonitor%2FTemplates%2FQuery%2FMIILogDetailsQry&Content-Type=text%2Fxml", {annotationURI: "/XMII/IlluminatorOData/$metadata"});
jQuery.sap.log.error(oModel.getMetaModel());
oModel.setCountSupported(false);
var oTable = this.getView().byId("oTable");
oTable.setEntitySet("Messages");
oTable.setModel(oModel);
oView = this.getView();
oView.setModel(oModel);
oTable.rebindTable();
},
onRouteMatched : function(oEvent) {
var oList = this.getView().byId("main");
var sName = oEvent.getParameter("name");
var oArguments = oEvent.getParameter("arguments");
// Wait for the list to be loaded once
jQuery.when(this.oUpdateFinishedDeferred).then(jQuery.proxy(function() {
var aItems;
// On the empty hash select the first item
if (sName === "main") {
//this.selectDetail();
}
// Try to select the item in the list
if (sName === "product") {
aItems = oList.getItems();
for (var i = 0; i < aItems.length; i++) {
if (aItems[i].getBindingContext().getPath() === "/" +
oArguments.product) {
oList.setSelectedItem(aItems[i], true);
break;
}
}
}
}, this));
},
});
I'm developing on the server itself so I have no issues with the CORS errors I would get otherwise.
My Main.view.xml:
<core:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:smartFilterBar="sap.ui.comp.smartfilterbar" xmlns:smartTable="sap.ui.comp.smarttable" controllerName="PATH.view.Main" height="100%" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:app="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1">
<Page id="main" title="{i18n>PageTitle}" showNavButton="false">
<Toolbar></Toolbar>
<content>
<smartFilterBar:SmartFilterBar id="smartFilterBar" entityType="Messages" persistencyKey="SmartFilter_Explored">
<smartFilterBar:controlConfiguration>
<smartFilterBar:ControlConfiguration key="CATEGORY">
<smartFilterBar:defaultFilterValues>
<smartFilterBar:SelectOption low="i">
</smartFilterBar:SelectOption>
</smartFilterBar:defaultFilterValues>
</smartFilterBar:ControlConfiguration>
<smartFilterBar:ControlConfiguration key="DATETIME">
<smartFilterBar:defaultFilterValues>
<smartFilterBar:SelectOption low="2014">
</smartFilterBar:SelectOption>
</smartFilterBar:defaultFilterValues>
</smartFilterBar:ControlConfiguration>
</smartFilterBar:controlConfiguration>
</smartFilterBar:SmartFilterBar>
<smartTable:SmartTable id="oTable" entitySet="Messages"
smartFilterId="smartFilterBar" tableType="Table"
useExportToExcel="false" useVariantManagement="false"
useTablePersonalisation="false" header="Messages"
showRowCount="false"
persistencyKey="SmartTableAnalytical_Explored"
enableAutoBinding="true" />
</content>
</Page>
My Component.js, index.html and MyRouter.js are setup according to the SAP Hana step by step guide for your first application.
I'm completely clueless on what the issue might be.
Thanks in advance.
The file component-changes.json is read for Variant Management but this should not prevent the data in smart table from loading. And since you have set enableAutoBinding does the system make a call to your Service/Messages?
I've ended up doing something entirely else due to the fact the metadata wasn't the right data I needed for the Smart-Table. Thanks for the answers to the question.
I've created a default table in my controller, which I filled with the columns I needed and wanted. And I've bound my rows to the columns.
var oTable = new sap.ui.table.Table();
oTable.addColumn(new sap.ui.table.Column({label: "{i18n>Category}", editable: false,
template: new sap.ui.commons.TextField( {
value: {
path: "CATEGORY",
formatter: sap.ui.demo.table.util.Formatter.label,
},
editable : false,
}), sortProperty: "Category" }));
// more addColumn lines...
oTable.setSelectionMode(sap.ui.table.SelectionMode.Single); // Single select mode.
oTable.bindRows({ // bind the rows to the odata model.
path: '/Rowset(QueryTemplate=\'MessageMonitor/Templates/Query/UniqueGUIDs\',RowsetId=\'1\')/Row',
});
this.getView().byId("idIconTabBar").insertContent(oTable); // add the table to the icontabbar

Knockout Nested Bindings--Visible in DOM but won't display

I've got an issue where my viewmodel has an observable object that contains observable properties. When I try to access those properties they don't display. I can, however, see that all the properties with values are visible in the DOM using the Knockout chrome extension.
My code looks like:
viewmodel:
self.device=ko.observable();
self.device(querydevice.query({"url": self.url, "ref":self.ref}));
query code:
define(['jquery','knockout','hsd'], function ($,ko, device) {
return{
query:function (params) {
var hsdevice=ko.observable();
self.url=params.url;
self.ref=params.ref;
var controlData = $.getJSON(self.url + "/JSON?request=getcontrol&ref=" + self.ref);
var statusData = $.getJSON(self.url + "/JSON?request=getstatus&ref=" + self.ref);
$.when(controlData, statusData).done(function (_cdata, _sdata) {
var data = $.extend(_cdata[0], _sdata[0]);
hsdevice(new device(data));
});
return hsdevice;
}};
});
device object:
define(['knockout'], function (ko) {
return function device (data){
var self=this;
self.deviceName = ko.observable(data.Devices[0].name);
self.value = ko.observable(data.Devices[0].value);
self.status =ko.observable(data.Devices[0].status);
self.controlPairs = ko.observableArray();
ko.utils.arrayPushAll(self.controlPairs, data.ControlPairs);
};
});
This is what I see being returned:
" device": Object
controlPairs: Array[2]
deviceName: "Garage Hall Light"
status: "Off"
value: 0
In my HTML I have this:
<span class="tile-title align-" data-bind="with: device.deviceName"></span>
I've also tried using data-bind:"text: device().deviceName", but that doesn't work either. Nothing displays. I can however access over observable properties that are on the viewmodel. The only difference is that they're single level properties with no sub-binding. So I am able to see something like self.test("test") in my html but not my self.device with the nested databinds.
Any ideas what I'm doing wrong?
Thanks!
It looks like you are using jquery promises. what you need to do is return the $.when
something like
define(['jquery','knockout','hsd'], function ($,ko, device) {
return{
query:function (params) {
self.url=params.url;
self.ref=params.ref;
var controlData = $.getJSON(self.url + "/JSON?request=getcontrol&ref=" + self.ref);
var statusData = $.getJSON(self.url + "/JSON?request=getstatus&ref=" + self.ref);
return $.when(controlData, statusData).done(function (_cdata, _sdata) {
var data = $.extend(_cdata[0], _sdata[0]);
return new device(data);
});
}};
});
then you end up with something like this.
querydevice.query({"url": self.url, "ref":self.ref})
.when(function(data){
self.device(data);
return true;
});
Thanks to Nathan for his code contribution. I was finally able to access my nested properties in the html by using:
<!-- ko with: device -->
<!-- /ko -->
and THEN data-bind to the property I needed.

Change DropDownList data with Javascript

I have a page where a user can select if the transaction type is an inter accounts transfer, or a payment.
The model I pass in had two lists.
One is a list of SelectListItem
One is a list of SelectListItem
One of the lists is populated like this:
var entities = new EntityService().GetEntityListByPortfolio();
foreach (var entity in entities.Where(x=>x.EntityTypeId == (int)Constants.EntityTypes.BankAccount))
{
model.BankAccounts.Add(new SelectListItem
{
Value = entity.Id.ToString(CultureInfo.InvariantCulture),
Text = entity.Description
});
}
If the user selects 'Inter account transfer', I need to:
Populate DropdownA with the list from Accounts, and populate DropdownB with the same list of Accounts
If they select "Payment", then I need to change DrowdownB to a list of ThirdParty.
Is there a way, using javascript, to change the list sources, client side?
function changeDisplay() {
var id = $('.cmbType').val();
if (id == 1) // Payment
{
$('.lstSource'). ---- data from Model.ThirdParties
} else {
$('.lstSource'). ---- data from Model.Accounts
}
}
I'd prefer not to do a call back, as I want it to be quick.
You can load the options by jquery Code is Updated
Here is the code
You will get everything about Newton Json at http://json.codeplex.com/
C# CODE
//You need to import Newtonsoft.Json
string jsonA = JsonConvert.SerializeObject(ThirdParties);
//Pass this jsonstring to the view by viewbag to the
Viewbag.jsonStringA = jsonA;
string jsonB = JsonConvert.SerializeObject(Accounts);
//Pass this jsonstring to the view by viewbag to the
Viewbag.jsonStringB = jsonB;
You will get a jsonstring like this
[{"value":"1","text":"option 1"},{"value":"2","text":"option 2"},{"value":"3","text":"option 3"}]
HTML CODE
<button onclick="loadListA();">Load A</button>
<button onclick="loadListB();">Load B</button>
<select name="" id="items">
</select>
JavaScript Code
function option(value,text){
this.val= value;
this.text = text;
}
var listA=[];
var listB=[];
//you just have to fill the listA and listB by razor Code
//#foreach (var item in Model.ThirdParties)
//{
// <text>
// listA.push(new option('#item.Value', '#item.Text'));
// </text>
// }
//#foreach (var item in Model.Accounts)
// {
// <text>
// listA.push(new option('#item.Value', '#item.Text');
// </text>
// }
listA.push(new option(1,"a"));
listA.push(new option(2,"b"));
listA.push(new option(3,"c"));
listB.push(new option(4,"x"));
listB.push(new option(5,"y"));
listB.push(new option(6,"z"));
function loadListA(){
$("#items").empty();
listA.forEach(function(obj) {
$('#items').append( $('<option></option>').val(obj.val).html(obj.text) )
});
}
function loadListB(){
$("#items").empty();
listB.forEach(function(obj) {
$('#items').append( $('<option></option>').val(obj.val).html(obj.text) )
});
}
NEW Javascript Code fpor Json
var listA=[];
var listB=[];
var jsonStringA ='[{"val":"1","text":"option 1"},{"val":"2","text":"option 2"},{"value":"3","text":"option 3"}]';
var jsonStringB ='[{"val":"4","text":"option 4"},{"val":"5","text":"option 5"},{"value":"6","text":"option 6"}]';
//you just have to fill the listA and listB by razor Code
//var jsonStringA = '#Viewbag.jsonStringA';
//var jsonStringB = '#Viewbag.jsonStringB';
listA = JSON.parse(jsonStringA);
listB = JSON.parse(jsonStringB);
function loadListA(){
$("#items").empty();
listA.forEach(function(obj) {
$('#items').append( $('<option></option>').val(obj.val).html(obj.text) )
});
}
function loadListB(){
$("#items").empty();
listB.forEach(function(obj) {
$('#items').append( $('<option></option>').val(obj.val).html(obj.text) )
});
}
Here is the fiddle http://jsfiddle.net/pratbhoir/TF9m5/1/
See the new Jsfiddle for Json http://jsfiddle.net/pratbhoir/TF9m5/3/
ofcourse you can so that
try
var newOption = "<option value='"+"1"+'>Some Text</option>";
$(".lstSource").append(newOption);
or
$(".lstSource").append($("<option value='123'>Some Text</option>");
Or
$('.lstSource').
append($("<option></option>").
attr("value", "123").
text("Some Text"));
Link for reference
B default, I don't think the concept of "data-source" means something in html/javascript
Nevertheless, the solution you're looking for is something like knockoutjs
You'll be able to bind a viewmodel to any html element, then you will be able to change the data source of your DropDownList
see : http://knockoutjs.com/documentation/selectedOptions-binding.html

Categories