What data format does KendoTreeView require in second hierarchy? - javascript

I am using KendoUI Web and have set up a TreeView with two levels of hierarchy which are loading data from a CRUD service using the transport option of the DataSource:
var Level2 = kendo.data.Node.define({
id: "Level2_Id",
hasChildren: false,
fields: {
"Level2_Id": { type: "number" },
"Name": { type: "string" },
"Level1_Id": { type: "number" }
}
});
var level2DataSource = {
transport: {
read: {
url: "/service/level2",
type: "get",
dataType: "json"
},
create: {
url: "/service/level2",
type: "post",
dataType: "json"
}
},
schema: {
model: Level2
}
};
var Level1 = kendo.data.Node.define({
id: "Level1_Id",
hasChildren: true,
fields: {
"Level1_Id": { type: "number" },
"Name": { type: "string" },
},
children: level2DataSource,
});
var level1DataSource = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: "/service/level1",
type: "get",
dataType: "json"
},
create: {
url: "/service/level1",
type: "post",
dataType: "json"
}
},
schema: {
model: Level1
}
});
var myTreeview = $("#treeview").kendoTreeView({
dataSource: leaguesDataSource,
template: kendo.template($("#treeview-template").html())
});
Reading the data works fine on both levels.
Creating new items is done by calling .append() on the TreeView and then .sync() on the level 1 DataSource.
This results in a POST request to my service which returns the new JSON object. The tree view updates just fine.
However, when doing the same thing on level 2, the treeview will remove all items and only show level 2 children of the level 1 item that the new item was appended to.
The GET requests return a JSON array of level 1 or level 2 items like
result of /service/level1
[
{Level1_Id:1,Name:"Item 1"},
{Level1_Id:2,Name:"Item 2"},
{Level1_Id:3,Name:"Item 3"},
]
result of /service/level2
[
{Level2_Id:1,Name:"Item 2.1",Level1_Id:2},
{Level2_Id:2,Name:"Item 2.2",Level1_Id:2}
]
The POST requests return a single object of the same format.
What format do I need to return in my service so the treeview will update correctly on level 2 after appending an item?
Expected result:
- Item 1
- Item 2 (append here)
- Item 2.1
- Item 2.2 (new item)
- Item 3
Actual result after POST request:
- Item 2.1
- Item 2.2 (new item)

your syntax it not right. your must write
schema:{model:{id: "IdLevel", children: "items", hasChildren: "hasChildren"}}
with hierarchical data.
For example you must have your data like this :
[
{ categoryName: "SciFi", items: [
{ movieName: "Inception", rating: 8.8 },
{ movieName: "The Matrix", rating: 8.7 }
] },
{ categoryName: "Drama", hasAssignedMovies: true }]

Related

How to iterate from JSON datatype in jquery

i have a form on select from dropdown the request goes to the controller and returns the following in
JSON formate
[{id: 2, slug: "manager", name: "Assistant Manager", created_at: "2019-12-10 09:20:45",…}]
0: {id: 2, slug: "manager", name: "Assistant Manager", created_at: "2019-12-10 09:20:45",…}
created_at: "2019-12-10 09:20:45"
id: 2
name: "Assistant Manager"
permissions: [{id: 2, slug: "edit-users", name: "Edit Users", created_at: "2019-12-10 09:21:01",…}]
0: {id: 2, slug: "edit-users", name: "Edit Users", created_at: "2019-12-10 09:21:01",…}
slug: "manager"
updated_at: "2019-12-10 09:20:45"
now i want to iterate from permissions and show name in another drop-down with multiple selection buit i don't know how to iterate from this JSON i tried the following script but doesn't work
$(document).ready(function () {
$("#roles").on('change', function () {
var query = $(this).val();
// alert(query);
if (query != '') {
$.ajax({
url: "{{route('get-roles-ajax-call')}}",
method: "POST",
dataType: 'JSON',
data: {"_token": "{{ csrf_token() }}", query: query},
success: function (data) {
var values = $.parseJSON(data)
$(values).each(function(i,val){
$.each(val,function(key,val)
{
console.log(key + " : " + val);
});
});
}
});
}
return false;
});
});
When setting this line dataType: 'JSON' you are already telling the $.ajax function to return JSON.
Quoted from jQuery documentation of $.ajax
"json": Evaluates the response as JSON and returns a JavaScript object.
So there is no need to parse the data once you've received it. Is is already JSON.
Now loop through every object in the data to search for the permissions property. If the object has the permissions property and the value of that is an array that is not empty then loop over each object in the permissions array and look for the the name property on each permission.
$.each(data, function(i, entry) {
var permissions = entry.hasOwnProperty('permissions');
if (permissions && permissions.length) {
$.each(entry.permissions, function(j, permission) {
console.log(permission.name);
});
}
});
Though I would suggest that you modify the, or create a new, server response so that all this filter work is done server side and you only have to call the server to get the data you need.

React - Loop through multiple nested arrays json object response then update State

I have some data that has the following shape. The schedule data also has other identifying information attached to it, being schedules.included which is an array of arrays. I want to loop through each included array and find it by type element. I'm not entirely sure how to get each included[] by type then update state with data from each array, respectively. Is forEach the correct approach?
const schedules = {
data: [
{
id: "2147483610",
type: "Schedule"
}
],
included: [
{
id: "21468486",
type: "Query",
name: "Query1"
},
{
id: "43573457345",
type: "DataSource",
name: "DataSource1"
}
]
};
I then want to update state with whatever data I need.
getData = () => {
axios({
method: "get",
url: `/endpoint/with/this/data`
})
.then(response => {
console.log(response);
var obj = schedules.included[i].type;
obj.forEach(function(type) {
alert(type.name);
});
this.setState({
schedules: schedules.data,
//update with name from type Query
});
})
.catch(error => console.log(error.response));
};
If you want to find the name of the element from the included array which has type = Query, and there is only one such element:
var query = schedules.included.find(el => el.type == "Query");
console.log(query.name); // output Query1
If there is more than one query element you could use filter to get all query elements, then loop thru them doing stuff with each one.
var queries = schedules.included.filter(el => el.type == "Query");
queries.forEach(q => console.log(q.name));
If there is only one element with the type you are looking for then you can use find or if there is more use filter.
const schedules = {
data: [
{
id: "2147483610",
type: "Schedule"
}
],
included: [
{
id: "21468486",
type: "Query",
name: "Query1"
},
{
id: "43573457345",
type: "DataSource",
name: "DataSource1"
}
]
};
const typeMatched = schedules.included.find( included => included.type === "Query");
console.log(': ', typeMatched);
const schedulesObj = {
data: [
{
id: "2147483610",
type: "Schedule"
}
],
included: [
{
id: "21468486",
type: "Query",
name: "Query1"
},
{
id: "43573457345",
type: "DataSource",
name: "DataSource1"
},
{
id: "21468482",
type: "Query",
name: "Query2"
},
{
id: "21468484",
type: "Query",
name: "Query3"
},
]
};
const typeMatchedArray = schedulesObj.included.filter( included => included.type === "Query");
console.log('Query Type List: ', typeMatchedArray)

JS: change params format from hash to array

I have this piece of JS, where I have create action with Ajax:
$(document).ready(function() {
editor = new $.fn.dataTable.Editor( {
table: "#user_groups_table",
template: '#user_groups_form',
display: "details",
idSrc: "id",
ajax: {
create: {
type: 'POST',
url: '/strongbolt/user_groups',
}
},
fields: [ {
name: "name"
}, {
name: "description"
}, {
type: "checkbox",
name: "users[].id",
optionsPair: {
label: 'name',
value: 'id'
}
}, {
type: "checkbox",
name: "roles[].id",
optionsPair: {
label: 'name',
value: 'id'
}
}
]
} );
editor.on( 'preSubmit', function ( e, data, action ) {
if ( action === 'create' ) {
data.strongbolt_user_group = {
"name": data.data[0].name,
"description": data.data[0].description,
"user_ids": data.data[0].users,
"role_ids": data.data[0].roles
};
delete data.data;
}
} );
The last section which starts with editor.on( 'preSubmit', function ( e, data, action ) { basically modifies data before they are passed to server.
At the moment I get my params in terminal like this:
{
"strongbolt_user_group"=>{
"name"=>"Some test group",
"description"=>"Some test description",
"user_ids"=>{"0"=>{"id"=>"3"}, "1"=>{"id"=>"2"}, "2"=>{"id"=>"5"}},
"role_ids"=>{"0"=>{"id"=>"1"}, "1"=>{"id"=>"2"}}
}
}
however I need it to be like this:
{
"strongbolt_user_group"=>{
"name"=>"Some test group",
"description"=>"Some test description",
"user_ids"=>["3", "2", "5"],
"role_ids"=>["1", "2"]
}
}
Basically I need user_ids and role_ids to be array.
How do I modify this in my JS, please? Thank you!
You have to map the array (or array-like object) of objects to an array of their ids:
"user_ids": Array.prototype.map.call(data.data[0].users, function(o) { return o.id; }),
If you are certain that data.data[0].users is an array, then just use map without call like:
"user_ids": data.data[0].users.map(function(o) { return o.id; }),
or even shorter in ES 6's arrow functions:
"user_ids": data.data[0].users.map(o => o.id),
Note: same applies for role_ids.

How to map model to table when the structure is array based?

I have my data as following:
{
meta: {
format: "csv",
info: "desc",
columns: [
{
id: "Name",
type: "Text",
length: 32
},
{
id: "Text",
type: "Text",
length: 128
}]
},
rows: [
["John","xxxx"],
["Alpha","yyyy"],
["Beta","wwww"],
["Gamma","zzzz"]]
}
Now, I am struggling to map the records to a Table control as Columns and Rows. Column seems straight forward, straight map, but the rows since lacks a mapping to column I wonder what could be the simplest way.
Approach Steps:
Make a keys[] from column.id of each columns record.
Traverse the rows[]
Each loop, while keys.length create an object as {keys[j]:row[k]}
Push to an array
Recreate the original JSON but replace Rows arrays with Objects
I am really struggling to translate this into code specially at the rows[] parsing and creating Objects. Is there, I am sure there must be, an efficient way to achieve this.
Here is what you could do. using Array.map and forEach.
var input = {
meta: {
format: "csv",
info: "desc",
columns: [{
id: "Name",
type: "Text",
length: 32
}, {
id: "Text",
type: "Text",
length: 128
}]
},
rows: [
["John", "xxxx"],
["Alpha", "yyyy"],
["Beta", "wwww"],
["Gamma", "zzzz"]
]
};
var columns = input.meta.columns.map((column) => {
return column.id
});
var rows = input.rows.map((row) => {
var obj = {};
row.forEach((column, idx) => {
obj[columns[idx]] = column;
});
return obj;
});
input.rows = rows;
console.log(input);

Loading data from ajax breaks functionality

I am trying to create a real-time filter on a table using knockoutjs.
I have managed to get everything to work when I statically create the observable array like this:
$(function() {
var assets = [
{id: "1", poster: "Pic010.jpg", name: "Asset1", category: "category1", type: "Movie", popup: "1" },
{id: "2", poster: "Pic06.jpg", name: "Asset2", category: "category2", type: "Movie", popup: "2" },
{id: "3", poster: "Pic04.jpg", name: "Asset3", category: "category1", type: "Pop-up", popup: "3" },
{id: "4", poster: "Pic07.jpg", name: "Asset4", category: "category2", type: "Pop-up", popup: "4" },
{id: "5", poster: "Pic011.jpg", name: "Asset1", category: "category3", type: "Promo", popup: "5" }
];
var viewModel = {
assets: ko.observableArray(assets),
query: ko.observable(''),
search: function(value) {
viewModel.assets.removeAll();
for(var x in assets) {
if(assets[x].name.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
viewModel.assets.push(assets[x]);
}
}
}
};
viewModel.query.subscribe(viewModel.search);
ko.applyBindings(viewModel);
});
JSFiddle of working code: http://jsfiddle.net/7ZLdk/1/
Now when I try to load the observable array data via ajax like this:
var assets = [];
$.ajax({
url: '/Assets/getJson/',
type: "GET",
dataType: 'json',
success: function (data) {
console.log(data);
viewModel.assets(data);
}
});
the data is displayed correctly in the table when the page is loaded, but when I start typing in the search input, all the data disappears.
I would appreciate it if someone could explain what I am doing incorrectly in the AJAX load? TIA
You are better off creating a ViewModel function, so the viewmodel only accesses data within itself:
$(function() {
$.ajax({
url: '/Assets/getJson/',
type: "GET",
dataType: 'json',
contentType: "application/json",
success: function (data) {
console.log(data);
var viewModel = new ViewModel(data);
ko.applyBindings(viewModel);
}
});
});
function ViewModel(assets) {
var self = this;
self.assets = ko.observableArray(assets);
self.allAssets = assets;
self.query = ko.observable('');
self.search = function(value) {
self.assets.removeAll();
for(var x in self.allAssets) {
if(self.allAssets[x].name.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
self.assets.push(self.allAssets[x]);
}
}
};
self.query.subscribe(self.search);
}
I have resolved the problem.
I was not populating the assets array. This is the updated ajax call:
$.ajax({
url: '/Assets/getJson/',
type: "GET",
dataType: 'json',
contentType: "application/json",
success: function (data) {
console.log(data);
viewModel.assets(data);
assets = data; // THIS WAS MISSING
}
});

Categories

Resources