Simple JSON issue with kendo-grid - json

Was wondering if you could help me, I've been battling with trying to get my rest JSON data to display correctly in a kendo-grid for a few hours now, and have just worked out it's due to additional nodes on my JSON
$(function() {
var grid = $("#grid").kendoGrid({
dataSource: {
data: {
"ttPortalCommunicationResult": [{
"UniqueID": 7,
"DocumentTitle": "Expense Contribution Scheme Guide",
"ActivationDate": "2012-05-22",
"DeactivationDate": "2020-05-12",
"CategoryDesc": "Operational news"
}],
},
pageSize: 10,
schema: {
data: "ttPortalCommunicationResult"
}
}
}).data("kendoGrid");
});
I get an error Cannot read property 'slice' of undefined.
My question is how can I use only the "ttPortalCommunicationResult" node on JSON data which contains the additional nodes?
I would have assumed kendo would understand how to traverse to that node. An explanation why it can't would also be nice.

Use dataSource schema parse method
schema: {
parse : function(data) {
return data.ttPortalCommunicationResult;
}
}

Related

EmberJS 2.7 How to restructure/reformat/customize data returned from the store

I have what I think is a very simple issue, but I just don't get how to do this data manipulation. This sadly didn't help, even though it's the same pain I am feeling with Ember.
Here is a route:
route/dashboard.js:
import Ember from 'ember';
export default Ember.Route.extend({
// this is for testing, normally we get the data from the store
model: function() {
return this.get('modelTestData');
},
modelTestData: [{
name: 'gear',
colorByPoint: true,
data: [
{y: 10, name: 'Test1'},
{y: 12, name: 'Test2'},
{y: 40, name: 'Test3'}
]
}],
});
The structure of the 'modelTestData' object has to be exactly like that as it is passed into a child component that needs it structured that way.
I can easily get my data from the API and put it into the model:
model: function() {
return this.store.get('category');
},
But then I need to restructure it...but how?
I have to somehow iterate over the categories collection and extract parts of data from each record to replace the 'data' part of the modelTestData object.
So I have 3 issues I am completely stumped on:
How to 'get at' the attributes I need from the model?
How to structure them as an array of objects with 'y' and 'name'?
How to assign that structure to the 'data' property of modelTestData instead of it being hardcoded?
Categories is a JSONAPI object like this:
{
"data":[
{
"id":"1",
"type":"categories",
"attributes":{
"name":"Carrying system",
"total-grams":"0.0"
}
},
{
"id":"2",
"type":"categories",
"attributes":{
"name":"Shelter system",
"total-grams":"0.0"
}
}
]
}
I need to map the grams value to 'y' and the name to 'name' in modelTestData.
Note that the category data is used in other routes for other purposes exactly as returned by the API. So I don't want to change the model structure itself, or what the API returns...that will break other parts of the app that do use 'category' in its original structure.
This is a specific use case that this route needs to massage the data to pass to the child component as per the structure of modelTestData.
I also wonder whether this data manipulation task belongs in a route?
Should I somehow do this in the serliazer adapter, creating a new structure as say 'categoryWeights' so I can then do:
model: function() {
return this.store.get('categoryWeights');
},
EDIT
I have managed to do this in the route, but it just gives me an array of objects. I need a single object containing 2 properties and an embedded array of objects.
model() {
return this.store.findAll('category')
.then(categories => categories.map(category => {
let data = {
y: category.get('totalGrams'),
name: category.get('name')
};
return data;
}))
},
This should probably go into a computed property:
dataForSubModel: Ember.computed('model.#each.totalGrams', 'model.#each.name', {
get() {
return [{name: 'gear', colorByPoint: true, this.get('model').map(m => ({y:m.get('totalGrams'), name:m.get('name')}))}
}
}),
The serializer is the wrong place, because its not that you need to convert it between the server and your app, but between your app and a strange component.
Actually the best thing would be to refactor the component.
Ok I got this to work in the route.
model() {
return this.store.findAll('category')
.then( function(categories) {
let data = [];
data = categories.map(category => {
return {
y: category.get('totalGrams'),
name: category.get('name')
}
});
return [{name: 'gear', colorByPoint: true, data}];
})
},
I still have the feeling this should be done in the adapter or serializer. Would be happy to see answers that show how to do that.

How can I use AJAX with web methods to send JSON objects to a jQuery DataTable using asp.net?

So I have the jQuery datatable using AJAX to call for the JSON in this format.
$(document).ready(function () {
$('#test').DataTable({
ajax:{
url:"players.json",
dataSrc:""
},
columns: [
{data: "id"},
{ data: "player" },
{ data: "points" },
{ data: "steals" },
{ data: "blocks" },
{ data: "assists" },
{ data: "MPG" },
{ data: "shot %" },
{ data: "3 %" }
]
});
});
My aspx.cs file has a method to create the JSON file which works.
[System.Web.Services.WebMethod]
public static void loadTable()
{
NBAPlayerRepository players = new NBAPlayerRepository();
DataTable dt = players.GetAll();
var json = dt.ToJson();
System.IO.File.WriteAllText(#"C:\Users\wheres\Downloads\nbaStats\nbaStats\nbaStats\players.json", json);
}
And the JSON looks like this:
[{"id" : "67926aa7-46b7-4418-96db-fc7e5216aac4","playername" : "Wilson Heres","points" : "34534","steals" : "34","blocks" : "34","assists" : "343","mpg" : "343","shootingpercentage" : "33.3429985046387","threepointpercentage" : "33.3429985046387"}
,{"id" : "6dc42e0b-8750-463d-a9ef-5a025a27154b","playername" : "Wilson Heres","points" : "34534","steals" : "34","blocks" : "34","assists" : "343","mpg" : "343","shootingpercentage" : "33.3429985046387","threepointpercentage" : "343.334014892578"}
,{"id" : "f727130c-5b94-4730-a653-cfb603c73b8a","playername" : "Wilson Heres","points" : "34534","steals" : "34","blocks" : "34","assists" : "343","mpg" : "343","shootingpercentage" : "33.3429985046387","threepointpercentage" : "343.334014892578"}
]
But now I am getting this error "jquery.dataTables.min.js:48 Uncaught TypeError: Cannot read property 'length' of undefined"
Edit: This all works now. Just had to add dataSrc:""
Cleaned-up version of your DataTables initialization
$(document).ready(function () {
$('#test').DataTable({
ajax: {
url: "players.aspx/loadTable"
},
columns: [
{ data: "id" },
{ data: "player" },
{ data: "points" },
{ data: "steals" },
{ data: "blocks" },
{ data: "assists" },
{ data: "MPG" },
{ data: "Shot %" },
{ data: "3 %" },
]
});
});
This may seem like a lot of stuff was removed from your code, so let me make some explanations/assumptions about what was changed.
Assumptions
First, an assumption: DataTables will always try to use a GET request, not a POST when first getting the data from the table, so make sure that your data processing code expects that.
I also am assuming that you have no strong desire to have your Ajax separate from your initialization and that was just how you decided to do it as a first attempt. If that is the case, let me know and I'll update the code to match that.
Explanation
Your formatting is incorrect in some areas and against DataTables standard in others, so this version should do most of what you were trying to do in a much simpler form. A lot of your Ajax options are unnecessary because they are already the default (JSON for the data type, for example), which is why they have been removed.
One nice thing about DataTables is that you can have the Ajax options in the initialization, which is what I have done here. You do lose the success and failure callbacks but I think that for debugging purposes they aren't really necessary and having any extra code increases the amount of stuff to debug (I don't even use those callbacks in most of my final code).
Most of the other changes were mainly incorrect nomenclature (e.g. data instead of title in the column definitions.
Disclaimer
While I would recommend these changes in general just to improve your code, I would make sure to take a look at the format of the JSON that is being sent to and from the server. If you don't know how to do that I'd recommend downloading Fiddler to 'listen in' on the JSON data being sent.
If your JSON is wrong, no amount of changes to the page are going to make the table appear.
Finally, make sure you have no JS errors on the page. Use your browser's developer console (F12) to check that.
If you do find any JS errors, post them in your question. I'd also recommend posting the JSON data being sent to the question as well so that we can ensure the format is correct.

VueJS - trouble understanding .$set and .$add

I am trying to build an array of objects in VueJS and I am running into some issues with .$set and .$add.
For example, I need the following structure when adding new items/objects:
{
"attendees": {
"a32iaaidASDI": {
"name": "Jane Doe",
"userToken": "a32iaaidASDI",
"agencies": [
{
"name": "Foo Co"
}
]
}
}
}
New objects are added in response to an AJAX call that returns JSON formatted the same as above. Here is my Vue instance:
var vm = new Vue({
el: '#trainingContainer',
data: {
attending: false,
attendees: {}
},
methods: {
setParticipantAttending: function(data)
{
if (data.attending)
{
this.attendees.$add(data.userToken, data);
} else {
this.attendees.$delete(data.userToken);
}
}
}
});
This only works if I start with attendees: {} in my data but when I try attendees.length after adding an attendee, I receive undefined. If I use attendees: [], the new object does not appear to be added. And lastly, if I use .$set(data.userToken, data) it does not add in the 'token':{data..} format required.
What could be the issue here? What is the correct way to use $.add when starting with an empty array of objects?
UPDATE
I found that it works if I set attendees: {} and then, when adding a new object,
if (data.userToken in this.attendees) {
this.attendees.$set(data.userToken, data);
} else {
this.attendees.$add(data.userToken, data);
}
Not sure if there is a better way to accomplish this.
If you set attendees to an empty object ({}) it will not have a length attribute. That attribute is on Arrays.
If you set attendees to an empty array ([]) then you need to use $set (or really, I think you want .push()) – $add is intended for use on objects not on arrays.
I'm not quite following your last question – could you add more context?
EDIT 2:
The answer below was for Vue 1.x. For Vue 2.x and greater use:
this.$set(this.attendees, data.userToken, data);
More information here: https://v2.vuejs.org/v2/api/#Vue-set
EDIT:
Responding to your update, you should be able to just use $set in all cases. I.e. just do this:
this.attendees.$set(data.userToken, data);
As of version 0.6.0, this seems to be the correct way:
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
http://vuejs.org/guide/reactivity.html#Change_Detection_Caveats

How to read kendo grid columns from a json file

I have a kendo grid which is reading data from a remote json file. I want that the grid columns should also be read from the same json file so that I dont have to change the client side code again and again. Whatever comes in the json file it should be capable enough to present the same data without any hard coding on client side. My json file looks like
{ "data":[
{"_type":"ProductDetails:#NWProducts","Discount":0,"OrderId":10248,"ProductId":11,"UnitPrice":14.0000,"quanity":12},{"_type":"ProductDetails:#NWProducts","Discount":0,"OrderId":10248,"ProductId":42,"UnitPrice":9.8000,"quanity":10},{"_type":"ProductDetails:#NWProducts","Discount":0,"OrderId":10248,"ProductId":72,"UnitPrice":34.8000,"quanity":5},{"_type":"ProductDetails:#NWProducts","Discount":0,"OrderId":10249,"ProductId":14,"UnitPrice":18.6000,"quanity":9}],
"columns":[
{"field":"_type","title":"Type"},{"field":"Discount","title":"Discount($)"},{"field":"OrderId","title":"Order ID"},{"field":"ProductId","title":"Product ID"},{"field":"UnitPrice","title":"Unit Price"},{"field":"quanity","title":"Quanity"}]
}
HTML code is as below
<div id="grid"></div>
JS code is below
$("#grid").kendoGrid({
title: { text: "Stats" },
sortable: false,
pageable: {
pageSizes: true,
buttonCount: 5
},
columnMenu: true,
dataSource: {
transport: {
read: {
url: "............/demo.json",
dataType: "json"
}
},
schema: {
data: "data"
}
},
columns: {
//What should be done here.
}
});
I tried the same transport read schema way to fetch the column data but it did not work. If I store the same columns json data in a variable and substitute that variable for columns then it works. Is there any way to store the columns json data as such in a variable from the json file. What is the best approach to achieve this behavior. Any help would be appreciated.
Thanks in Advance.

How to avoid "Unable to get property 'X' of undefined or null reference" when creating $scope properties from JSON data

I want to populate some charting data from some JSON data pulled down using $http.get. However, the issue I have is the $scope property I am binding to doesn't exist until the JSON is returned, so the page is throwing an error when it loads.
How do I avoid the error? It feels like I have a chicken and egg scenario.
Example:
$scope.Model.Charts.Electricity = {
series: [
name: "2014 Target",
data: $scope.Model.Data.Json.Charts.Electricity.CurrentYearTarget
]
};
The Electricity.CurrentYearTarget property is the one that doesn't exist until the promise is completed:
promise.then(
function(payload) {
$scope.Model.Data.Json.Charts = payload.data;
});
The JSON is what then defines the objects that sit under .Charts. Example:
{"Electricity":
{"CurrentYearTarget":
[10000.0,
// snip
10000.0]
}
}
OK, so what can I do to work with this? I suppose I could wrap all of my properties like $scope.Model.Charts.Electricity and so forth into a simple JavaScript if statement, but that doesn't feel right.
I suggest you consider simplifying your approach somewhat, as $scope.Model.Data.Json.Charts.Electricity.CurrentYearTarget is somewhat verbose, and Model, Data, Json all mean the same thing really, you can probably cut some of these out.
However, this is beside the point, you can still acheive what you want to, just populate the data when the request has returned:
$scope.Model = { Data: { Json: { Charts: {} } } }
promise.then(
function(payload) {
$scope.Model.Data.Json.Charts = payload.data;
$scope.Model.Charts.Electricity = {
series: {
name: "2014 Target",
data: $scope.Model.Data.Json.Charts.Electricity.CurrentYearTarget
}
};
});