Related
When I click the button, I want to include all the objects in the itemSold and itemGet objects of the customers into the products array. how can I do that?
let customers = [{
active: true,
id: 1,
product: {
itemSold: [{id:1,name : 'car'}, {id:2,name : 'home'}],
itemGet: [{id:3,name : 'phone'}, {id:4,name : 'fly'}],
},
},
{
active: true,
id: 2,
product: {
itemSold: [{id:5,name : 'lamb'}, {id:6,name : 'mouse'}],
itemGet: [{id:7,name : 'mouse pad'}, {id:8,name : 'tv'}],
},
},
];
let clickButton = document.querySelector("#clickButton");
let products = [];
clickButton.addEventListener("click", getProcuts()});
function getProducts(){}
<button id="clickButton" >Click
</button>
let customers = [{
active: true,
id: 1,
product: {
itemSold: [{ id: 1, name: 'car' }, { id: 2, name: 'home' }],
itemGet: [{ id: 3, name: 'phone' }, { id: 4, name: 'fly' }],
},
},
{
active: true,
id: 2,
product: {
itemSold: [{ id: 5, name: 'lamb' }, { id: 6, name: 'mouse' }],
itemGet: [{ id: 7, name: 'mouse pad' }, { id: 8, name: 'tv' }],
},
},
];
let clickButton = document.querySelector("#clickButton");
let products = [];
clickButton.addEventListener("click", getProducts);
function getProducts() {
for (let i = 0; i < customers.length; i++) {
products.push(...customers[i].product.itemGet, ...customers[i].product.itemSold);
}
console.log(products);
}
<button id="clickButton">Click</button>
We loop our customers array and then select product property there we push both itemSold and itemGet arrays into products.
You can map over the customers and concatenate the arrays.
const customers = [
{
active: true,
id: 1,
product: {
itemSold: [
{ id: 1, name: "car" },
{ id: 2, name: "home" },
],
itemGet: [
{ id: 3, name: "phone" },
{ id: 4, name: "fly" },
],
},
},
{
active: true,
id: 2,
product: {
itemSold: [
{ id: 5, name: "lamb" },
{ id: 6, name: "mouse" },
],
itemGet: [
{ id: 7, name: "mouse pad" },
{ id: 8, name: "tv" },
],
},
},
];
const products = customers.map((customer) => {
return customer.product.itemSold.concat(customer.product.itemGet);
});
console.log(products);
const customers = [
{
active: true,
id: 1,
product: {
itemSold: [
{ id: 1, name: "car" },
{ id: 2, name: "home" },
],
itemGet: [
{ id: 3, name: "phone" },
{ id: 4, name: "fly" },
],
},
},
{
active: true,
id: 2,
product: {
itemSold: [
{ id: 5, name: "lamb" },
{ id: 6, name: "mouse" },
],
itemGet: [
{ id: 7, name: "mouse pad" },
{ id: 8, name: "tv" },
],
},
},
];
const products = customers.map((customer) => {
return customer.product.itemSold.concat(customer.product.itemGet).flat();
});
console.log(products.flat());
I have a data structure as given below
ds: [
{ id: "0a12", pos: 0, name: "PH1" },
{
id: "8f83",
name: "PH2",
pos: 1,
children: [
{ id: "ll54", pos: 0, name: "L1" },
{
id: "97cs",
name: "L2",
pos: 1,
children: [
{ id: "80s3", pos: 0, name: "LL1" },
{ id: "2dh3", pos: 1, name: "LL2" },
],
},
],
},
{ id: "75fd", pos: 2, name: "PH3" },
{ id: "34jg", pos: 3, name: "PH4" },
],
I am creating a org chart wherein I have option to add a node to the left or right.
On clicking the node, I can get the node obj as an argument (ie) if I clicked on 'LL1' I can get that object, along with second arg called as type which will contain either 'left' or 'right'.
so now the type == 'left' then my resultant data structure should be like
ds: [
{ id: "0a12", pos: 0, name: "PH1" },
{
id: "8f83",
name: "PH2",
pos: 1,
children: [
{ id: "4", pos: 0, name: "L1" },
{
id: "5",
name: "L2",
pos: 1,
children: [
{ id: "36fd", pos: 0, name: "" }, // new node for type === 'left'
{ id: "80s3", pos: 1, name: "LL1" },
{ id: "2dh3", pos: 2, name: "LL2" },
],
},
],
},
{ id: "75fd", pos: 2, name: "PH3" },
{ id: "34jg", pos: 3, name: "PH4" },
],
and if type === 'right'
ds: [
{ id: "0a12", pos: 0, name: "PH1" },
{
id: "8f83",
name: "PH2",
pos: 1,
children: [
{ id: "4", pos: 0, name: "L1" },
{
id: "5",
name: "L2",
pos: 1,
children: [
{ id: "80s3", pos: 0, name: "LL1" },
{ id: "36fd", pos: 1, name: "" }, // new node for type === 'right'
{ id: "2dh3", pos: 2, name: "LL2" },
],
},
],
},
{ id: "75fd", pos: 2, name: "PH3" },
{ id: "34jg", pos: 3, name: "PH4" },
],
Note: for those nodes that don't have children we shouldn't initialize an empty array to children attribute
You can use Array.slice and spread operator to insert the new node into your array.
let data = [
{ id: '0a12', pos: 0, name: 'PH1' },
{
id: "8f83",
name: "PH2",
pos: 1,
children: [
{ id: '4', pos: 0, name: 'L1' },
{
id: '5',
name: 'L2',
pos: 1,
children: [
{ id: '80s3', pos: 0, name: 'LL1' },
{ id: '2dh3', pos: 1, name: 'LL2' },
],
},
],
},
{ id: '75fd', pos: 2, name: 'PH3' },
{ id: '34jg', pos: 3, name: 'PH4' },
];
function addNode(direction, idElement, ptr) {
const elementIndex = ptr.findIndex(x => x.id === idElement);
if (elementIndex === -1) {
// Go deeper
return ptr.map(x => x.children ? {
...x,
children: addNode(direction, idElement, x.children),
}: x);
}
const offset = direction === 'left' ? 0 : 1;
// Insert the new node in the correct position
const mutatedPtr = [
...ptr.slice(0, elementIndex + offset),
{ id: 'XXXX', pos: elementIndex + offset, name: '' },
...ptr.slice(elementIndex + offset),
];
// change the positions
mutatedPtr.forEach((x, xi) => {
x.pos = xi;
});
return mutatedPtr;
}
data = addNode('right', '75fd', data);
data = addNode('left', '75fd', data);
data = addNode('left', '2dh3', data);
data = addNode('right', '2dh3', data);
console.log(data);
This is a tree insertion problem. First you need to find the index to the anchor node and then insert a new node at index if type is "left" or index + 1 if type is "right". Here's a solution that works for your case. Note that you need to set the right "id" using whatever id generator you have.
ds = [
{ id: "0a12", pos: 0, name: "PH1" },
{
id: "8f83",
name: "PH2",
pos: 1,
children: [
{ id: "4", pos: 0, name: "L1" },
{
id: "5",
name: "L2",
pos: 1,
children: [
{ id: "80s3", pos: 0, name: "LL1" },
{ id: "2dh3", pos: 1, name: "LL2" }
]
}
]
},
{ id: "75fd", pos: 2, name: "PH3" },
{ id: "34jg", pos: 3, name: "PH4" }
];
// Returns parent & position
function findNode(childNodes, name) {
for (var ii = 0; ii < childNodes.length; ii++) {
let child = childNodes[ii];
if (child.name == name) {
return {
childNodes: childNodes,
index: ii
};
}
if (child.children) {
let result = findNode(child.children, name);
if (result) {
return result;
}
}
}
return null;
}
function rewritePositions(childNodes) {
for (var ii = 0; ii < childNodes.length; ii++) {
childNodes[ii].pos = ii;
}
}
function insertNode(name, type) {
let searchResult = findNode(ds, name);
if (!searchResult) {
return;
}
let index = searchResult.index;
let newPosition = type === "left" ? index : index + 1;
let newNode = { id: "todo: index", pos: newPosition, name: "" };
searchResult.childNodes.splice(newPosition, 0, newNode);
rewritePositions(searchResult.childNodes);
}
i'm using select2 in v4.0.3
When I search through the children, for example, "sub category 1", the search appears and your parent "Category 1" is also located above.
https://ibb.co/iNAdLG
But, when I search for "Category 1" it does not show me any of the children. I have reviewed the documentation and several approaches but none has worked for me.
https://ibb.co/eVuSEb
Annex images of reference and code
$("#multisearch").select2({
language: "es",
closeOnSelect: false,
placeholder: "Comienza tu búsqueda",
data: [{
id: 0,
text: 'Linea 1',
children: [{
id: 1,
text: 'San Pablo'
},
{
id: 2,
text: 'Pajaritos'
},
{
id: 3,
text: 'Las Rejas'
},
{
id: 4,
text: 'Ecuador'
}
]
},
{
id: 5,
text: 'Linea 2',
children: [{
id: 6,
text: 'La Cisterna'
},
{
id: 7,
text: 'El Parrón'
},
{
id: 8,
text: 'Lo Ovalle'
},
{
id: 9,
text: 'Ciudad del niño'
},
{
id: 10,
text: 'Pajaritos'
}
]
},
{
id: 1,
text: 'prueba'
},
]
});
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
<select multiple id="multisearch" style="width:500px">
</select>
I will be attentive, thank you very much
You can achieve this by implementing custom matcher function.
Please check the example below:
$(document).ready(function(){
function customMatcher(params, data) {
data.parentText = data.parentText || "";
if ($.trim(params.term) === '') {
return data;
}
if (data.children && data.children.length > 0) {
var match = $.extend(true, {}, data);
for (var c = data.children.length - 1; c >= 0; c--) {
var child = data.children[c];
child.parentText += data.parentText + " " + data.text;
var matches = customMatcher(params, child);
if (matches == null) {
match.children.splice(c, 1);
}
}
if (match.children.length > 0) {
return match;
}
return customMatcher(params, match);
}
var original = (data.parentText + ' ' + data.text).toUpperCase();
var term = params.term.toUpperCase();
if (original.indexOf(term) > -1) {
return data;
}
return null;
}
$("#multisearch").select2({
language: "es",
closeOnSelect: false,
matcher: customMatcher,
placeholder: "Comienza tu búsqueda",
data: [{
id: 0,
text: 'Linea 1',
children: [{
id: 1,
text: 'San Pablo'
},
{
id: 2,
text: 'Pajaritos'
},
{
id: 3,
text: 'Las Rejas'
},
{
id: 4,
text: 'Ecuador'
}
]
},
{
id: 5,
text: 'Linea 2',
children: [{
id: 6,
text: 'La Cisterna'
},
{
id: 7,
text: 'El Parrón'
},
{
id: 8,
text: 'Lo Ovalle'
},
{
id: 9,
text: 'Ciudad del niño'
},
{
id: 10,
text: 'Pajaritos'
}
]
},
{
id: 1,
text: 'prueba'
},
]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
<select multiple id="multisearch" style="width:500px">
</select>
I am trying to create a JavaScript object that grabs each services array in BusinessData, and then collates it as follows:
services: [
{
id: 1,
businessId: 1,
title: 'Brake Fluid Refresh'
},
{
id: 2,
businessId: 1,
title: 'Diagnostics'
},
{
id: 3,
businessId: 1,
title: 'Coolant Refresh'
},
{
id: 4,
businessId: 1
title: 'Oil Change'
},
{
id: 5,
businessId: 1,
title: 'MOT'
},
{
id: 6,
businessId: 1,
title: 'Summer Check'
},
{
id: 7,
businessId: 1,
title: 'Winter Check'
}
]
This is my code so far:
var businessData = [
{
id: 1,
categoryId: 1,
name: 'Japan Center Garage',
services: [
{
id: 1,
businessId: 1,
title: 'Brake Fluid Refresh'
},
{
id: 2,
businessId: 1,
title: 'Diagnostics'
}
]
},
{
id: 2,
categoryId: 1,
name: 'Rex Garage',
services: [
{
id: 3,
businessId: 1,
title: 'Coolant Refresh'
},
{
id: 4,
businessId: 1
title: 'Oil Change'
}
]
},
{
id: 3,
categoryId: 1,
name: 'Mission & Bartlett Garage',
services: [
{
id: 5,
businessId: 1,
title: 'MOT'
},
{
id: 6,
businessId: 1,
title: 'Summer Check'
},
{
id: 7,
businessId: 1,
title: 'Winter Check'
}
]
}
]
return {
getAllCategories: function () {
return categoryData;
},
getAllServices: function () {
var servicesData = {
services: []
};
for(var i = 0; i < businessData.length; i++) {
if(businessData[i].services) {
servicesData['services'].push(businessData[i].services)
}
}
return servicesData;
},
getAllBusinesses: function () {
return businessData;
},
}
}])
It doesn't work very well, and produced an array that I can't seem to access in my view after calling it from my controller:
<div class="item item-divider">
Service
</div>
<ion-list>
<ion-item ng-repeat="item in serviceList | orderBy:'title'">
<p>{{item.title}}</p>
</ion-item>
</ion-list>
<div ng-if="item !== undefined && !item.length" class="no-results">
<div class="item" style="border-top: 0px">
<p>No Results</p>
</div>
</div>
Update
serviceList is called from my the controller:
$scope.serviceList = ServicesData.getAllServices();
What is going wrong here?
var services = [];
businessData.forEach(function (business) {
Array.prototype.push.apply(services, business.services);
});
You are almost there, but you are pushing array of services to an array. By using Array.prototype.push.apply, we are instead pushing services to an array. Which eventually gives you the result you want :)
You can use lodash for that, and you better add it to your toolkit in general.
Here is how it will look with lodash:
_.flatMap(businessObject, (d) => d.services)
Or even
_.flatMap(businessObject, "services")
To make it little bit more verbose, you are doing map and then flatten:
var mapped = _.map(businessObject, "service")
var services = _.flatten(mapped)
I have a Object which looks like the following obj.
var obj = [
{ id: 1, name: "animals" },
{ id: 2, name: "animals_cat" },
{ id: 3, name: "animals_dog" },
{ id: 4, name: "animals_weazle" },
{ id: 5, name: "animals_weazle_sand shadow weazle" },
{ id: 11, name: "fruits" },
{ id: 32, name: "fruits_banana" },
{ id: 10, name: "threes" },
{ id: 15, name: "cars" }
];
The Object should be converted into the following scheme:
var items = [
{ id: 11, name: "fruits", items: [
{ id: 32, name: "banana" }
]},
{ id: 10, name: "threes" },
{ id: 1, name: "animals", items: [
{ id: 2, name: "cat" },
{ id: 3, name: "dog" },
{ id: 4, name: "weazle", items: [
{ id: 5, name: "sand shadow weazle" }
]}
]},
{ id: 15, name: "cars" }
];
I tried a lot but unfortunately without any success. I did $.each on obj, did a split('_') on it and pushed it to items. But how can I do it for unlimited depth and push it into the right category?
I'm happy for any help.
Maybe this helps.
It works with Array.prototype.forEach for processing obj, Array.prototype.reduce for getting the right branch and Array.prototype.some for the right array element for inserting the new object.
This proposal works for sorted and consistent data.
var obj = [
{ id: 1, name: "animals" },
{ id: 2, name: "animals_cat" },
{ id: 3, name: "animals_dog" },
{ id: 4, name: "animals_weazle" },
{ id: 5, name: "animals_weazle_sand shadow weazle" },
{ id: 11, name: "fruits" },
{ id: 32, name: "fruits_banana" },
{ id: 10, name: "threes" },
{ id: 15, name: "cars" }
],
tree = [];
obj.forEach(function (a) {
var path = a.name.split('_'),
o = {};
o.id = a.id;
path.reduce(function (r, b) {
o.name = b;
r.some(function (c) {
if (c.name === b) {
c.items = c.items || [];
r = c.items;
return true;
}
});
return r;
}, tree).push(o);
});
document.write('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');
Update: Version for independent order of items.
var obj = [
{ id: 5, name: "animals_weazle_sand shadow weazle" },
{ id: 32, name: "fruits_banana" },
{ id: 1, name: "animals" },
{ id: 2, name: "animals_cat" },
{ id: 3, name: "animals_dog" },
{ id: 4, name: "animals_weazle" },
{ id: 11, name: "fruits" },
{ id: 10, name: "threes" },
{ id: 15, name: "cars" },
{ id: 999, name: "music_pop_disco_euro"}
],
tree = [];
obj.forEach(function (item) {
var path = item.name.split('_'),
o = tree;
path.forEach(function (a, i) {
var oo = { name: a, items: [] },
last = path.length - 1 === i,
found = o.some(function (b) {
if (b.name === a) {
if (last) {
b.id = item.id;
return true;
}
b.items = b.items || [];
o = b.items;
return true;
}
});
if (!found) {
if (last) {
o.push({ id: item.id, name: a });
} else {
o.push(oo);
o = oo.items;
}
}
});
});
document.write('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');