React Select - Default Value from Redux not working - javascript

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

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],
};

TypeError: Cannot read property 'indexOf' of null vuejs on consecutive v-fors

I am having this issue for hours now. I am rendering items on <options> for my <select> element using vuejs' v-for and when it rendered it gave me the type error. I tried changing my :key values but still having the same error and won't render the items that I needed.
Where did I make a mistake?
Code below:
This is my first <select> tag:
<vs-select placeholder="Gender"
v-model="gender"
color="#ffc640"
class="col-span-2 mt-2 z-0"
>
<vs-option v-for="(gender, index) in $store.state.genders"
:key="`${index}_gender`"
:label="gender.label" :value="gender.name">
{{ gender.label }}
</vs-option>
</vs-select>
Here is the next <select> tag:
<vs-select placeholder="Attainment"
v-model="attainment"
color="#ffc640"
class="col-span-2 mt-2 z-0"
>
<vs-option v-for="(attainment, index) in $store.state.attainment"
:key="`${index}_attainment`"
:label="attainment.label" :value="attainment.name">
{{ attainment.label }}
</vs-option>
</vs-select>
Here is the error:
For context, here are the objects
genders: [
{
name: 'male',
label: 'Man',
value: '1-male',
},
{
name: 'female',
label: 'Woman',
value: '2-female',
},
{
name: 'lgbtq',
label: 'Transgender',
value: '3-lgbtq',
},
{
name: 'nottosay',
label: 'Prefer not to say',
value: '4-nottosay',
},
],
attainment: [
{
name: 'high_school',
label: 'High School',
value: 'high_school',
},
{
name: 'senior_high_school',
label: 'Senior High School',
value: 'senior_high_school',
},
{
name: 'associate',
label: 'Associate',
value: 'associate',
},
{
name: 'bachelor',
label: 'Bachelor',
value: 'bachelor',
},
{
name: 'master',
label: 'Master',
value: 'master',
},
{
name: 'doctorate',
label: 'Doctorate',
value: 'doctorate',
},
],
Here are my computed values:
attainment: {
get() {
return this.$store.state.user.attainment;
},
set(value) {
this.$store.commit('setAttainment', value);
},
},
gender: {
get() {
return this.$store.state.user.gender;
},
set(value) {
this.$store.commit('setGender', value);
},
},
Computed are functions that return a value according to the state. You cannot use them in v-model directives (but ': value' is correct). Reading the store state is prohibited also, you should use getters.
Your code can be something like this (remove computeds):
<vs-select placeholder="Gender"
:value="$store.state.user.gender"
#input="$store.commit('setGender', $event)"
color="#ffc640"
class="col-span-2 mt-2 z-0"
>
<vs-option v-for="(gender, index) in $store.state.genders"
:key="`${index}_gender`"
:label="gender.label" :value="gender.name">
{{ gender.label }}
</vs-option>
</vs-select>
Anyway, it is not clean. Revise your store to use getters, listen to #input, and commit data changes.

onClick overrides Semantic UI's dropdown

Dropdown functions normally until I add onClick(). I guess Semantic UI has some built in functions for onClick() so when I call it, the item does not show up as selected choice with the option to "x" out.
onChange() does not work.
class Wines extends Component {
state = {
wines: [],
list: []
};
handleDropdown = (event, {value}) => {
this.setState({ list: value})
console.log(value)
}
render() {
const options = [
{ key: 'France', text: 'France', value: 'France', onClick: this.handleDropdown },
{ key: 'Spain', text: 'Spain', value: 'Spain'},
{ key: 'Portugal', text: 'Portugal', value: 'Portugal' }
]
return (
<Dropdown placeholder='Countries' fluid multiple selection options={options} />
)
}
}
export default Wines;
More likely than not, it is working as intended. I checked the docs of the Semantic UI dropdown here. It doesn't do anything in that regard for you in a magic-y way.
One issue is that you aren't building a list inside your click handler. You just keep replacing the value you just clicked on. You need to build on top each time
setState({ list: [...this.state.list, value] })
As mentioned before, it doesn't do any magic for you, so you have to modify the props yourself, based on the items that you have placed in this.state.list. I suggest mapping over the array again, so you don't have to repeatedly hard code the equality check for every entry.
const options = [
{ key: 'France', text: 'France', value: 'France', onClick: this.handleDropdown },
{ key: 'Spain', text: 'Spain', value: 'Spain'},
{ key: 'Portugal', text: 'Portugal', value: 'Portugal' }
]
const optionsToRender = options.map(dropdownEntry => {
if (this.state.list.includes(dropdownEntry.value)) {
dropdownEntry.somePropYouWantToChange = 'some value you want to assign it to'
}
return dropdownEntry
})
<Dropdown placeholder='Countries' fluid multiple selection options={optionsToRender} />

How to apply filter and show/hide columns in React Table - React

I am working on React Table. I am basically a beginner in React. I have a dashboard page where I display a React Table of 8 columns. I have a customize button which will open a popup page, this popup page has 8 check boxes allows me to show/hide those React columns. Initially all the check boxes in this popup page is set to true. When I uncheck a column that particular column get disabled.
The first image only has columns (no sub columns are there but in real life I will have to use sub columns) . Also in the 1st image there are 8 check boxes. It is 10 in real life. The 2nd image basically shows the basic columns. I am basically telling you as this images do not 100% correlate to my functionality. It shows a basic idea
This is my column data (total 8 columns, column 1 to 5 and column 7 has one sub column while column 6 & column 8 has multiple sub columns)
I need to apply show/hide filter on the level 1 header (super header) and level 2 headers of column 1 to 5. Column 6 to 8 are always visible.
It is to be noted that I have a constant file in my project. Whenever I use the global constants of that file in other components I import it.
It should be mentioned that React Table has a property called show (default value is true but we can hide a column by setting it false)
const Constants = {
columnShowHide: [
{ id: 1, value: true },
{ id: 2, value: true },
{ id: 3, value: true },
{ id: 4, value: true },
{ id: 5, value: true },
{ id: 6, value: true },
{ id: 7, value: true },
{ id: 8, value: true },
{ id: 9, value: true },
{ id: 10, value: true },
]
};
export { Constants as default };
This is the code for the popup page for checkbox
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { ActionCreators } from '../../../actions';
import ButtonComponent from '../../common/button/ButtonComponent';
import { CheckBox } from '../../common/chkbox/CheckBox';
import Constants from '../../../util/constants';
class CustomizedView extends Component {
constructor(props) {
super(props);
this.handleCheckChildElement = this.handleCheckChildElement.bind(this);
this.state = {
items: [
{ id: 1, value: 'Sub Column 1', isChecked: true },
{ id: 2, value: 'Super Column 1', isChecked: true },
{ id: 3, value: 'Sub Column 2', isChecked: true },
{ id: 4, value: 'Super Column 2', isChecked: true },
{ id: 5, value: 'Column 5', isChecked: true },
{ id: 6, value: 'Column 6', isChecked: true },
{ id: 7, value: 'Column 7', isChecked: true },
{ id: 8, value: 'Column 8', isChecked: true },
{ id: 9, value: 'Column 7', isChecked: true },
{ id: 10, value: 'Column 8', isChecked: true },
]
};
}
handleClick() {
this.setState({ isChecked: !this.state.isChecked });
}
handleCheckChildElement(event) {
const { items } = this.state; //extract state values like this to a const variable
const newItems = items.map((item) => { //do map on items because map returns a new array. It’s good practice to use .map than forEach in your case
if(item.value === event.target.value) {
item.isChecked = event.target.checked;
return item; //return updated item object so that it will be pushed to the newItems array
}
return item; // return item because you need this item object as well
});
this.setState({ items: newItems }); //finally set newItems array into items
Constants.columnShowHide[0].value = items[0].isChecked;
Constants.columnShowHide[1].value = items[1].isChecked;
Constants.columnShowHide[2].value = items[2].isChecked;
Constants.columnShowHide[3].value = items[3].isChecked;
Constants.columnShowHide[4].value = items[4].isChecked;
Constants.columnShowHide[5].value = items[5].isChecked;
Constants.columnShowHide[6].value = items[6].isChecked;
Constants.columnShowHide[7].value = items[7].isChecked;
console.log('From constant file after ' + JSON.stringify(Constants.columnShowHide));
}
render() {
return (
<div className='div-container-custom' >
<div className='bottomBar'>
<ButtonComponent
text='Apply'
className='activeButton filterMargin-custom'
width='100'
display='inline-block'
onClick={() => { this.props.applyFilter(this.state, false); }}
/>
<ButtonComponent
text='Clear Filter'
className='greyedButton clear-custom-filter'
width='100'
display='block'
marginTop='60'
onClick={() => { this.props.clearFilter(this.state, true); }}
/>
</div>
<div>
<div className='data-points-text'>
<span> Columns </span>
</div>
<div className="App">
<ul>
{
this.state.items.map((item, i) => {
return (<div key={i} ><CheckBox handleCheckChildElement={this.handleCheckChildElement} {...item} /></div>);
})
};
</ul>
</div>
</div>
</div>
);
}
}
CustomizedView.propTypes = {
applyFilter: PropTypes.func.isRequired
};
CustomizedView.defaultProps = {
};
function mapStateToProps(state) {
return {
auth: state.auth
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(ActionCreators, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(CustomizedView);
Now I need to use the constant to moduify my ReactTableComponent
This is my column data in React Table component
const columns = [
{
Header: 'Column 1',
columns: [
{
Header: 'S Column 1',
accessor: 'firstName',
show : some_var (if this is true,column/sub column in shown, else hidden )
}
]
},
{
Header: 'Column 2',
columns: [
{
Header: 'S Column 2',
accessor: 'firstName'
}
]
},
{
Header: 'Column 3',
columns: [
{
Header: 'S Column 3',
accessor: 'firstName'
}
]
},
{
Header: 'Column 4',
columns: [
{
Header: 'S column 4',
accessor: 'firstName'
}
]
},
{
Header: 'Column 5',
columns: [
{
Header: 'S column 5',
accessor: 'firstName'
}
]
},
{
Header: 'Column 6',
columns: [
{
Header: 'S column 6a',
accessor: 'firstName'
},
{
Header: 'S column 6b',
accessor: 'firstName'
},
{
Header: 'S column 6c',
accessor: 'firstName'
},
{
Header: 'S column 6d',
accessor: 'firstName'
}
]
},
{
Header: 'Column 7',
columns: [
{
Header: 'S column 7',
accessor: 'firstName'
}
]
},
{
Header: 'Column 8',
columns: [
{
Header: 'S Column 8a',
accessor: 'firstName'
},
{
Header: 'S Column 8b',
accessor: 'firstName'
},
{
Header: 'S Column 8c',
accessor: 'firstName'
},
{
Header: 'S Column 8d',
accessor: 'firstName'
}
]
},
];
Now I have the 10 boolean flags in Constants.js which I can import in any component. It is available across the project. I have checked by consoling.
Initially all the flags are true so when the checkbox popup page opens, so when I uncheck and press apply button that particular columns/sub columns will be hidden.
The checkbox values can be brought to initial state by clearFilters function. All columns and sub columns should show after clearFilter
Now since I am complete beginner In React, what should I write in the function of Apply and clear button to implement my desired idea. I have some incorrect functions. Also after pressing applyFilter/clearFilter I need to update the global constants and use them in ReactTableComponent to use the show property of ReactTable to show/hide columns/sub columns.
I am not using Redux or any complex things. I have a working constants file and I want to use that to implement this. Kindly help me in achieving this

Json format output

I am new to development, and learning angular 2 and node. Now working on a project with API integration and in the code below. I am sending all JSON data to array, I tried using JSON.stringify but did not get the desired output. And I need this kind of output:
Area = [
{ value: '3', label: 'sports' },
{ value: '4', label: 'fest' },
{ value: '5', label: 'music' }
];
My ts code is like this
var Area = [];
area=> {
console.log(departments);
area.map(function(areas) {
var array = {"value":area._id,"label":area.areaFor};
Area.push(array);
})
console.log(Area);
},
error => {
console.log(error);
});
but i am getting this output in console
label
"sports"
value
2
label
"fest"
value
3
label
"music"
value
5
You can try this, I changed area to areas inside map function.
area = [
{ value: '3', label: 'sports' },
{ value: '4', label: 'fest' },
{ value: '5', label: 'music' }
];
constructor() {
var Area = [];
Area = this.area.map(function(areas) {
return {"value":areas.value,"label":areas.label};
})
console.log(Area);
}

Categories