How to handle multiple options with isMulti in react-select - reactjs

I am trying to make a select, where I can select different cities and filter out the ones not from the selected cities, my filter seem to work, but I can't select more than one city even tho I have set isMulti on Select I have also tried isMulti={true} but it does not work, I think it is my handler that doesn't work:
handleChange (selectedOptions) {
selectedOptions.map(o => this.setState({by: o.value.value}))
//var options = selectedOptions.value;
/*var value = [];
for (var i = 0, l = options.length; i < l; i++) {
if (options[i].selected) {
value.push(options[i].value);
}
}*/
console.log(selectedOptions)
}
the one commented out does not work either but it did work with html tag select.
this is my filter:
const filteredUsers = (usersGet.filter(item => {
const checkHairColor = () => {
if(Array.isArray(haircolor)) {
return haircolor.length > 0 ? haircolor.includes(item.haircolor) : true;
} else {
return (haircolor === '') || (haircolor === item.haircolor);
}
}
const checkCity = () => {
if(Array.isArray(city)) {
return city.length > 0 ? by.includes(item.city) : true;
} else {
return (city === '') || (city === item.city);
}
}
const filter = (item.navn.toLowerCase().includes(searchfield.toLowerCase()) ||
item.navn.toLowerCase().includes(searchfield.toLowerCase()) === '')
&& (item.age > minage || minage === '')
&& (item.age < maxage || maxage === '')
&& checkHairColor()
&& checkCity();
console.log(filter);
return filter
}))
But my filter I'm pretty sure works, but not for sure since I haven't gotten an array to send to the filter yet.
<Select
isMulti={true}
hideSelectedOptions={false}
closeMenuOnSelect={false}
isSearchable={true}
name="by"
value={selectedOptions}
onChange={this.handleChange}
options={byer}
/>
https://stackblitz.com/edit/react-fntxzp?file=index.js

The problem with select was, that you did not updated the state correctly. If you are updating state in react, you should provide a brand new object. And update just the part you need to change.
https://stackblitz.com/edit/react-uygysb?file=index.js

Related

How can i make an optional field?

I am making a Checkout form but i dont know how can i make it optional? I'm new with react js and i badly need help because i have defense some time next week and this is the only problem that i am encountering with the revisions that they have said.
Anyway here it is.
const objChecker = (e, id) => {
const hasEmpty = Object.values(orderInfo).some(x => x == '' );
console.log(Object.values(orderInfo), hasEmpty, id)
if(hasEmpty){
window.alert('Please input all fields')
return false
} else {
console.log(e, 'e')
setOrderInfo({ ...orderInfo, payment_id: id })
}
}
<div className='checkout_modal_payment_method_wrap'>
{paymentMethods.length > 0 && paymentMethods.map(method => (
<label htmlFor={`payment_method_${method.id}`} key={method.id} className='checkout_modal_payment_method_item'
style={{display: method.id === 1 && product.category_id === 2 && 'none'}}>
<input type='radio' id={`payment_method_${method.id}`} name='payment_id' value={method.id} onChange={(e) => objChecker(e, method.id)} required checked={payment_id === method.id}/>
<div>
{method.payment_name}
</div>
The only fields that i want to declare as optional is the ADDRESS LINE 2 and TYPE OF EVENT only. The rest will be required
This is the UI

I want to set checkbox to true based on a condition in ag-grid

I have a button which basically imports some data. This imported data needs to be compared with the data inside already loaded ag-grid and if there is a match, set the cehckbox of that particlar row node to true.
This is the button which checks for the condition:
enableCheck() {
alert('works');
if (this.DataService.isNotBlank(this.rowDataImport)) {
for (let i = 0; i < this.rowDataImport.length; i++) {
if (this.DataService.isNotBlank(this.rowData)) {
for (let j = 0; j < this.rowData.length; j++) {
if (this.DataService.isNotBlank(this.rowData[j].calDate)) {
for (const calDates of this.rowData[j].calDate) {
if (
this.rowDataImport[i].isin === calDates.isin ||
this.rowDataImport[i].portfolioName === calDates.portfolioName ||
this.rowDataImport[i].valuationDate === calDates.valuationDate
)
{
// alert('true')
this.checkValue = true;
} else {
this.checkValue = false;
}
}
}
}
}
}
}
}
The this.checkValue is a flag which will be true if match is found.
public gridColumnDefs = [
{
headerName: 'Portfolio Name',
field: 'portfolioName',
cellRenderer: 'agGroupCellRenderer',
headerCheckboxSelection: true,
headerCheckboxSelectionFilteredOnly: true,
checkboxSelection: true,
pinned: 'left',
filter: true,
cellRendererParams:(params) => {
console.log(params);
if (this.checkValue) {
params.node.selected = true;
}
}
},
]
here I used cellRendererParams. But this will only for on load I guess. What to do if I want to update the ag-grid row from a value outside i.e. from import check as given above?
First of all, you should add id for each row in defaultColDef
this.defaultColDef = {
getRowNodeId: data => data.id,
};
Then you can find this id and set the checkbox to true.
Also, you can find separate field by name.
It is really easy, you should use the next combination
selectRow() {
this.gridApi.forEachNode(node => {
if (node.id == 1 || node.id == 2 || node.data.country == 'Australia') {
node.setSelected(true);
}
});
}
Working example:
https://plnkr.co/edit/ijgg6bXVleOAmNL8
In this example when we click on the button - we set the checkbox to true for two rows with id 1 and 2 and for each field that has country 'Australia'
And in your case, you are using incorrect configuration.
You should you cellRenderer
cellRenderer: params => {
if(params.value === 'Ireland') {
params.node.setSelected(true)
}
return params.value
},
One more example: https://plnkr.co/edit/PcBklnJVT2NsNbm6?preview
I manpulated a bit and did the below which worked like a charm.
this.gridApi.forEachNode(node => {
if (node.data.isin === this.rowDataImport[i].isin &&
node.data.portfolioName === this.rowDataImport[i].portfolioName &&
node.data.valuationDate === this.rowDataImport[i].valuationDate
) {
node.setSelected(true);
}

Filter array of objects on multiple keys

I have a react table that I am trying to filter on multiple columns using a filter function. If i filter on one column its fine but if i add another column it filters only by that and not both.
Example would be the name "Scott". I want to filter the first_name column by it and also the biz_name column by it. But when I check the box to change state for that column, it only filters on one. Here is the checkbox in which I have checked state to make sure it is working correctly.
<Checkbox
label="Business Name"
onCheck={event => {
if (event.target.checked) {
this.setState({
filterBusinessName: true
});
} else {
this.setState({
filterBusinessName: false
});
}
}}
/>
<Checkbox
label="First Name"
onCheck={event => {
if (event.target.checked) {
this.setState({
filterFirstName: true
});
} else {
this.setState({
filterFirstName: false
});
}
}}
/>
And then here is the filter function above the table:
let items = this.state.contacts
if (this.state.term && items.length > 0) {
let searchTerm = this.state.term.toLowerCase()
items = items.filter(row => {
if(this.state.filterBusinessName && row.biz_name){
return row.biz_name.toLowerCase().includes(searchTerm)
}
if(this.state.filterFirstName && row.first_name){
return row.first_name.toLowerCase().includes(searchTerm)
}
if(this.state.filterFirstName && row.first_name && this.state.filterBusinessName && row.biz_name){
return row.first_name.toLowerCase() == searchTerm || row.biz_name.toLowerCase() == searchTerm
}
})
}
I think you want something like this
let items = this.state.contacts;
if (this.state.term && items.length > 0) {
let searchTerm = this.state.term.toLowerCase();
items = items.filter(row => {
if (
this.state.filterBusinessName &&
row.biz_name &&
row.biz_name.toLowerCase().includes(searchTerm)
) {
return true;
}
if (
this.state.filterFirstName &&
row.first_name &&
row.first_name.toLowerCase().includes(searchTerm)
) {
return true;
}
return (
this.state.filterFirstName &&
row.first_name &&
this.state.filterBusinessName &&
row.biz_name &&
(row.first_name.toLowerCase() == searchTerm ||
row.biz_name.toLowerCase() == searchTerm)
);
});
}
The main difference here is that the function will only return false if it doesn't match any. Before it returned false immediately if it didn't match one of the filter checks.
There's definitely some optimisation you can do to make this more comprehensible. But it illustrates the idea. Hope that helps

How to display react numerical props only if they pass from the container?

I have two different containers that call ControlSection component. One pass bestScore prop and the second pass level prop.
In the ControlSection component I want to display the prop in <h2> only if they pass from the container. How can I do it?
const ControlSection = ({ score, bestScore, level }) => {
return (
<div className='controlSection'>
<div className='gameStatistics'>
<h2>Score: {score}</h2>
{bestScore ? <h2>Best: {bestScore}</h2>}
{level ? <h2>Level: {level}</h2>}
</div>
</div>
)
}
The term you're looking for is Conditional Rendering and the standard way to render a component when the prop is defined is by using the && operator.
{bestScore && <h2>Best: {bestScore}</h2>}
The second part, <h2>Best: {bestScore}</h2>, will only be rendered if bestScore is true. (you could use any other condition here)
This is because in JS, undefined, null, 0, '' and NaN are evaluated as false (falsy).
false && <h1>something</h1> will be evaluated as false, therefore it won't be rendered.
Coming back to the bestScore prop, it could also be 0 and evaluated as falsy. You need to take care of that. Something like this could work:
{(bestScore || bestScore === 0) && <h2>Best: {bestScore}</h2>}
What I would do in your case is the following to cover your requirement:
const ControlSection = ({ score, bestScore, level }) => {
return (
<div className='controlSection'>
<div className='gameStatistics'>
<h2>Score: {score}</h2>
{bestScore != null ? <h2>Best: {bestScore}</h2> : null}
{level != null ? <h2>Level: {level}</h2> : null}
</div>
</div>
)
}
By doing bestScore != null the code identifies 2 different things as false which are null and undefined. Please refer to the following code example:
let bestScore = null;
console.log('testing for null value:', bestScore != null);
bestScore = undefined;
console.log('testing for undefined value:', bestScore != null);
bestScore = '';
console.log('testing for \'\' value:', bestScore != null);
bestScore = 0;
console.log('testing for 0 value:', bestScore != null);
In false value case the h2 tag won't be rendered in your component thus you have covered 2 cases where you have either undefined or null value from properties.
To handle 0 and '' values you might want to do the following:
function hasToRender(value) {
if (value === '') {
return false;
} else if (value == 0) {
return true;
} else if (value != null) {
return true;
}
return false;
}
console.log('null', hasToRender(null));
console.log('undefined', hasToRender(undefined));
console.log('\'\'', hasToRender(''));
console.log(0, hasToRender(0));
console.log(17, hasToRender(17));
So I think the working solution would be the following in your case to cover all the cases:
const ControlSection = ({ score, bestScore, level }) => {
function hasToRender(value) {
if (value === '') {
return false;
} else if (value == 0) {
return true;
} else if (value != null) {
return true;
}
return false;
}
return (
<div className='controlSection'>
<div className='gameStatistics'>
<h2>Score: {score}</h2>
{hasToRender(bestScore) ? <h2>Best: {bestScore}</h2> : null}
{hasToRender(level) ? <h2>Level: {level}</h2> : null}
</div>
</div>
)
}
Of course the hasToRender function can be simplified further but this gives you the idea, hope this helps!
{typeof bestScore !== 'undefined' && <h2>Best: {bestScore}</h2>}
or
{typeof level === 'number' && <h2>Level: {level}</h2>}

Can I filter an ng-repeat by more than one item at a time?

I have this ng-repeat:
ng-repeat="row in phs.phrasesView =
(phs.phrases | keywordRange:phs.englishRange )"
Here's the code for the filter:
app.filter('keywordRange', function () {
return function (value, english) {
var out = [];
if (!english) {
return value;
}
var ucEnglish = english[0].toUpperCase() + english.substr(1);
value.map((row: any) => {
if (typeof row.english !== 'undefined' &&
typeof row.english === 'string' &&
row.english != null &&
(row.english.includes(english) || row.english.includes(ucEnglish))
) {
out.push(row);
}
});
return out;
};
});
What I would like to do is to extend this so that rows that contain:
phs.englishRange or phs.romajiRange
Are passed through the filter.
Note that only one of englishRange or romajiRange will be populated. There won't be a case where they both have a value.
Can someone tell me is this possible and give me some advice on how I can do this?

Resources