Related
I'm learning Javascript and getting started with React. I'm attempting to build a Materials-UI's DataGrid and need to structure my data accordingly. I have the following piece of code that prepares the Rows and Columns for DataGrid but I feel it may be "slow" and wondering if I can get the community's input on how it can be written more efficiently. Any ideas/solutions would be appreciated. Thanks.
input:
const values = [
{
"documentId": "12345",
"documentDirectory": "Canadian PnC",
"properties": [
{
"name": "HoldingNumber",
"type": "STRING",
"value": "88888",
},
{
"name": "DocumentType",
"type": "STRING",
"value": "TAC",
},
{
"name": "DocumentName",
"type": "STRING",
"value": "Income",
},
]
},
{
"documentId": "54321",
"documentDirectory": "Wealth",
"properties": [
{
"name": "HoldingNumber",
"type": "STRING",
"value": "99999",
},
{
"name": "DocumentType",
"type": "STRING",
"value": "TAC",
},
{
"name": "DocumentName",
"type": "STRING",
"value": "Appraisal",
},
]
}
];
output:
//console.log(cols);
[
{
field: "DocumentDirectory", headerName: "DocumentDirectory", width: 200
},
{
field: "DocumentId", headerName: "DocumentId", width: 200
},
{
field: "HoldingNumber", headerName: "HoldingNumber", width: 200
},
{
field: "DocumentType", headerName: "DocumentType", width: 200
},
{
field: "DocumentName", headerName: "DocumentName", width: 200
}
]
//console.log(rows);
[
{
id: 0,
DocumentDirectory: "Canadian PnC",
DocumentId: "12345",
HoldingNumber: "88888",
DocumentType: "TAC",
DocumentName: "Income"},
{
id: 1,
DocumentDirectory: "Wealth",
DocumentId: "54321",
HoldingNumber: "99999",
DocumentType: "TAC",
DocumentName: "Appraisal"
}
]
I'm currently achieving it the using the following:
const docDirectory = values.map(result => result.documentDirectory);
const docId = values.map(result => result.documentId);
const docProperties = values.map(result => result.properties);
let cols= [];
let rows= [];
for (let i = 0; i < docProperties.length; i++) {
const p = docProperties[i];
let o = {};
o["id"] = i;
o["DocumentDirectory"] = docDirectory[i];
o["DocumentId"] = docId[i];
if (i === 0) {
cols.push({ field: "DocumentDirectory", headerName: "DocumentDirectory", width: 200 });
cols.push({ field: "DocumentId", headerName: "DocumentId", width: 200 });
}
for (let j = 0; j < p.length; j++) {
let nam = p[j].name;
let val = p[j].value;
o[nam.replace(/\s+/, "")] = val;
if (i === 0) {
cols.push({ field: nam.replace(/\s+/, ""), headerName: nam, width: 200 });
}
}
rows.push(o);
}
console.log(cols);
console.log(rows);
const values = [
{
documentId: '12345',
documentDirectory: 'Canadian PnC',
properties: [
{
name: 'HoldingNumber',
type: 'STRING',
value: '88888'
},
{
name: 'DocumentType',
type: 'STRING',
value: 'TAC'
},
{
name: 'DocumentName',
type: 'STRING',
value: 'Income'
}
]
},
{
documentId: '54321',
documentDirectory: 'Wealth',
properties: [
{
name: 'HoldingNumber',
type: 'STRING',
value: '99999'
},
{
name: 'DocumentType',
type: 'STRING',
value: 'TAC'
},
{
name: 'DocumentName',
type: 'STRING',
value: 'Appraisal'
}
]
}
];
const cols = [
{
field: 'DocumentDirectory',
headerName: 'DocumentDirectory',
width: 200
},
{
field: 'DocumentId',
headerName: 'DocumentId',
width: 200
},
...values[0].properties.map(p => ({
field: p.name,
headerName: p.name,
width: 200
}))
];
const rows = values.map((value, index) => {
return {
id: index,
DocumentDirectory: value.documentDirectory,
DocumentId: value.documentId,
...value.properties.reduce(
(val, cur) => ({
...val,
[cur.name]: cur.value
}),
{}
)
};
});
console.log(cols);
console.log(rows);
const values = [{
"documentId": "12345",
"documentDirectory": "Canadian PnC",
"properties": [{
"name": "HoldingNumber",
"type": "STRING",
"value": "88888",
},
{
"name": "DocumentType",
"type": "STRING",
"value": "TAC",
},
{
"name": "DocumentName",
"type": "STRING",
"value": "Income",
},
]
},
{
"documentId": "54321",
"documentDirectory": "Wealth",
"properties": [{
"name": "HoldingNumber",
"type": "STRING",
"value": "99999",
},
{
"name": "DocumentType",
"type": "STRING",
"value": "TAC",
},
{
"name": "DocumentName",
"type": "STRING",
"value": "Appraisal",
},
]
}
];
const allCols = values.reduce((prev, { documentDirectory, properties }) => ([
...prev,
{ field: documentDirectory, headerName: documentDirectory, width: 200 },
...properties.map(({name: field, name: headerName}) => ({field, headerName, width: 200}))
]), [])
const cols = [...new Set(allCols.map(JSON.stringify))].map(JSON.parse)
console.log(cols)
const rows = values.reduce((prev, next) => ([
...prev,
...next.properties.map(property => ({
DocumentDirectory: next.DocumentDirectory,
DocumentId: next.DocumentId,
...property
}))
]), []).map((row, key) => ({id: key, ...row}))
console.log(rows)
I have a huge object, with almost 50k lines.
I need to add in each object new key with the current path of the node
Example:
let obj = {
"title": "RESSONÂNCIA MAGNÉTICA DA COLUNA LOMBAR",
"data": [{
"title": "Método:",
"data": [{
"title": "Procedimento 1",
"data": [{
"title": "CONTRASTE"
},
{
"title": "CONTRASTE 2"
}
]
},
{
"title": "Procedimento 2",
"data": [{
"title": "CONTRASTE 3"
},
{
"title": "CONTRASTE 4"
}
]
}
]
}]
}
And I need to change my object to return this:
obj = {
"path": "$",
"title": "RESSONÂNCIA MAGNÉTICA DA COLUNA LOMBAR",
"data": [{
"path": "$.data.0",
"title": "Método:",
"data": [{
"path": "$.data.0.data.0",
"title": "Procedimento 1",
"data": [{
"path": "$.data.0.data.0.data.0",
"title": "CONTRASTE"
},
{
"path": "$.data.0.data.0.data.1",
"title": "CONTRASTE 2"
}
]
},
{
"path": "$.data.0.data.1",
"title": "Procedimento 2",
"data": [{
"path": "$.data.0.data.1.data.0",
"title": "CONTRASTE 3"
},
{
"path": "$.data.0.data.1.data.1",
"title": "CONTRASTE 4"
}
]
}
]
}]
}
If you notice, i added the key path inside each object for key data, with the current path of the node. This is what I need.
All my object are much bigger then this example, with much more nested objects
Performant version in case you have to deal with large files
const data = {
"title": "RESSONÂNCIA MAGNÉTICA DA COLUNA LOMBAR",
"data": [{
"title": "Método:",
"data": [{
"title": "Procedimento 1",
"data": [{
"title": "CONTRASTE"
},
{
"title": "CONTRASTE 2"
}
]
},
{
"title": "Procedimento 2",
"data": [{
"title": "CONTRASTE 3"
},
{
"title": "CONTRASTE 4"
}
]
}
]
}]
}
function PathUpdate(data, path) {
data.path = path;
const nd = data.data;
if (nd == null) return;
for (let i = 0; i < nd.length; i++) {
PathUpdate(nd[i], `${path}.data.${i}`);
}
}
console.log("before", { data });
PathUpdate(data, "$");
console.log("after", { data });
const data = {
title: "RESSONÂNCIA MAGNÉTICA DA COLUNA LOMBAR",
type: "template",
data: [
{
title: "Método:",
type: "top-level-component",
data: [
{
title: "Procedimento",
type: "navigation",
normal: "CONTRASTE",
checked: true,
data: [
{
type: "single-selection",
title: "CONTRASTE",
},
{
type: "single-selection",
title: "CONTRASTE 2",
},
],
},
{
title: "Procedimento 2",
type: "navigation",
normal: "CONTRASTE",
checked: false,
data: [
{
type: "single-selection",
title: "CONTRASTE 3",
},
{
type: "single-selection",
title: "CONTRASTE 4",
},
],
},
],
},
],
};
function addPathToObj(obj, path) {
obj.path = path;
for (const [key, value] of Object.entries(obj)) {
if (Array.isArray(value)) {
value.forEach((item, index) => {
addPathToObj(item, `${path}.data.${index}`);
});
}
}
}
addPathToObj(data, "$");
console.log(data);
I have the following Json coming from an api, which I want to present in a V-DATA-TABLE:
[
{
"id": 1,
"firstName": "Ana",
"lastName": "Lucia",
"phone": "(11)99989-8989",
"mobilePhone": "(11)99989-8989",
"email": "aninha#gmail.com",
"gender": {
"name": "feminino"
},
"status": {
"name": "inativo"
},
"services": [
{
"name": "progressiva"
},
{
"name": "Manicure"
}
]
},
{
"id": 2,
"firstName": "Maria",
"lastName": "Luiza",
"phone": "(12)32333-3333",
"mobilePhone": "(43)45555-5555",
"email": "marialu#gmail.com",
"gender": {
"name": "feminino"
},
"status": {
"name": "pendente"
},
"services": [
{
"name": "progressiva"
}
]
},
{
"id": 3,
"firstName": "Mario",
"lastName": "Braz",
"phone": "(11)23232-3222",
"mobilePhone": "(11)23232-3222",
"email": "mariobraz#gmail.com",
"gender": {
"name": "masculino"
},
"status": {
"name": "ativo"
},
"services": [
{
"name": "progressiva"
}
]
}
]
However in the Data table the field that the Services would come from, is empty as shown in the image:
Here is the code of my .Vue data:
data: () => ({
dialog: false,
pageTitle: 'Employees',
headers: [
{
text: 'First Name',
align: 'start',
sortable: false,
value: 'firstName',
},
{ text: 'Last Name', value: 'lastName' },
{ text: 'Email', value: 'email' },
{ text: 'Phone', value: 'phone' },
{ text: 'Mobile Phone', value: 'mobilePhone' },
{ text: 'Gender', value: 'gender.name' },
{ text: 'Status', value: 'status.name' },
{ text: 'Services', value: 'services.name' },
{ text: 'Actions', value: 'action', sortable: false },
],
search: '',
employees: [],
genders: [],
status: [],
services:[],
editedIndex: -1,
editedItem: {},
defaultItem: {},
}),
I noticed that when I change this code snippet and leave only 'services':
{ text: 'Services', value: 'services' },
exactly the number of objects that are the services appears but not the names:
Here is the method I used to pull the main object that is the 'employees' and all their relationships:
methods: {
initialize () {
axios.get('http://192.168.26.130:3000/employees/').then(response => {
this.employees = response.data
console.log(response)
}).catch(e => {
console.log(e)
});
axios.get('http://192.168.26.130:3000/genders/').then(response => {
this.genders = response.data
console.log(response)
}).catch(e => {
console.log(e)
});
axios.get('http://192.168.26.130:3000/employee-status').then(response => {
this.status = response.data
console.log(response)
}).catch(e => {
console.log(e)
});
axios.get('http://192.168.26.130:3000/services').then(response => {
this.services = response.data
console.log(response)
}).catch(e => {
console.log(e)
});
},
{ text: 'Services', value: 'services.map(s => s.name).join(", ") }
will display the services names, separated by ', ' (comma + space).
Alternative method, using template:
<template v-slot:item.services="{ item }">
{{ item.services.map(s => s.name).join(', ') }}
</template>
services prop is an array:
"services": [
{
"name": "progressiva"
},
{
"name": "Manicure"
}
]
If you want to display the first value, write:
{ text: 'Services', value: 'services[0].name' },
Otherwhise, you need to transform the array.
I am working with kendo UI and angular grid application. My grid is populated from JSON data (separate file) and I am use angular service:
My JSON data:
[
{ "Id": 1, "AccountNo": "10236", "PostingDate": "20.01.2015", "MaturityDate": "24.01.2015", "Description": "description1", "DocumentTypeId": 1 },
{ "Id": 2, "AccountNo": "10648", "PostingDate": "26.01.2015", "MaturityDate": "28.01.2015", "Description": "description2", "DocumentTypeId": 2 },
{ "Id": 3, "AccountNo": "10700", "PostingDate": "22.01.2015", "MaturityDate": "25.01.2015", "Description": "description3", "DocumentTypeId": 3 },
{ "Id": 4, "AccountNo": "10810", "PostingDate": "24.01.2015", "MaturityDate": "27.01.2015", "Description": "description4", "DocumentTypeId": 2 },
{ "Id": 5, "AccountNo": "10101", "PostingDate": "29.01.2015", "MaturityDate": "30.01.2015", "Description": "description5", "DocumentTypeId": 4 },
{ "Id": 6, "AccountNo": "10364", "PostingDate": "25.01.2015", "MaturityDate": "31.01.2015", "Description": "description6", "DocumentTypeId": 6 }
]
My Angular service:
angular.module("app").factory('myService', function ($http) {
return {
getAll: function (onSuccess, onError) {
return $http.get('/Scripts/app/data/json/master/masterGridData.js').success(function (data, status, headers, config) {
onSuccess(data);
}).error(function (data, status, headers, config) {
onError(data);
});
},
getDocumentTypes: function (onSuccess, onError) {
return $http.get('/Scripts/app/data/json/documentType.js').success(function (data, status, headers, config) {
onSuccess(data);
}).error(function (data, status, headers, config) {
onError(data);
});
}
}
});
This is my controller:
var app = angular.module("app", ["kendo.directives"]).controller("myController", function ($scope, myService) {
$scope.tabStrip = null;
$scope.$watch('tabStrip', function () {
$scope.tabStrip.select(0);
});
$scope.masterDataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
url = "/Scripts/app/data/json/master/masterGridData.js",
myService.getAll(function (data) {
options.success(data);
}).error(function (data) {
options.error(data);
})
}
},
schema: {
model: {
id: "Id",
fields: {
Id: { type: "number" },
AccountNo: { type: "string" },
PostingDate: { type: "string" },
MaturityDate: { type: "string" },
Description: { type: "string" },
DocumentTypeId: { type: "number" }
}
}
},
pageSize: 16
});
$scope.gridMaster = {
columns: [
{ field: "Id", hidden: true },
{ field: "AccountNo", title: "Account No", width: "77px", template: '<div style="text-align:left;">#= kendo.toString(AccountNo) #</div>' },
{ field: "PostingDate", title: "Posting Date", width: "70px" },
{ field: "MaturityDate", title: "Maturity Date" width: "70px" },
{ field: "Description", title: "Description", width: "170px" },
{ field: "DocumentTypeId", hidden: true }
],
dataSource: $scope.masterDataSource,
selectable: true,
filterable: true,
scrollable: true,
pageable: {
pageSize: 16,
//refresh: true,
pageSizes: ["50", "100", "200", "All"]
},
toolbar: [{
name: "create"
}],
change: function () {
var dataItem = this.dataItem(this.select());
$scope.isRowSelected = true;
$scope.id = dataItem.Id;
$scope.accountNumber = dataItem.AccountNo;
$scope.postingDate = dataItem.PostingDate;
$scope.description = dataItem.Description;
$scope.maturityDate = dataItem.MaturityDate;
$scope.documentTypeId = dataItem.DocumentTypeId;
}
};
$scope.documentType = {
dataSource: {
transport: {
read: function (options) {
url = "/Scripts/app/data/json/documentType.js",
myService.getDocumentTypes(function (data) {
options.success(data);
}).error(function (data) {
options.error(data);
});
}
},
schema: {
model: {
id: "Id",
fields: {
Id: { type: "number" },
Name: { type: "string" }
}
}
}
},
dataTextField: "Name",
dataValueField: "Id"
}
});
This is my JSON which contain data for documentType:
[
{ "Id": 1, "Name": "Document 1" },
{ "Id": 2, "Name": "Document 2" },
{ "Id": 3, "Name": "Document 3" },
{ "Id": 4, "Name": "Document 4" },
{ "Id": 5, "Name": "Document 5" },
{ "Id": 6, "Name": "Document 6" }
]
And this is my HTML:
<html>
<head>
<!-- css and javaScript files -->
</head>
<body ng-app="app" ng-controller="myController">
<div class="divH3Style">
<h3 class="h3LabelForm">Grid Master</h3>
</div>
<div id="tabstrip" class="k-tabstrip-wrapper" data-kendo-tab-strip="tabStrip">
<ul>
<li>Overview</li>
<li>Update</li>
</ul>
<div id="tabstrip-1">
<div id="gridMaster" kendo-grid k-options="gridMaster" k-data-source="masterDataSource">
</div>
</div>
<div id="tabstrip-2" style="overflow: hidden">
<div id="tabStrip2Half1">
<div class="divHeightStyle">
<label for="accountNumber" class="labelTextSize">Account Number:</label>
<input id="accountNumber" type="number" class="k-textboxField" name="accountNumber" ng-model="accountNumber" placeholder="Account Number" />
</div>
<div class="datepickerStyle">
<label for="postingDate" class="labelTextSize">Posting Date:</label>
<input id="postingDate" class="k-datetimepickerMaster" name="postingDate" ng-model="postingDate" />
</div>
<div class="divHeightStyle">
<label for="desccription" class="labelTextSize">Description:</label>
<input id="desccription" type="text" class="k-textboxField" name="description" placeholder="Description" ng-model="description" />
</div>
<div class="datepickerStyle">
<label for="maturityDate" class="labelTextSize">Maturity Date:</label>
<input id="maturityDate" class="k-datetimepickerMaster" name="maturityDate" ng-model="maturityDate" />
</div>
</div>
<div id="tabStrip2Half2">
<div class="divHeightStyle">
<label for="documentType" class="labelTextSize">Document Type:</label>
<select kendo-drop-down-list
class="k-dropdownField" k-options="documentType"
ng-model="documentTypeId" ng-bind="documentTypeId"></select>
</div>
<div>
<button type="button" id="saveDataMasterGrid" class="k-button buttonSaveCancel" onclick="saveDataMasterGrid()">Save</button>
<button type="button" id="cancelDataMasterGrid" class="k-button buttonSaveCancel" onclick="cancelButtonMasterGrid()">Cancel</button>
</div>
</div>
</div>
</div>
</body>
</html>
In HTML I have dropdownlist which contain data for documentType and my dropdownlist is populated with JSON data. But, problem is in binding. When I select some grid row dropdownlist always display first item. My grid datasource contain foreign key value (documentTypeId) and this value should match with Id value from documentType JSON file, ie $scope.documentType property dataValueFiled value. How can bind this dropdownlist? Pls help..
For solve that problem I use hardCoded variable:
$scope.documentTypeDS = [
{ "value": 1, "text": "doc 1" },
{ "value": 2, "text": "doc 2" },
{ "value": 3, "text": "doc 3" },
{ "value": 4, "text": "doc 4" },
{ "value": 5, "text": "doc 5" },
{ "value": 6, "text": "doc 6" }
];
And modified definition for my gridMaster. In gridMaster column property I insert:
{ field: "DocumentTypeId", hidden: true, values: $scope.documentTypeDS },
And, In HTML i modified code lines, from this:
<select kendo-drop-down-list
class="k-dropdownField" k-options="documentType"
ng-model="documentTypeId" ng-bind="documentTypeId"></select>
to this:
<input kendo-drop-down-list k-data-text-field="'text'" k-data-value-field="'value'" data-bind="value:documentTypeId"
class="k-dropdownField" k-data-source="documentType" ng-readonly="isReadonly" ng-model="documentTypeId" />
I suppose that there is a better solution of this, because I use hardCoded part of code for define $scope.documentTypeDS.
My code seems to only work when I have the alert("document loaded"). If I remove it, it does not work anymore. It supposed to setFocus on a particular field.
What could be the problem, is the alert("document loaded") giving the code time to execute before it fires off the rest?
<style type='text/css'>
/* T */
.comboItemContainer {
width: auto;
font-family: "Courier New", Courier, monospace;
}
.colOne {
border-right: 1px dashed gray;
float: left;
width: 100px;
}
.colTwo_NoDash {
float: left;
padding-left: 5px;
width: 350px;
}
</style>
<input type="text" name="test" id="test1" /><br /><br />
<div id="comboready"></div>
<div id="comboload"></div>
<div id="comboOrderTypes"></div>
<script>
$(document).ready(function () {
var data = [
{ "ID": 1, "Name": "John Smith", "Age": 45 },
{ "ID": 2, "Name": "Mary Johnson", "Age": 32 },
{ "ID": 3, "Name": "Bob Ferguson", "Age": 27 }
];
$("#comboready").igCombo({
dataSource: data, //JSON Array defined above
valueKey: "ID",
textKey: "Name",
itemTemplate: "<div class='comboItemContainer'><div class='colOne'>${ID}</div><div class='colTwo_NoDash'>${Name}</div></div>"
});
var data = [
{ "ID": 1, "Name": "John S", "Age": 45 },
{ "ID": 2, "Name": "Mary J", "Age": 32 },
{ "ID": 3, "Name": "Bob F", "Age": 27 }
];
$("#comboload").igCombo({
dataSource: data, //JSON Array defined above
valueKey: "ID",
textKey: "Name",
itemTemplate: "<div class='comboItemContainer'><div class='colOne'>${ID}</div><div class='colTwo_NoDash'>${Name}</div></div>"
});
// OrderType Combobox - On Page Load
$.get("../order/Json_OrderTypes", function (data) {
//Get
$("#comboOrderTypes").igCombo({
dataSource: data,
valueKey: "Order_Type",
textKey: "Order_Type",
width: "100px",
dropDownWidth: 500,
itemTemplate: "<div class='comboItemContainer'><div class='colOne'>${Order_Type}</div><div class='colTwo_NoDash'>${Description}</div></div>"
});
}, "json");
alert("document loaded");
});
$(window).load(function () {
$("#comboOrderTypes").igCombo("setFocus");
alert("window loaded");
});
</script>
The plugin is not initialized till the ajax request is completed... so do the setFocus call inside the ajax success callback.
$(document).ready(function () {
var data = [{
"ID": 1,
"Name": "John Smith",
"Age": 45
}, {
"ID": 2,
"Name": "Mary Johnson",
"Age": 32
}, {
"ID": 3,
"Name": "Bob Ferguson",
"Age": 27
}];
$("#comboready").igCombo({
dataSource: data, //JSON Array defined above
valueKey: "ID",
textKey: "Name",
itemTemplate: "<div class='comboItemContainer'><div class='colOne'>${ID}</div><div class='colTwo_NoDash'>${Name}</div></div>"
});
var data = [{
"ID": 1,
"Name": "John S",
"Age": 45
}, {
"ID": 2,
"Name": "Mary J",
"Age": 32
}, {
"ID": 3,
"Name": "Bob F",
"Age": 27
}];
$("#comboload").igCombo({
dataSource: data, //JSON Array defined above
valueKey: "ID",
textKey: "Name",
itemTemplate: "<div class='comboItemContainer'><div class='colOne'>${ID}</div><div class='colTwo_NoDash'>${Name}</div></div>"
});
// OrderType Combobox - On Page Load
$.get("../order/Json_OrderTypes", function (data) {
//Get
$("#comboOrderTypes").igCombo({
dataSource: data,
// selectedItems: [{ index: 5 }, { text: "S" }],
valueKey: "Order_Type",
textKey: "Order_Type",
width: "100px",
dropDownWidth: 500,
itemTemplate: "<div class='comboItemContainer'><div class='colOne'>${Order_Type}</div><div class='colTwo_NoDash'>${Description}</div></div>"
});
//the window load event is not really needed,use it only if you need it for some other purpose
$(window).load(function () {
$("#comboOrderTypes").igCombo("setFocus");
});
}, "json");
});
use as
setTimeout(function(){$("#comboOrderTypes").igCombo("setFocus");},0);