I hope you are good.
I am struggling to create a compatible data type in javascript to display a cartesian like table where we have a vertical and a horizontal header.
Basically I have 3 one dimensional arrays where the first two are the table headers, and the third has the combination of those two by id's (basically the table cells).
let horizontal_header = [
{ id: 1, name: 'h1' },
{ id: 2, name: 'h2' },
];
let vertical_header = [
{ id: 10, name: 'r1' },
{ id: 11, name: 'r2' },
];
let cells = [
{ hid: 1, vid: 10, id: 7, name: 'c1' },
{ hid: 1, vid: 11, id: 8, name: 'c2' },
{ hid: 2, vid: 10, id: 9, name: 'c3' },
{ hid: 2, vid: 11, id: 10, name: 'c4' },
],
Also it can happen that a combination might not exists in that case, I want to enter an empty cell or something obvious that this cell is missing.
I want to create a table like below:
h1
h2
r1
c1
c3
r2
c2
c4
I would appreciate any suggestion and be very thankful to help me solve this complex use-case using Angular for rendering the table template.
Thank you.
I'd approach this problem by parsing the cells into more table-render friendly format like below. Note: I used ### separator, you can use anything that suits for coding practice.
let output = {};
cells.forEach(cell => {
output[cell.hid + '###' + cell.vid] = {
id: cell.id,
name: cell.name,
};
});
After that, you can use the output object to render the table cell as you already know the combination of hid and vid. You can prepare/render your table rows as below.
const rows = [];
for (let i = 0; i < horizontal_header.length; i++) {
const row = [];
for (let j = 0; j < vertical_header.length; j++) {
const hid = horizontal_header[i];
const vid = vertical_header[j];
if (output[hid + '###' + vid]) {
row.push(output[hid + '###' + vid].name);
} else {
row.push('-');
}
}
rows.push(row);
}
Related
I have a product which is made of many x materials, each material can be made of other materials or be pure. If they are made of other materials, it is specified which materials are need with their needed quantity and currently available quantity for the item. I want to calculate how many material I have and I don't have, and for the material I don't have, I want to sum all the missing quantities.
Right know I am getting right the material quantity in the "first level" when the product is missing a material which is not used in submaterials. When I try to sum the missing submaterials the operation is not right.
How can I calculate the materials needed to create a product and each materials?
Here is the code I write:
const product = {
name: 'prod_1',
quantity: 1.2,
material_quantities: [
{ id: 2, quantity: 2 },
{ id: 1, quantity: 2 },
],
};
const materials = [
{
id: 1,
name: 'material1',
quantity: 1.2,
material_quantities: null,
},
{
id: 2,
name: 'material2',
quantity: 1.2,
material_quantities: [{ id: 1, quantity: 2 }],
},
];
function areEnoughMaterials(materialId, neededQuantity) {
const mainMaterial = materials.find(id === materialId);
const inStock = parseFloat(neededQuantity) <= parseFloat(mainMaterial.quantity);
if (mainMaterial?.material_list?.length === 0 && inStock) {
materialsStatus.available[materialId] = mainMaterial.quantity;
}
if (!inStock) {
if (!materialsStatus.missing[materialId]) {
materialsStatus.missing[materialId] =
parseFloat(neededQuantity) - parseFloat(mainMaterial.quantity);
} else {
materialsStatus.missing[materialId] =
materialsStatus.missing[materialId] + parseFloat(mainMaterial.quantity);
}
}
if (mainMaterial.material_quantities) {
for (const material of mainMaterial.material_quantities) {
areEnoughMaterials(material.id, material.quantity);
}
}
return;
}
let materialsStatus = {
available: {},
missing: {},
};
for (const material of product.material_quantities) {
areEnoughMaterials(material.id, material.quantity);
}
The output I am expecting is this:
{
available: { 2:1.2, 1:1.2 },
missing:{ 2:0.8, 1:3.6 }
}
I just try to recreate this grouping example: https://jsfiddle.net/api/post/library/pure/
var now = moment().minutes(0).seconds(0).milliseconds(0);
var itemCount = 60;
// create a data set with groups
var groups = new vis.DataSet();
groups.add([
{
id: 1,
content: "Lee",
nestedGroups: [11, 12, 13],
},
{
id: 2,
content: "invisible group",
visible: false,
},
{
id: 3,
content: "John",
nestedGroups: [14],
showNested: false,
},
{
id: 4,
content: "Alson",
},
]);
groups.add([
{
id: 11,
content: "cook",
},
{
id: 12,
content: "shop",
},
{
id: 13,
content: "clean house",
},
{
id: 14,
content: "wash dishes",
},
]);
// create a dataset with items
var items = new vis.DataSet();
var groupIds = groups.getIds();
var types = ["box", "point", "range", "background"];
for (var i = 0; i < itemCount; i++) {
var start = now.clone().add(Math.random() * 200, "hours");
var end = start.clone().add(2, "hours");
var randomGroupId = groupIds[Math.floor(Math.random() * groupIds.length)];
var type = types[Math.floor(4 * Math.random())];
items.add({
id: i,
group: randomGroupId,
content: "item " + i,
start: start,
end: end,
type: type,
});
}
// create visualization
var container = document.getElementById("visualization");
var options = {
groupOrder: "content", // groupOrder can be a property name or a sorting function
};
var timeline = new vis.Timeline(container, items, groups, options);
However I embed it in my own application which has, among others a menu structure (using toggle an collapse).
My Vis time works for the best part without any problems but toggling the groups gives strange behavior. Groups are disappearing and sub groups are not shown.
I assume this is caused by event-triggering confusion.
Is there a way I can isolate the vis.js events from my hosting application?
Never experienced something like this before so no clue how to solve it.
I know this may a simple problem but I have a the following javascript object:
const categories = {
title: 'cat1',
contents: [
{
name: 'cont1'
},
{
name: 'cont2'
},
{
name: 'cont3'
}
]
}
How can a transform this categories object so it has only 2 contents element as an example?
const transformedCategories = {
title: 'cat1',
contents: [
{
name: 'cont1'
},
{
name: 'cont2'
}
]
}
A couple of ways to do it:
const transformedCategories = {
title: categories.title,
contents: categories.contents.slice(0,2) // you can also use splice here
}
Another, slightly cheeky way:
const contents = [...categories.contents];
contents.length = 2;
const transformedCategories = {...categories, contents}
While I was facing slow loading time when it iterate array to render objects, I want to change its data structure. I show table of contents for seasons. When user clicks an item, the item is marked as selected.
Here is current data structure (Array)
const seasons = [{
id: 6,
value: 'All',
}, {
id: 7,
value: 'Spring',
}, {
id: 8,
value: 'Summer',
}, {
id: 9,
value: 'Fall',
}, {
id: 10,
value: 'Winter',
}];
I'm storing selected Season Ids as an Array now
state = {selectedSeasonIds: []}
When selectedSeasonIds has id, I want to remove the id from it. Otherwise, add the id to selectedSeasonIds. (This is current approach)
if(_.includes(this.state.selectedSeasonIds, id)) {
let newSelectedSeasonIds = _.filter(this.state.selectedSeasonIds, (curObject) => {
return curObject !== id;
});
this.setState({selectedSeasonIds : newSelectedSeasonIds});
} else {
let newSelectedSeasonIds = [...this.state.selectedSeasonIds, id];
this.setState({selectedSeasonIds : newSelectedSeasonIds});
}
And here is my pseudo-code for refactoring to convert my arrays to object structure for performance. (I found searching on an object is MUCH faster than searching on the array)
Changing the array to object
const seasons = {
6 :{
id: 6,
value: 'All',
},
7: {
id: 7,
value: 'Spring',
},
8: {
id: 8,
value: 'Summer',
},
9: {
id: 9,
value: 'Fall',
},
10: {
id: 10,
value: 'Winter',
}
};
Changing Selected Seasons <- I want to store only the key(id) of the objects. But I want to use it as an object
state = {selectedSeasonIds : {}} Can I store object type state?
Here is expected logic which can be 50 times faster than array search.
if(selectedSeasonIds[id]) {
//remove
return _.omit(state.selectedSeasonIds, id); < is this right?
} else {
//add
return {...state.selectedSeasonIds, [id]:id} <- Does this look ok?
}
Well if you think this is right, you can copy and paste my code to the answer (I will edit my question too).
Otherwise, Can you provide better suggestion or find the error?
Thank you so much
I guess you have to loop through seasons in order to render them.
My first suggestion is to add selected prop in each one of them so you don't have to check in selectedSeasonsIds on every render.
In case this is not an option, you can still keep the key value approach.
onAdd(id) {
this.setState({
selectedSeasonsIds: {
...this.state.selectedSeasonsIds,
[id]: this.state.selectedSeasonsIds[id] ? false : true
}
})
}
When checking for specific season whether they are selected or not, simply:
render() {
const { seasons, selectedSeasonsIds } = this.state
return (
<div>
...
{Object.keys(seasons).map(key =>
<ItemComponent
{...propsThatYouMightNeed}
selected={selectedSeasonsIds[key]}
/>
)}
</div>
)
}
Maybe something like this? I'd recommend storing arrays and then converting as necessary for lookups.
const seasons = [{
id: 6,
value: 'All',
}, {
id: 7,
value: 'Spring',
}, {
id: 8,
value: 'Summer',
}, {
id: 9,
value: 'Fall',
}, {
id: 10,
value: 'Winter',
}];
const seasonsHash = _.keyBy(seasons, 'id');
// check for existence
const hasId = _.has(seasonsHash, id)
// remove and convert back to array
_.values(_.omit(seasonsHash, id))
// add new id
_.concat(_.values(seasonsHash), id)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
bit of a newbie! I am trying to re-populate a carousel of images... based on an array of search results. But really hitting surprising amount of issues.
I'm using JS/Jquery and have, say, an array of objects that exist from my api:
let arrayOfObjects = [
{id: 0, title: 'Beauty & The Beast', img: 'https://imgthing1.com' },
{id: 1, title: 'The Brainiac', img: 'https://imgthing2.com' },
{id: 2, title: 'Mac and Me', img: 'https://imgthing3.com' }
];
Then i have my searchTerm which i want to filter the array down, and return a new array of results from:-
function checkWords(searchTerm, arr) {
let results = [];
let st = searchTerm.toLowerCase();
// **** i map through the array - if the search term (say its 'a' is the same
// as the first character of an object's 'title'... then it stores
// that object in results, ready to be rendered. ****
arr.map((each) => {
if (st === each.title.charAt(0)) {
results.push(each)
}
})
console.log(finalResults);
}
But i can't work out how to keep it matching... based on:
'Bea' vs 'Beauty & The Beast' - pass.
'Beat' vs 'Beauty & The Beast' - fail.
You could use Array#filter and check if the string contains the wanted string at position zero.
let arrayOfObjects = [{ id: 0, title: 'Beauty & The Beast', img: 'https://imgthing1.com' }, { id: 1, title: 'The Brainiac', img: 'https://imgthing2.com' }, { id: 2, title: 'Mac and Me', img: 'https://imgthing3.com' }];
function checkWords(searchTerm, arr) {
let st = searchTerm.toLowerCase();
return arr.filter(each => each.title.toLowerCase().indexOf(st) === 0);
}
console.log(checkWords('bea', arrayOfObjects));