Product Vairant Dropdown in ReactJS - javascript

I'm facing an issue while showing product variant drop down in ReactJS component.
Background of the Probelm;
A product can have multiple variants based on different options like (but not limited to) size (with values [7,8,9]), color (with values ["blue", "red", "green"]) or type (with values ["A", "B"]). Sometimes a product can have multiple options available sometime just none.
The following data that is coming from backend, we have two options size and color with 2-2 values each. But in variant, we only have size=7, color=blue and size=9, color=red
{
"data": {
"id": 3,
"name": "Awesome product",
"variants": {
"1": {
"price": "120.00",
"quantity_in_stock": 10,
"Size": "7",
"Color": "blue"
},
"2": {
"price": "125.00",
"quantity_in_stock": 12,
"Size": "9",
"Color": "red"
}
},
"options": {
"Size": [
"7",
"9"
],
"Color": [
"blue",
"red"
]
}
}
}
And I wanted to show the following data in UI,
A user can select any values from size (7,8,9) and color (blue, red) dropdowns. Now, I'm not sure how to prevent user from select variant option that is not available (for e.g. size=7, color=red)

Related

How can I send Multiple Array in FormData API with React native

Form data that I want to send.
these array will increase if user select more data
what I need to do is , when user select YES it will add an array and
when user select multiple YES it will adds multiple array.
categories[65][sub_category_id]:65
categories[65][value]:1
categories[65][category_id]:61
categories[65][sub_category_name]: Cover Immersion
categories[66][sub_category_id]:66
categories[66][value]:1
categories[66][category_id]:61
categories[66][sub_category_name]: Foam Immersion Support & Structure
!FormData Picture with API]2
When user select yes it adds a new array in the categories just like I
mentioned above.
well I need to send this data with FormData I already used APPEND and
PUSH in my code but it didn't work for me maybe I didn't wrote it
correctly.
Full FORMDATA data
this type of response I get when I hit the FORMDATA API from post man
"data": {
"categories": {
"65": {
"sub_category_id": "65",
"value": "1",
"category_id": "61",
"sub_category_name": "Cover Immersion"
},
"66": {
"sub_category_id": "66",
"value": "1",
"category_id": "61",
"sub_category_name": "Foam Immersion Support & Structure"
},
"67": {
"sub_category_id": "67",
"value": "1",
"category_id": "61",
"sub_category_name": "Foam Depth"
}
},
"audit": {
"site": "Neuro. ios22",
"ward_id": "14",
"score_threshold": "33",
"super_user_id": 15,
}
}
this is my code in expo snack for further edition
Expo snack

Setting a field to an object in an array, Vega-lite

I have an array of objects that I am using as a dataset in an interactive data dashboard. I want to add a new feature that displays data from only one object at a time, rather than pulling data from all objects (which I am already doing and it works well). As a test case, I have created a simple array:
var test1 = [
[{
"name": "Piece One",
"amount": 5
}, {
"name": "Piece Two",
"amount": 5
}, {
"name": "Piece Three",
"amount": 5
}],
[{
"name": "Piece One",
"amount": 1
}, {
"name": "Piece Two",
"amount": 1
}, {
"name": "Piece Three",
"amount": 5
}]
];
and the Vega-lite javascript:
var pieCreate = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": "A pie chart",
"description": "A simple pie chart with embedded data.",
"width": "container",
"height": "container",
"data": {
"values": test1[0]
},
"mark": "arc",
"encoding": {
"theta": {
"field": "amount",
"type": "quantitative"
},
"color": {
"field": "name",
"type": "nominal",
"legend": null
}
}
};
This works, but I want the user to be able to choose which object to display (in the dashboard, each object contains data on different schools, and I want the user to be able to choose which school's data to display using a dropdown menu). My first thought was to set up a signal in the "data": {"values": field that would change the number in brackets to the array I want, but after a lot of trial and error, I think that may be a dead end. Signals should work to modify "field": "amount" and "field": "name" but I've tried every iteration of [0].amount that I can think of, while dropping the brackets from test1[0] and nothing has worked. If I can manage to access the object by directly referencing it in "field": I believe I can figure out the process using a signal and html form, but I'm starting to doubt if I'm even on the right track here.
I also tried the process outlined here in the vega-lite documentation: https://vega.github.io/vega-lite/tutorials/streaming.html, but it's doing something much more complicated than what I'm trying to do, and my javascript knowledge isn't sufficient to break it down to something usable. Does anyone have any ideas on how to make this work, using any of the above approaches (or a new, better one)?
You can use the vega Api's to change the data. On your selection, add a change event and on some conditions you can toggle between your data using those API's.
Refer the below snippet or fiddle:
var test1 = [
[{
"name": "Piece One",
"amount": 5
}, {
"name": "Piece Two",
"amount": 5
}, {
"name": "Piece Three",
"amount": 5
}],
[{
"name": "Piece One",
"amount": 1
}, {
"name": "Piece Two",
"amount": 1
}, {
"name": "Piece Three",
"amount": 5
}]
];
var yourVlSpec = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": "A pie chart",
"description": "A simple pie chart with embedded data.",
"width": "350",
"height": "400",
"data": {
"values": test1[0]
},
"mark": "arc",
"encoding": {
"theta": {
"field": "amount",
"type": "quantitative"
},
"color": {
"field": "name",
"type": "nominal",
"legend": null
}
}
}
var view;
vegaEmbed("#vis", yourVlSpec).then(res => {
view = res.view;
});
function handleChange(a, b) {
var selectValue = document.getElementById("myselect").value;
if (selectValue == 'A') {
view.data('source_0', test1[0]);
} else {
view.data('source_0', test1[1]);
}
view.runAsync();
}
<script src="https://cdn.jsdelivr.net/npm/vega#5.20.2/build/vega.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite#5.0.0/build/vega-lite.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed#6.17.0/build/vega-embed.min.js"></script>
<select id="myselect" style="width:100px;" onchange="handleChange()">
<option>A</option>
<option>B</option>
</select>
<br>
<div id="vis"></div>

Redux state tree structure: "same type of data with different format / amounts of detail"

I've done Dan Abramov's intro series on EggHead, and am working on a real world app. The domain is complex, so I'll run with a classic "blogs" example.
Let's say, we have an "index / list" page, where all we need to show are the blog post's title and blurb. So we have an API endpoint that returns that, and we store it in our state tree under blogs.byId.
Then, when you click through on a blog post, we actually need a bunch more info - e.g. the full blog post, and also tags and categories. Let's call this "blogs with metadata".
Stretching the example, there might be another completely separate page where I want to display a list of blog posts with the most recent 3 comments. Let's call this "blogs with comments".
My question is, how should my state tree treat these separate examples where I'm storing the same "thing" but in different "formats"? My initial hunch would be to treat them as completely separate data types, so my state tree would have eg: blogs.byId, blogsWithMetadata.byId and blogsWithComments.byId.
And then, even if every single blog post is cached in the blogs.byId section, the minute we need to view a blog post, the app completely ignores that warm blogs.byId cache, and looks only at blogsWithMetadata.byId - so we'd essentially be building up 3 separate caches of blog data, each with different amounts of info, and treating it as though they are as unrelated to each other as "blogs" and a completely unrelated table like "widgets" would be.
Is this correct? Or is there a better way?
The app currently rams them all under the same node, without distinction based on "format" and it's causing a world of pain.
There are probably many ways you could choose to do this. One of it is to use normalizr to structure your data.
Your blog post could have a data structure returned by the API like this:
{
"id": "123",
"author": {
"id": "1",
"name": "Paul"
},
"title": "My awesome blog post",
"comments": [{
"id": "324",
"commenter": {
"id": "2",
"name": "Nicole"
}
}],
"tags": [{
"id": "1",
"value": "awesome"
}, {
"id": "2",
"value": "journal"
}],
"categories": [{
"id": "1",
"value": "personal"
}, {
"id": "2",
"value": "life"
}]
}
which after normalizing, will look something like this:
{
entities: {
"post": {
"123": {
id: "123",
author: "1",
title: "My awesome blog post",
comments: ["324"],
tags: ["1", "2"],
categories: ["1", "2"],
}
},
"users": {
"1": { "id": "1", "name": "Paul" },
"2": { "id": "2", "name": "Nicole" }
},
"comments": {
"324": { id: "324", "commenter": "2" }
}
"tags": {
"1": { id: "1", "value": "awesome" },
"2": { id: "2", "value": "journal" },
}
"categories": {
"1": { id: "1", "value": "personal" },
"2": { id: "2", "value": "life" },
}
}
}
Subsequently, you could have a state for each page if you needed to:
{
entities: {...},
ui: {
blogs: {
posts: [1, 2],
hasComments: false,
// Displaying the blogs with or without comments
// could simply just be a boolean flag in state.
},
}
}
using reselect, you then create the selectors to pass the posts you want as props to the page Components.

Multiple series data on HighCharts column

I'm using HighCharts on a project, and I'm having trouble formatting the data in the way I'd like. I currently have something that works, but it doesn't feel quite right.
What I have is a column chart with everything in one series. I'd rather have each data point be in it's own series & properly labeled in the legend & tooltips. Below are samples of the relevant bits to format the data.
I'm not sure what I'm doing wrong, the changes I've made feel like they should work given their docs & this demo. Also, Do I need the categories if multiple series works?
Working:
"series": [
{
"data": [
{
"y": 92,
"name": "Apples: 92ms for 83,481,430 requests",
"color": "#91cb73"
},
{
"y": 761,
"name": "Bananas: 761ms for 58,050,877 requests",
"color": "#ab7053"
},
{
"y": 774,
"name": "Kiwis: 774ms for 362,294 requests",
"color": "#44719c"
}
]
}
]
Demo: http://jsfiddle.net/b65kp/
Not working:
"series": [
{
"name": "Apples",
"data": {
"y": 92,
"name": "92ms for 83,481,430 requests",
"color": "#91cb73"
}
},
{
"name": "Bananas",
"data": {
"y": 761,
"name": "761ms for 58,050,877 requests",
"color": "#ab7053"
}
},
{
"name": "Kiwis",
"data": {
"y": 774,
"name": "774ms for 362,294 requests",
"color": "#44719c"
}
}
]
Demo: http://jsfiddle.net/u74Qw/1/
The problem is that "data" expects an array, and you are giving it an object. Wrap each object in an array. For example:
"data": [{
"y": 92,
"name": "92ms for 83,481,430 requests",
"color": "#91cb73"
}]
Here is your full fix, but it might not give the result you expect, personally I like your first attempt better
FWIW, alternate approach to setting this up:
http://jsfiddle.net/jlbriggs/zbW4D/
Things to consider:
1) using a legend instead of just directly labeling each bar makes the user do a lot of looking back and forth to see which is which (doing both just adds extra clutter to distract the user)
2) rotating labels always adds more work for the user
3) multiple colors for the bars is not necessary when each bar is labeled appropriately, and again just adds distraction
A horizontal bar chart with no legend and single color for data solves these problems.

Handsontable Replace autocomplete values with key before posting

I am using HandsOnTable to make editing database tables more interactive on my site.
HandsOnTable fulfils nearly all my requirements except that some columns in my database actually store foreign keys rather than local string values.
In the UI I would like these columns to appear as dropdown menus where the user selects a readable value mapped to the previously mentioned foreign key (I.e. something like an HTML name/value select).
Unfortunately HandsOnTable does not have such a cell type. The closest thing to it is autocomplete. This allows me to create a dropdown, but it only contains values; no corresponding keys. Here is how it is created:
"source": ["Jebediah", "Bob", "Bill", "Buzz"]
So what I am planning is to send two Json strings from the server:
One containing the parameters needed by HandsOnTable to render the table:
{
"data": [
{ "ID": 1, "Description": "Crude", "Volume": 204, "Customer": "jebediah" },
{ "ID": 2, "Description": "Hidrogen", "Volume": 513, "Customer": "Bob" },
{ "ID": 3, "Description": "Coal", "Volume": '67', "Customer": "Bill" },
{ "ID": 4, "Description": "Wood", "Volume": '513', "Customer": "Buzz" }
],
"columns": [
{ "data": "ID", "type": "numeric" },
{ "data": "Description", "type": "text"},
{ "data: "Volume", "type": "numeric" },
{ "data": "color", "type": "autocomplete", "strict": "true",
"source": ["Jebediah", "Bob", "Bill", "Buzz"]}
]
}
The second mapping keys to values
{
"mappings": [
{"key": 0, "value": "Jebediah"},
{"key": 0, "value": "Bob"},
{"key": 0, "value": "Bill"},
{"key": 0, "value": "Buzz"}
]
}
So far so good. Now for the tricky part:
HandsOnTable has a function (getData()) that allows me to retrieve the tables data as a Json string ready to be sent back to the server:
var jdata = myHandsOnTable.getData();
Where jdata would look something like this:
"data": [
{ "ID": 1, "Description": "Crude", "Volume": 204, "Customer": "jebediah" },
{ "ID": 2, "Description": "Hidrogen", "Volume": 513, "Customer": "Bob" },
{ "ID": 3, "Description": "Coal", "Volume": '67', "Customer": "Bill" },
{ "ID": 4, "Description": "Wood", "Volume": '513', "Customer": "Buzz" }
]
Now before posting, I would like to replace that values for the Customer node with their matching pair key within the mappings json string.
How can I best achieve this in JavaScript/JQuery?
Is there a function that works something as follows?:
jdata.replaceNode('node', mappings)
Thanks
I had a similar issue and here's what I did...
For each foreign key column, I stored 2 values in handsontable; one for the id itself, which I set as a hidden column and the other is the user friendly readable text value as dropdowns.
Everytime the value of a dropdown is changed, I also change the corresponding hidden id. In my case I have a dropdown outside the handsontable as a filter which I use to map key/value pairs, but you could use Hashtables or anything else.
Now the code...
Handsontable config:
afterChange: function (changes, source) { AfterChange(changes, source); }
After change event (called everytime there is a change in the table):
function AfterChange(Changes, Source) {
if (Source === 'loadData') {
return; //don't save this change
}
var rowIndex = 0, columnID = 1, oldTextVal = 2, newTextVal = 3, ntv = '', nv = '';
$(Changes).each(function () {
if (this[columnID] === 'CategoryID') {
// Do nothing...
//To make sure nothing else happens when this column is set through below
}
else if (this[columnID] === 'CategoryName') {
ntv = this[newTextVal];
//This is where I do my mapping using a dropdown.
nv = $('#CategoriesFilterDropdown option').filter(function () { return $(this).text() === ntv; }).val();
//13 is my CategoryID column
$container.handsontable('setDataAtCell', this[rowIndex], 13, nv);
}
});
}
}
This way, you change the foreign keys as you and don't need to loop through it all before saving. It also makes it easy to send the table data as is back to server.
In summary,
The user interacts with CategoryName column (which is of type autocomplete).
The CatgoryID column is hidden to the user by setting the column width to 0 using the colWidths option of handsontable.
When the CategoryName field changes, use afterChange event to set the corresponding CategoryID column. In my case, I use a dropdown somewhere else on the page to map Name => ID, but you can use other means such as a hashtable.
I hope it makes sense...

Categories