Adding items in the nested array of React state - javascript

I'm trying to add new items to an array of an object that resides in another object of a state. Pretty nested.
So I tried the following way...
// The initial data
[options, setOptions] = useState({
name: 'Name goes here'
type: 'type goes here'
series : [{
type: 'series type',
label: 'series label'
})
Now I want to add another object inside the object of series array with useEffect(). And I tried:
useEffect(() => {
// other functionalities goes here
setOptions({
...options, // for copying previous data outside of series
series: [{
...options.series, //this is for copying previous data of series
tooltip: {
enable: true,
}]
})
}, [refreshData])
The way I'm copying ...options works absolutely fine, But when I try to copy ...options.series it adds a new copied object inside the object of series array like the following:
{
name: 'Name goes here' //fine
type: 'type goes here' //fine
series: [{
{type: 'series type', label: 'series label'}, //not fine
tooltip: {enable: true} //not fine
//what I want is: to have previous object data and tooltip appended as another item
}]
}
The way I want the object to be is:
{
name: 'Name goes here' //fine
type: 'type goes here' //fine
series: [{
type: 'series type',
label: 'series label'
tooltip: {enable: true}
}]
}
Can Anybody help me regarding this. I would appreciate any help..
Thanks

here is sample of what you are trying to achieve .
const d = {
name: 'Name goes here',
type: 'type goes here',
series : [{
type: 'series type',
label: 'series label'
}]
}
const newD = {
...d,
series: [
{
...d.series[0], // problem is here
tooltip: {
enable: true,
}
}
]
}
console.log (newD)

Related

How to transform only 2 properties but keep remaining same as is in a nested object structure?

Apologies if title is not clear.
I am using json2csv npm package to prepare csv from json object and this package allows us to add a hook to transform object before actual csv line is prepared.
I only need to manipulate two properties out of all. How can I do this effectively? My code feels too bloated.
const {
Parser: Json2csvParser,
transforms: { unwind },
} = require('json2csv');
const json2csvFields = [
{ value: 'root.filename', label: 'File Name' },
{ value: 'issue.root.priority', label: 'Priority' },
{ value: 'issue.root.url', label: 'URL' },
{ value: 'issue.root.startline', label: 'Start Line' },
{ value: 'issue.root.stopline', label: 'Stop Line' },
{ value: 'issue.root.startcolumn', label: 'Start Column' },
{ value: 'issue.root.stopcolumn', label: 'Stop Column' },
{ value: 'issue.root.issuename', label: 'Issue Name' },
{ value: 'issue.root.issuecategory', label: 'Issue Category' },
{ value: 'issue._', label: 'Issue Description' },
];
const sampleData = [
{
root: {
filename:
'/home/users/john-doe/workspace/foo-project/src/main/classes/foo.cls',
},
issue: {
root: {
priority: 1,
url: 'www.example.com',
startline: 100,
stopline: 105,
startcolumn: 20,
stopcolumn: 25,
issuename: 'blah',
issuecategory: 'Category A',
},
_: ' Fox ',
},
},
];
const json2csvOptions = {
fields: json2csvFields,
quote: '',
header: true,
transforms: [
(item) => ({
'root.filename': item.root.filename.replace(
'/home/users/john-doe/workspace/foo-project/src/main/classes/',
''
),
'issue._': `"${item.issue._.trim()}"`,
// Except for the above two, everything else doens't need any transformation.
'issue.root.priority': item.issue.root.priority,
'issue.root.url': item.issue.root.url,
'issue.root.startline': item.issue.root.startline,
'issue.root.stopline': item.issue.root.stopline,
'issue.root.startcolumn': item.issue.root.startcolumn,
'issue.root.stopcolumn': item.issue.root.stopcolumn,
'issue.root.issuename': item.issue.root.issuename,
'issue.root.issuecategory': item.issue.root.issuecategory,
}),
],
};
const json2csvParser = new Json2csvParser(json2csvOptions);
const csv = json2csvParser.parse(sampleData);
console.log(csv);
This prints below output:
File Name,Priority,URL,Start Line,Stop Line,Start Column,Stop Column,Issue Name,Issue Category,Issue Description
foo.cls,1,www.example.com,100,105,20,25,blah,Category A,"Fox"
EDIT: Updated code to a working example.
After listing the two properties with special treatment, use Object.fromEntries and Object.entries to transform all the issue.root properties to their flat structure with .s in the property names. Then that object can be spread into the returned object.
const transformsFn = ({ root, issue }) => ({
'root.filename': root.filename.replace(
'/home/users/john-doe/workspace/foo-project/src/main/classes/',
''
),
'issue._': `"${issue._.trim()}"`,
...Object.fromEntries(
Object.entries(issue.root).map(
([key, val]) => [`issue.root.${key}`, val]
)
),
});
const json2csvOptions = {
fields: json2csvFields,
quote: '',
header: true,
transforms: [transformsFn],
};

React Select - Default Value from Redux not working

I've data coming from Redux in this format:
[
0: {value: '1.5', label: 'Extra cheese'}
1: {value: '3', label: 'Tomato'}
]
and i try to load them into my react-select.
But it fails, bcs it loads instantly the initialToppings as defaultValue (So it shows me empty Strings as defaultValue). And this Value can never be changed again. But without initialToppings i get nothing at defaultValue bcs redux is to slow and the defaultValue is empty so i can't load it in again later...
const initialToppings = [{ label: '', value: '' }];
const [defaultToppings, setDefaultToppings] = useState(initialToppings);
useEffect(() => {
setDefaultToppings(
editProduct?.selectedToppings?.map((topping, value) => ({
...topping,
value,
})) ?? initialToppings
);
}, [editProduct]);
<Select
options={extraOptions}
formatOptionLabel={formatExtras}
isMulti
defaultValue={defaultToppings}
// defaultValue={[
// { label: 'Test 1', value: '1' },
// { label: 'Test 2', value: '2' },
// ]}
onChange={setSelectedToppings}
/>
You can add key props to Select to force remounting component and make it re-render
<Select
key={defaultToppings}
options={extraOptions}
formatOptionLabel={formatExtras}
isMulti
defaultValue={defaultToppings}
// defaultValue={[
// { label: 'Test 1', value: '1' },
// { label: 'Test 2', value: '2' },
// ]}
onChange={setSelectedToppings}
/>
I've a simple codesandbox, you can check it

how can i handle my json elements

Here is my json file
{
id: '81224112234234222223422229',
type: 'message',
message: 'vacation',
attachments: [
{
type: 'template',
elements: [
{
id: '123123123123123',
title: 'job',
text: 'job',
properties: {
code: 'IO002',
value: 'messenger/IO001,messenger2(IO)/IO002,messenger3(IO)/IO003'
}
},
{
id: '123123123123123',
title: 'Date',
text: 'date',
properties: {
code: '2017-11-09~2017-11-09',
value: '2017-11-09~2017-11-09'
}
},
{
id: '123123123123123',
title: 'Sequence',
text: 'sequence',
properties: {
code: '1',
value: '1process/1,2process/1,3process/1'
}
}
]
}
],
module: 'temp'
}
i am using react.js and i want to extract all properties
result
job code: I0002
job value:messenger/IO001,messenger2(IO)/IO002,messenger3(IO)/IO003
date code:2017-11-09~2017-11-09
date value:2017-11-09~2017-11-09
sequence code:1
sequence value:1process/1,2process/1,3process/1
i tried to execute like this
const job=elements.filter(x=>x.text==='job');
const date=elements.filter(x=>x.text==='date');
const sequence=elements.filter(x=>x.text==='sequence');
is it proper way to use filter or another way to extract data from json file?
i am new to react.js and es6,javascript.so i have no idea to display each property.
how can i solve my problem? pz give me a tip.i want to extract properties
You can use
var yourobject=JSON.parse(jsondata);
const job=yourobject.job;

AngularJS nested ng-repeat access $parent array element

Right so I have a dilemma, that seems like a simple question but I can't figure it out.
I have a nested array:
$scope.rootItem = {
id: '1',
type: 'course',
title: 'Adobe Photoshop CC for beginners',
items: [{
id: '2',
type: 'label',
title:'Label Title',
items:[{
id: '3',
type: 'module',
title:'Module title',
items: [{
id: '4',
type: 'topic',
title:'Topic title',
items: [{
id: '5',
type: 'content',
title:'Content title'
}, {
id: '6',
type: 'content',
title:'Content title'
}]
}]
},{
id: '7',
type: 'resources',
title:'Resources'
},{
id: '8',
type: 'module',
title:'Module title',
items: [{
id: '9',
type: 'topic',
title:'Topic',
items: [{
id: '10',
type: 'question',
title:'Question title'
}]
}, {
id: '11',
type: 'topic',
title:'Topic title',
items: [{
id: '12',
type: 'content',
title:'Content title'
}]
}]
}]
},{
id: '14',
type: 'assessmentLabel',
title: 'Assessment Label',
items: [{
id: '15',
type: 'assessment',
title: 'Assessment Title',
items: [{
id: '16',
type: 'courseAssessment',
title: 'Course Assessment Question',
items: []
}]
}]
}]
};
That is outputted using ng-repeat. All works great there, by the way it is also sortable using ng-sortable (based on JQuery UI Sortable).
What I'm trying to do is duplicate lets say id: 5 using angular.copy().
HTML:
<a href="" title="Duplicate Content" data-ng-click="duplicate(ngModelItem, $parent.ngModelItem.items)">
<span class="icon-duplicate"></span>
</a>
That seems to work fine too. I'm able to pass the object to the function.
The problem arises when I try and push that object to its parents array. I read about $parent and what I think would make sense is passing $parent.ngModelItems.items to the ng-click as such:
data-ng-click="duplicate(ngModelItem, $parent.ngModelItem.items)"
Which to me makes sense, pass parents ngModelItem.items (items is array that ID:5 is part of). But I can't figure out why do I get $parent.ngModelItem.items as undefined.
This is my controller:
$scope.duplicate = function(item, parent) {
var itemCopy = angular.copy(item);
parent.push(item);
};
HTML ng-repeat:
<ul class="apps-container" ui-sortable="sortableOptions" ng-model="ngModelItem.items" ng-class="ngModelItem.type">
<li class="innerCont" ng-repeat="innerItem in ngModelItem.items">
<tg-dynamic-directive ng-model="innerItem" tg-dynamic-directive-view="getView">
</tg-dynamic-directive>
</li>
</ul>
But angular seems to have different ideas. So I guess my question is how can I pass parents ngModelItem.items (rootItem.items) so that I can access that array?
Can someone please explain why {{$parent.$parent.ngModelItems.id}} returns correct parent id. Yet when I try to pass that parent to the function such as
data-ng-click="duplicate(parent.parent.ngModelItem.items)"
It doesnt work
Directive below:
angular.module('tg.dynamicDirective', [])
.directive('tgDynamicDirective', ['$compile',
function($compile) {
'use strict';
function templateUrlProvider(getView, ngModelItem) {
if (getView) {
if (typeof getView === 'function') {
var templateUrl = getView(ngModelItem) || '';
if (templateUrl) {
return templateUrl;
}
} else if (typeof getView === 'string' && getView.length) {
return getView;
}
}
return '';
}
return {
restrict: 'E',
require: '^ngModel',
scope: true,
template: '<div ng-include="templateUrl"></div>',
link: function(scope, element, attrs, ngModel) {
scope.$watch(function() {
var ngModelItem = scope.$eval(attrs.ngModel);
var getView = scope.$eval(attrs.tgDynamicDirectiveView);
scope.ngModelItem = ngModelItem;
return templateUrlProvider(getView, ngModelItem);
}, function(newValue, oldValue) {
scope.templateUrl = newValue;
});
}
};
}
]);
After few hours of trying to fix this, and reading numerous articles about $scope inheritance I found out that ng-if create new scope using prototypical inheritance. Which I was not accounting for.
Which required me to insert one more $parent when passing it to the function as such:
data-ng-click="duplicate(ngModelItem, $parent.$parent.$parent.ngModelItem)"
and then in the controller do something like this:
$scope.duplicate = function(item, parent) {
var itemCopy = angular.copy(item);
var parentArray = parent.items;
parentArray.push(itemCopy)
};
Hope this will save someone hours of work, whoever runs into this problem.

Access and chart through perl arrays

I am trying to write code this way in perl.
\$('#AmpCovPlot').highcharts({
var amp_name = new Array[$amp];
var amp_cov = new Array[$cov]
chart: {
type: 'line'
},
title: {
text: 'Average cov'
},
xAxis: {
categories: [amp_name]
},
yAxis: {
title: {
text: 'Amp name'
}
},
series: [{
name: [amp_name]
data: [amp_cov]
}]
});
so $amp and $cov are perl variables containing array elements, generated by statement :
my $Cov=join(",",#cov);
And I am getting "Uncaught SyntaxError: Unexpected Identifier". I know I am doing a blunder, and I am new to javascript.
Can somebody let me know how to fix this?
Thanks!!!
"Unexpected Identifier" is a hint for invalid Javascript. In your case, i think you print the Javascript Code without double quotes qq{}, to be more precise: You print a $ where no $ is allowed or you dont print a $ where a $ is expected.
When you just Copy + Pasted your Javascript code, you have a syntax Error as well:
var amp_cov = new Array[$cov] // no semicolon ;
// what is the following part for? you dont really assign that stuff to
// something .... seems wrong
chart: {
type: 'line'
},
title: {
text: 'Average cov'
},
xAxis: {
categories: [amp_name]
},
yAxis: {
title: {
text: 'Amp name'
}
},
series: [{
name: [amp_name]
data: [amp_cov]
}]
The next part is the join of the Perl Array. You need to quote the Variables inside the Javascript as well:
var array = ['a','b','c'];
So your join need to be something like:
my $cov = join q{,}, map {qq{'$_'}} #cov;
Which just mean, that you first add single quotes to each element in #cov and then join all with ,
You are defining variables inside object, which is not proper for JS:
$('#AmpCovPlot').highcharts({
var amp_name = new Array[$amp]; // not here!
var amp_cov = new Array[$cov] // not here!
chart: {
type: 'line'
},
title: {
text: 'Average cov'
},
xAxis: {
categories: [amp_name]
},
yAxis: {
title: {
text: 'Amp name'
}
},
series: [{
name: [amp_name]
data: [amp_cov]
}]
});
This should be done this way:
var amp_name = new Array[$amp]; // here define variables
var amp_cov = new Array[$cov]; // here define variables
$('#AmpCovPlot').highcharts({ ... }); // and create chart

Categories