Can I pass object of data in select option - reactjs

Can I pass object of data in select option ?
I'm displaying name in select option & I'm using ID in value.
After some option is selected, I want to display the selected option. Since the value is ID, I can't display name.
How can I solve this?
This is my code:
{
Makes.hasData ?
(_.map(Makes.data.data, (make, index) => {
return (
<option key={index} value={make.id}> {make.make}</option>
);
}))
: ''
}
Thank You

On your select option you will have onChange in that you can search in the array for the obejct with a given id using lodash's find method
handleChange(e) {
var id=e.target.value
var value = _.result(_.find(Makes.data.data, function(obj) {
return obj.id=== id;
}), 'make');
console.log(value)
}

Related

Filter table with select options (check if column is number or null) in React

I am new at React and I am stuck.
I have a table with data from database. I want to filter that table with a select dropdown. I have mulitple "select-fields" that works fine, because the value in the dropdown matches the exact value in database. But now I just want to check if the column value is null or a number.
In my select options I just want three options (see left picture):
All (Show all result. It is working)
Missing number(is null in Database. Not working)
Has number(Not working)
So the value in the table column (see right picture) I want to filter is either a number or null.
Here is my code so far:
const [filteredData, setFilteredData] = useState([]);
//Column in table:
{
Header: () => (<div>TableHead</div>),
accessor: "accessorToDatabase",
Cell: (props) => { return <div>{props?.cell?.value}</div> }
}
// The select dropdown and the table
<Col>
<Label>Select Dropbox</Label>
<Input type="select" onChange={handleChange('id', 'description')}>
<option>All</option>
<option value="false">Missing number</option>
<option value="true">Has number</option>
</Input>
</Col>
<Table columns={columns} data={filteredData} HandleRowData={HandleRowData} />
//The filter functions
const handleChange = name => ({ target: { value } }) => {
filter[name] = (value === 'All') ? null : value
if (checkProperties(filter)) {
var filtered = state
}
else {
var filtered = handleFilter(state, filter)
}
setFilteredData(filtered)
}
const handleFilter = (arr: Object[], filters: Object) => {
const filterKeys = Object.keys(filters)
return arr.filter(eachObj => {
return filterKeys.every(eachKey => {
if (!filters[eachKey] || !filters[eachKey].length) {
return true
}
})
})
}
I have tried with something like this, for looping through all values in the column, but without no success:
state.map(x=>((
x.id> 0 ? x.id : null)))
.map is used to transform one array of values/objects to another array with the same length but with transformed values/objects. What you want to use is .filter, which removes elements from an array but maintain the element structure.
To keep the ones that does not have an id:
array.filter(x => !x.id)
To keep the ones that has an id that is a number:
array.filter(x => !isNaN(x.id))
A simple Array.prototype.filter should do the trick:
//removes all entries with an id of `0 || null || undefined`
state.filter(entry=>!!entry.id)
//removes all entries with an id of `null || undefined` but keeps the 0
state.filter(entry=>!!entry.id || entry.id === 0)
I would not recommend using isNan: as it internally tries to parse strings to check if they are numbers you might end up with some unexpected behaviors. It also goes wild with booleans, null and undefined.
See this link for more info:
https://www.w3schools.com/jsref/jsref_isnan.asp
EDIT
Rereading your question it looks like you want
all items
items with an ID of type number
items that are not numbers
Here is how you could implement that
const [items,setItems]= useState(someItems)
const [filter, setFilter]=useState('all')
function handleChange(e){
setFilter(e.target.value)
}
const filteredItems = items.filter(item=>{
if(filter === 'number')
return typeof items === 'number'
if(filter === 'no-number')
return typeof item !== 'number'
return true
})
return (
<React.Fragment>
<select onChange={handleChange}>
<option value='all'>All</option>
<option value='no-number'>Missing number</option>
<option value="number">Has number</option>
</select>
<Table columns={columns} data={filteredData} HandleRowData={HandleRowData} />
</React.Fragment>
)
Change the elements with the specific library you are using and you are good to go
I would recommend not using NaN, as it tries to parse strings. Instead, you can create an array and use the map function, in combination with the filter function.

display array values into select option tag in react js

I am trying to display array values into select tag, but all the array values displayed as single value. Please see below logic I added. Data is dynamic, I am getting data from backend like this ["Sankranti", "Sankranti 1"].
const [eventNameList, setEventNameList] = useState([])
var eventList = eventNameList.length > 0 ?
eventNameList.map((item,i) => {
console.log('list: ', item)
return (
<option>{item}</option>
)
})
:
'No Events'
<select>
{eventList}
</select>
please find below console screen shot
It looks that your list is nested inside another array so to fix this you could use flatMap instead of map
or you could just iterate throw the first element inside your nested array
const [eventNameList, setEventNameList] = useState([])
var eventList = eventNameList.length > 0 ?
eventNameList[0].map((item,i) => {
console.log('list: ', item)
return (
<option>{item}</option>
)
})
:
'No Events'
<select>
{eventList}
</select>

Primereact datatable: filter null values or template values

I have a datatable in primereact with a list of customers which has a column validTo which returns a date or null. I want to filter all valid customers, so I would filter for equals null, but that doesn't work because null resets the filter.
Second Option would be to replace null with something like "-" in a template, but how do I filter the value returned by the template, as it seems, that datatable only filters the source data?
Update 1:
I got a bit further.
my column looks like this
<Column
field="giltbis"
header="giltbis"
filter={true}
filterElement={giltbisFilterElement}
filterMatchMode="custom"
filterFunction={filterGiltbis}
sortable={true}
body={dateTemplate_giltbis}
/>
And here is my filter setup:
const handleFilterClick = (value) => {
setgiltbisSelected(value);
dt.current.filter(value, "giltbis", "custom");
};
const filterGiltbis = (value) => {
if (giltbisSelected === "Gültig") {
return value == null;
} else if (giltbisSelected === "Ungültig") {
return value != null;
} else {
//how to cancel filter or show all values
}
};
const giltbisFilterElement = (
<SelectButton
style={{ width: "100%" }}
value={giltbisSelected}
options={giltbisoptions}
onChange={(e) => handleFilterClick(e.value)}
/>
);
So only one problem left. How to I cancel the filtering or show all values?
You need to implement a custom filter function. Here is an example
filterMatchMode="custom" filterFunction={customFunction}
export const customFunction = (value, filter) => {
return value.toUpperCase().indexOf(filter.toUpperCase()) >= 0
}

How can I combine these custom filters?

Im trying to create a filter mechanism using this code, which works perfectly (independently):
// Report Filtering
$scope.filter = {};
$scope.getCategories = function () {
return ($rootScope.reportsData || []).map(function (report) {
return report.type;
}).filter(function (report, idx, arr) {
return arr.indexOf(report) === idx;
});
};
$scope.getPackages = function () {
return ($rootScope.reportsData || []).map(function (report) {
return report.package;
}).filter(function (report, idx, arr) {
return arr.indexOf(report) === idx;
});
};
$scope.filterByCategory = function (reportsData) {
return $scope.filter[reportsData.type] || noFilter($scope.filter);
};
$scope.filterByPackage = function (reportsData) {
return $scope.filter[reportsData.package] || noFilter($scope.filter);
};
function noFilter(filterObj) {
for (var key in filterObj) {
if (filterObj[key]) {
return false;
}
}
return true;
}
and the ng-repeat is:
ng-repeat="item in filtered=(reportsData | filter:filterByPackage)"
This works perfectly if I replace filter: with either filterByPackage or filterByCategory.
Im using this code to iterate through the keys and create checkboxes to toggle the visibility of the items:
<label ng-repeat="cat in getCategories()">
<input type="checkbox" ng-model="filter[cat]" />{{cat}}</label>
However, I would like to use these both in conjunction. If i modify my inline code on the ng-repeat to:
ng-repeat="item in filtered=(reportsData | filter:filterByPackage | filter:filterByCategory)"
then clicking on checkbox makes the entire list disappear. What is the syntax to properly combine these two filters?
If you select a category and a package you only want to display the reportData that matches with both?
The problem you are having is that you are using your "filter" object for both types of filtering and this in combination with your noFilter function that also verifies if anything is checked on the filter is causing that you need to select both a package and category exactly matching the reportData for it to be displayed (you cannot leave a filter unselected or it doesn't display any).
What you can do is initialize your filter as an object in which each criteria is a member, and utilize them as so:
$scope.filter = { packages: {}, categories: {}};
return $scope.filter.categories[reportsData.type] || noFilter($scope.filter.categories);
<label ng-repeat="cat in getCategories()">
<input type="checkbox" ng-model="filter.categories[cat]" />{{cat}}
</label>

AngularJS/Bootstrap - DataTables - Turn off certain dropdown filters in footer

Is it possible to turn off certain dropdown filters in the footer? This is the API I'm using: https://datatables.net/examples/api/multi_filter_select.html
I don't want all columns to be filterable. Also, is it possible to have the header labels be the default in the dropdown instead of a blank?
Here is my live example: http://live.datatables.net/cufawibi/3/
A usual approach is to use a css class to filter which columns can be filterable.
You could also add the column name as selected and disabled in order to display it as the default (included an all values options to disable the filter).
initComplete: function () {
var api = this.api();
api.columns('.filtersearch').indexes().flatten().each( function ( i ) {
var column = api.column( i );
var select = $('<select></select>')
.appendTo( $(column.footer()).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
select.append('<option selected disabled>"'+$(column.header()).text()+'"</option>');
select.append('<option value="">All values</option>');
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' );
} );
} );
}
UPDATE:
In order to have the class added from the controller, changed also the table head definition to
<th ng-repeat="(i, th) in head" value="{{th.id}}" class="{{th.class}}"><span>{{th.name}}</span></th>
Live example (filter only for the "Payload" column, add filtersearch class to other columns to enable filtering)
I don't think there's a clean way to do this via the API. So this solution will be hacky.
So you'd wrap your logic around an IF block to filter out the columns dropdown filters you don't want to display.
api.columns().indexes().flatten().each(function (index) {
var column, select;
// You don't want to display the first and the fourth dropdown filter
if (index !== 0 || index !== 3) {
column = api.column(i);
select = $('<select><option value=""></option></select>')
.appendTo($(column.footer()).empty())
.on('change', function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
column.search(val ? '^' + val + '$' : '', true, false).draw();
});
column.data().unique().sort().each(function (d, j) {
select.append('<option value="' + d + '">' + d + '</option>')
});
}
});

Resources