How do I set data for subgrid in expandable grid - javascript

My array is like this
$scope.ebObjArr = [{key: 'val', monthsArray: [{myDate:'',}]},{myDate:'',}]
monthArray is used for filling the sub-grid. I can't figure out how to set data for the sub-grid.
I tried this:
for (let i = 0; i < $scope.ebObjArr.length; i++) {
$scope.ebObjArr.monthsArray[i].subGridOptions = {
columnDefs: [{ name: "Month", field: "myDate" }, { name: "Cost", field: "totalCost" }, {name:"Units consumed", field : "unitsConsumed"}],
data: $scope.ebObjArr[i].monthsArray
}
}
I tried this too :
for (let i = 0; i < $scope.ebObjArr.length; i++) {
for (let j = 0; j < $scope.ebObjArr[i].monthsArray[j].length; j++) {
$scope.ebObjArr[i].monthsArray[j].subGridOptions = {
columnDefs: [{ name: "Month", field: "myDate" }, { name: "Cost", field: "totalCost" }, { name: "Units consumed", field: "unitsConsumed" }],
data: $scope.ebObjArr[i].monthsArray[j]
}
}
}
I'm using only the MainCtrl in this example: http://ui-grid.info/docs/#/tutorial/216_expandable_grid.

I'm sure there's a better way to do this but since no one answered I did this and it worked.
onRegisterApi: function (gridApi) {
$scope.grid1Api = gridApi;
$scope.grid1Api.expandable.on.rowExpandedStateChanged($scope, function (row) {
if (row.isExpanded) {
console.log(row.entity);
row.entity.subGridOptions = {
columnDefs: [{ name: "Month", field: "myDate" }, { name: "Cost", field: "totalCost" }, { name: "Units consumed", field: "unitsConsumed" }],
}
row.entity.subGridOptions.data = (function () {
var a;
a = $scope.ebObjArr.filter(function (val) {
if (val.ebName === row.entity.ebName && val.ebAddress === row.entity.ebAddress) {
// console.log(val.monthsArray);
return val.monthsArray
}
return false;
});
console.log(a);
console.log(a[0].monthsArray);
return a[0].monthsArray;
})();
console.log(row.entity.subGridOptions.data);
}
});
}

Related

Add/Update a property in a deeply nested array of objects based on a given key and value

I've got a deeply nested array that looks like this:
const elements = [
{
type: "section",
id: "basic-section",
title: "Basic information",
children: [
{
type: "select",
label: "Entity type",
id: "entity-type",
options: [
{ value: "person", label: "Person" },
{ value: "company", label: "Company" },
{ value: "organisation", label: "Organisation" },
],
},
{
type: "group",
conditions: [
{ type: "isEqual", variable: "entity-type", value: ["person"] },
],
children: [
{ type: "text", label: "First name", id: "entity.firstName" },
{ type: "text", label: "Last name", id: "entity.lastName" },
{ type: "number", label: "Age", id: "entity.age" },
{
type: "select",
label: "Gender",
id: "entity.gender",
defaultValue: "female",
options: [
{ value: "male", label: "Male" },
{ value: "female", label: "Female" },
],
},
],
},
{
type: "group",
conditions: [
{
type: "isEqual",
variable: "entity-type",
value: ["company", "organisation"],
},
],
children: [
{ type: "text", label: "Name", id: "entity.name" },
{ type: "text", label: "Address", id: "entity.address" },
],
},
],
},
];
I'm trying to add and update a property based on a given key and value.
Example 1: Add an option to the options list of entity-type
Example 2: Update the defaultValue of entity.gender to male
My current steps to accomplish this actions are:
1) Find the element based on the id key and id value
const element = findObject(elements, 'id', 'entity-type');
function findObject(object, key, value) {
if(object.hasOwnProperty(key) && object[key] === value) {
return object;
}
for(let i = 0; i < Object.keys(object).length; i++){
if(typeof object[Object.keys(object)[i]] == "object") {
const o = findObject(object[Object.keys(object)[i]], key, value);
if(o !== null) return o;
}
}
return null;
}
2) Create new option
const newOption = { value: 'government', label: 'Government' };
3) Add the new option to the found element
const updatedElement = Object.assign({}, element, { options: [...element.options, newOption] });
4) Replace the old element with the updatedElement
const newElementsList = // Stuck
5) Update the state with the updatedElementsList
setElementsList(newElementsList);
I don't see how I can replace the original element with the updated one based on the key and value.
Can someone help me out?
This is not recommended, but you can keep track of parent. Once you find the element, update the parent data with update value. But you loose immutability.
A better approach would be found and update the same time.
const elements = [{"type":"section","id":"basic-section","title":"Basic information","children":[{"type":"select","label":"Entity type","id":"entity-type","options":[{"value":"person","label":"Person"},{"value":"company","label":"Company"},{"value":"organisation","label":"Organisation"}]},{"type":"group","conditions":[{"type":"isEqual","variable":"entity-type","value":["person"]}],"children":[{"type":"text","label":"First name","id":"entity.firstName"},{"type":"text","label":"Last name","id":"entity.lastName"},{"type":"number","label":"Age","id":"entity.age"},{"type":"select","label":"Gender","id":"entity.gender","defaultValue":"female","options":[{"value":"male","label":"Male"},{"value":"female","label":"Female"}]}]},{"type":"group","conditions":[{"type":"isEqual","variable":"entity-type","value":["company","organisation"]}],"children":[{"type":"text","label":"Name","id":"entity.name"},{"type":"text","label":"Address","id":"entity.address"}]}]}];
// console.log("%j", elements);
function findObject(element, key, value, { parent = null, index = -1 }) {
if (element.hasOwnProperty(key) && element[key] === value) {
return { element: element, parent, index };
}
let keys = Object.keys(element);
for (let i = 0; i < keys.length; i++) {
if (typeof element[keys[i]] == "object") {
const o = findObject(element[Object.keys(element)[i]], key, value, {
parent: element,
index: i,
});
if (o !== null) return o;
}
}
return { element: null };
}
const { element, parent, index } = findObject(
elements,
"id",
"entity-type",
{}
);
const newOption = { value: "government", label: "Government" };
const updatedElement = Object.assign({}, element, {
options: [...element.options, newOption],
});
if (parent && index !== -1) parent[index] = updatedElement;
console.log(JSON.stringify(elements, null, 4));

JS Split array into X chunks, then Y chunks and so on

How exactly could I split an array into 6 chunks, then 3 chunks, then 6 chunks, then 3 chunks and so on?
So say I have this dataset:
const datasaet = [
{ text: 'hi1' },
{ text: 'hi2' },
{ text: 'hi3' },
{ text: 'hi4' },
{ text: 'hi5' },
{ text: 'hi6' },
{ text: 'hi7' },
{ text: 'hi8' },
{ text: 'hi9' },
{ text: 'hi10' },
{ text: 'hi11' },
{ text: 'hi12' },
{ text: 'hi13' },
{ text: 'hi14' },
{ text: 'hi15' },
{ text: 'hi16' },
]
and I need to split it into an array like this:
const expected = [
[
{ text: 'hi1' },
{ text: 'hi2' },
{ text: 'hi3' },
{ text: 'hi4' },
{ text: 'hi5' },
{ text: 'hi6' },
],
[
{ text: 'hi7' },
{ text: 'hi8' },
{ text: 'hi9' },
],
[
{ text: 'hi10' },
{ text: 'hi11' },
{ text: 'hi12' },
{ text: 'hi13' },
{ text: 'hi14' },
{ text: 'hi15' },
{ text: 'hi16' },
]
]
Essentially what I'm doing is splitting the array into 6 chunks if it's event and 3 chunks if it's odd.
However I don't know exactly how to go about doing this. My current attempt looks like this, I can split it into 6 chunks perfectly but how do I go about doing the next 3, and then the next 6 and so on:
const grouped = datasaet.reduce(
(initital: any[], current, index, items) => {
const isFirstOfSix = index % 6 === 0
if (isFirstOfSix) {
const nextSix = items.slice(index, index + 6)
initital.push(nextSix)
}
return initital
},
[]
)
You might consider creating a copy of the array (to avoid mutating the original), then splicing out items until it's empty, checking and toggling a boolean that indicates whether to remove 6 or 3 items on the current iteration:
const datasaet = [
{ text: 'hi1' },
{ text: 'hi2' },
{ text: 'hi3' },
{ text: 'hi4' },
{ text: 'hi5' },
{ text: 'hi6' },
{ text: 'hi7' },
{ text: 'hi8' },
{ text: 'hi9' },
{ text: 'hi10' },
{ text: 'hi11' },
{ text: 'hi12' },
{ text: 'hi13' },
{ text: 'hi14' },
{ text: 'hi15' },
{ text: 'hi16' },
]
const tempArr = datasaet.slice();
const output = [];
let removeSix = true;
while (tempArr.length) {
output.push(tempArr.splice(0, removeSix ? 6 : 3));
removeSix = !removeSix;
}
console.log(output);
You can create a function that takes an array, and array of chunk sizes. The function iterates the array, cycles between the chunk sizes, and uses slice to take the current chunk size from the original array:
const chunks = (arr, chunkSize) => {
const result = [];
let current = -1;
for (let i = 0; i < arr.length; i += chunkSize[current]) {
current = (current + 1) % chunkSize.length;
result.push(arr.slice(i, i + chunkSize[current]));
}
return result;
}
const dataset = [{"text":"hi1"},{"text":"hi2"},{"text":"hi3"},{"text":"hi4"},{"text":"hi5"},{"text":"hi6"},{"text":"hi7"},{"text":"hi8"},{"text":"hi9"},{"text":"hi10"},{"text":"hi11"},{"text":"hi12"},{"text":"hi13"},{"text":"hi14"},{"text":"hi15"},{"text":"hi16"}];
const result = chunks(dataset, [6, 3]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to traverse in a tree and filter matching nodes in javascript?

I have tried to filter nodes, but succeed to filter only root nodes.
My implementation is below.
How can I use a methodology to filter also sub-nodes?
function getMatchedValues(nodes)
{
var leafContainsText = false;
for (var i = 0; i < nodes.length; i++)
{
if (nodes[i].items && nodes[i].items.length > 0)
{
leafContainsText = getMatchedValues(nodes[i].items);
if (leafContainsText)
break;
}
else
{
if (nodes[i].text.toLowerCase().indexOf($scope.filterReports.toLowerCase()) !== -1)
{
leafContainsText = true;
break;
}
}
}
return leafContainsText;
}
$scope.temp_reports = [];
for (var i = 0; i < $scope.reports.length; i++)
{
if ($scope.reports[i].items && $scope.reports[i].items.length > 0)
{
if (getMatchedValues($scope.reports[i].items))
$scope.temp_reports.push($scope.reports[i]);
else if ($scope.reports[i].text.toLowerCase().indexOf($scope.filterReports.toLowerCase()) !== -1)
$scope.temp_reports.push($scope.reports[i]);
}
else
{
if ($scope.reports[i].text.toLowerCase().indexOf($scope.filterReports.toLowerCase()) !== -1)
$scope.temp_reports.push($scope.reports[i]);
}
}
The tree object($scope.reports) looks likes below:
[
{
text:"abc",
items:[
{
text:"abf"
},
{
text:"abd",
items:[
{
text:"bbb"
},
{
text:"dba"
}
]
}
]
},
{
text:"def",
items:[
{
text:"ddf"
},
{
text:"ddd",
items:[
{
text:"dfg"
},
{
text:"dba",
items:[
{
text:"qqq"
},
{
text:"www"
}
]
}
]
}
]
}
]
For example, If want to filter nodes that contain 'd' then result tree should look like this;
[
{
text:"abc",
items:[
{
text:"abd",
items:[
{
text:"dba"
}
]
}
]
},
{
text:"def",
items:[
{
text:"ddf"
},
{
text:"ddd",
items:[
{
text:"dfg"
},
{
text:"dba",
items:[]
}
]
}
]
}
]
You could filter the array by filtering the items array as well.
This solution mutates the original data.
function filter(array, search) {
return array.filter(function f(o) {
var t;
if (o.items) {
t = o.items.filter(f);
}
if (o.text.includes(search) || t && t.length) {
if (t) {
o.items = t;
}
return true;
}
});
}
var array = [{ text: "abc", items: [{ text: "abf" }, { text: "abd", items: [{ text: "bbb" }, { text: "dba" }] }] }, { text: "def", items: [{ text: "ddf" }, { text: "ddd", items: [{ text: "dfg" }, { text: "dba", items: [{ text: "qqq" }, { text: "www" }] }] }] }],
result = filter(array, 'd');
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Dijit Selects, Items in the Combobox disabled = true doesn't works

This is my code and it doesn't works. It belong to a combobox. Some items should be disabled in it.
var data = [];
for (i = 0; i < items.length; i++) {
data.push({id: items[i].id, label: "foobaa"});
data.getOptions(items[i].id).disabled = true;
}
var memory = new Memory({
idProperty: "id",
data: data
});
this._widget.set("store", memory);
I found a code snipe at fiddle.net and this works but im not able to converte it to my problem.
http://jsfiddle.net/g00glen00b/akcZy/
Also the otherwise super documentation of dojo doesn't helps me :-(
http://dojotoolkit.org/documentation/tutorials/1.10/selects_using_stores/
I have made some changes try this and let me know is this your need? Use the code below to disable all the select items.
var data = [];
for (i = 0; i < myData.length; i++) {
data.push('{id: myData[i].id, label: "foobaa"}');
registry.byId("mySelect").getOptions(myData[i].id).disabled = true;
}
http://jsfiddle.net/f3snxrrd/
http://jsfiddle.net/5pgkkf0z/
items: {
mutators: {
value: [],
type: verify.ARRAY
},
widget: {
updateI18n: true,
mapping: function (widget, items) {
if (this._widget) {
var i;
var data = [];
for (i = 0; i < items.length; i++) {
data.push({id: items[i].id, label: i18n.resolveSequence(items[i].label)});
//register.byId(data).getOptions((items[i].value).disabled = true);
}
var memory = new Memory({
idProperty: "id",
data: data
});
this._widget.set("store", memory);
this._widget.closeDropDown(true);
this._widget.reset();
if (items.length === 0) {
this._enabledItems = false;
}
else if (items.length === 1) {
this.set("selectedId", items[0].id);
this._enabledItems = (this.get("selectedId") !== items[0].id);
}
else {
this._enabledItems = true;
}
this._widget.set("disabled", !(this._enabledState && this._enabledItems ));
}
}
}
},
_createWidget: function () {
var ret;
ret = new Select({id: this.uniqueId, disabled: true, labelAttr: "label", labelType: "Text", required: false, store: new Memory({data: []})});
var that = this;
ret.own(on(ret, "change", function (value) {that._onChange(value); }));
return ret;
},
This is the items array:
The code from jsfiddle.net
http://jsfiddle.net/8m52n81u/11/
I can't change the items array :-/
items = [{
id: "0",
label: key[{0: "foo", 1: "baa"}]
}, {
id: "1",
label: key[{0: "foo", 1: "baa"}]
}];
require([
"dojo/ready",
"dijit/registry",
"dijit/form/Select",
"dojo/store/Memory",
"dojo/parser"
], function(ready, registry) {
ready(function() {
var data = [];
for (i = 0; i < items.length; i++) {
data.push('{id: items[i].id, label: items[i].label}');
registry.byId("uniqueId").getOptions(items[i].id).disabled = true;
}
});
});

How to update code to avoid "Undefined value"?

Recently I was working on a project with this extension and I have noticed that when I select "FIELD" option and enter a value everything works fine. But after I delete value from field and push enter whole app crash because of undefined value. Maybe someone could help me with code how to avoid this annoying crash?
Thx in advance!
Here is whole code.
/*global define*/
define(["qlik"], function(qlik) {
'use strict';
var BTN_SELECTED = 'qui-button-selected',
BTN = 'qui-button',
SELECT = 'qui-select',
INPUT = 'qui-input';
function createVariable(name) {
var app = qlik.currApp();
//from 2.1: check if variable exists
if (app.variable.getByName) {
app.variable.getByName(name).then(function() {
//variable already exist
}, function() {
//create variable
app.variable.create(name);
});
} else {
//create variable - ignore errors
app.variable.create(name);
}
}
function createElement(tag, cls, html) {
var el = document.createElement(tag);
if (cls) {
el.className = cls;
}
if (html !== undefined) {
el.innerHTML = html;
}
return el;
}
return {
initialProperties: {
variableValue: {},
variableName: "",
render: "f",
defaultValue: 0,
alternatives: []
},
definition: {
type: "items",
component: "accordion",
items: {
settings: {
uses: "settings",
items: {
variable: {
type: "items",
label: "Variable",
items: {
name: {
ref: "variableName",
label: "Name",
type: "string",
change: function(data) {
createVariable(data.variableName);
data.variableValue.qStringExpression = '=' + data.variableName;
}
},
render: {
type: "string",
component: "dropdown",
label: "Render as",
ref: "render",
options: [{
value: "b",
label: "Button"
}, {
value: "s",
label: "Select"
}, {
value: "f",
label: "Field"
}, {
value: "l",
label: "Slider"
}],
defaultValue: "f"
},
emptyVal: {
ref: "emptyVal",
label: "default(when empty)",
type: "string",
defaultValue: 0
},
alternatives: {
type: "array",
ref: "alternatives",
label: "Alternatives",
itemTitleRef: "label",
allowAdd: true,
allowRemove: true,
addTranslation: "Add Alternative",
items: {
value: {
type: "string",
ref: "value",
label: "Value"
},
label: {
type: "string",
ref: "label",
label: "Label",
expression: "optional"
}
},
show: function(data) {
return data.render === "b" || data.render === "s";
}
},
min: {
ref: "min",
label: "Min",
type: "number",
defaultValue: 0,
show: function(data) {
return data.render === "l";
}
},
max: {
ref: "max",
label: "Max",
type: "number",
defaultValue: 100,
show: function(data) {
return data.render === "l";
}
},
step: {
ref: "step",
label: "Step",
type: "number",
defaultValue: 1,
show: function(data) {
return data.render === "l";
}
}
}
}
}
}
}
},
paint: function($element, layout) {
var wrapper = createElement('div'),
ext = this;
empty = layout.emptyVal;
if (layout.render === 'b') {
layout.alternatives.forEach(function(alt) {
var clazz = alt.value === layout.variableValue ? BTN_SELECTED : BTN;
var btn = createElement('button', clazz, alt.label);
btn.onclick = function() {
qlik.currApp(ext).variable.setContent(layout.variableName, alt.value);
}
wrapper.appendChild(btn);
});
} else if (layout.render === 's') {
var sel = createElement('select', SELECT);
layout.alternatives.forEach(function(alt) {
var opt = createElement('option', undefined, alt.label);
opt.value = alt.value;
opt.selected = alt.value === layout.variableValue;
sel.appendChild(opt);
});
sel.onchange = function() {
qlik.currApp(ext).variable.setContent(layout.variableName, this.value);
}
wrapper.appendChild(sel);
} else if (layout.render === 'l') {
var range = createElement('input');
range.type = 'range';
range.min = layout.min || 0;
range.max = layout.max || 100;
range.step = layout.step || 1;
range.value = layout.variableValue;
range.title = layout.variableValue;
range.style.width = '98%';
range.onchange = function() {
qlik.currApp(ext).variable.setContent(layout.variableName, this.value);
}
wrapper.appendChild(range);
} else {
var fld = createElement('input', INPUT);
fld.type = 'number';
fld.value = layout.variableValue;
fld.onchange = function () {
if (this.value != "undifined") {
qlik.currApp(ext).variable.setContent(layout.variableName, this.value);
} else {
qlik.currApp(ext).variable.setContent(layout.variableName, 0);
}
}
wrapper.appendChild(fld);
}
var elem = $element[0];
if (elem.childNodes.length === 0) {
elem.appendChild(wrapper);
} else {
elem.replaceChild(wrapper, elem.childNodes[0]);
}
}
};
});
if (this.value != "undifined") {
Here, you are comparing value to the string "undifined" (which is also mistyped).
It seems you want to compare to the value undefined:
if (this.value !== undefined) {
or check the data type of value:
if (typeof this.value != "undefined") {

Categories

Resources