filter array doesn't work in React component - reactjs

I wanna sort the sizes of my clothes but when I click to elect the size, no matter what I choose, it stays "All"...Is there anything wrong with my function filterProducts?
function Filter(props) {
return (
<div className="filter">
<div className="filter-result">{props.count} Products</div>
<div className="filter-sort">
Order
<select value={props.sort} onChange={props.sortProducts}>
<option value="latest">Latest</option>
<option value="lowest">Lowest</option>
<option value="highest">Highest</option>
</select>
</div>
<div className="filter-size">
Filter
<select value={props.size} onChange={props.filterProducts}>
<option value="">All</option>
<option value="">XS</option>
<option value="">S</option>
<option value="">M</option>
<option value="">L</option>
<option value="">XL</option>
<option value="">XXL</option>
</select>
</div>
</div>
);
}
My codesand link:https://codesandbox.io/s/redux-shop-cart-forked-tlpek?file=/src/App.js

All the size options were missing unique value props, they were all value="".
Update the value props to match your data:
Filter
<select value={props.size} onChange={props.filterProducts}>
<option value="">All</option>
<option value="XS">XS</option>
<option value="S">S</option>
<option value="M">M</option>
<option value="L">L</option>
<option value="XL">XL</option>
<option value="XXL">XXL</option>
</select>
You also had a typo in filterProducts in App where you reset the state to a product property instead of products. This wasn't allowing the "All" filter value to work.
filterProducts = (event) => {
if (event.target.value === "") { // all
this.setState({
size: event.target.value,
products: data.products // <-- reset products!!
});
} else {
this.setState({
size: event.target.value,
products: data.products.filter(
(product) => product.availableSizes.indexOf(event.target.value) >= 0
)
});
}
};

Related

Can you loop through an api endpoint? date data for example

I made a little project that renders a football league of your choice and then the standings for that year plus the overall points won. But now let's say I would like to display in one render the 10-year history of the said league to see who has won the most points. How can I manipulate the endpoint of this API :
https://api-football-standings.azharimm.site/leagues/${selectedLeague}/standings?season=2011
so let's say from 2011 till 2021. What is this process called?
Thank you in advance,
The code is below:
import React, {useState,useEffect} from "react";
import axios from "axios";
import {TailSpin} from "react-loader-spinner";
const Standings = () => {
const [data,setData] = useState([]);
const [loading, setLoading] = useState(false);
const [selectedLeague,setSelectedLeague] = useState('eng.1');
useEffect(()=> {
setLoading(true);
axios(
`https://api-football-standings.azharimm.site/leagues/${selectedLeague}/standings?season=2011`
).then(res=> {
console.log(res.data.data.standings);
setData(res.data.data.standings);
} ).catch(err => console.log(err))
.finally(() => setLoading(false));
},[selectedLeague]);
return (
<div className="standings-container">
<div className="select-container">
<select
name="select-league"
id="select-league"
defaultValue={selectedLeague}
onChange={(e) => setSelectedLeague(e.target.value)}
>
<option value="arg.1">Argentine Liga Profesional de Fútbol</option>
<option value="aus.1">Australian A-League</option>
<option value="bra.1">Brazilian Serie A</option>
<option value="chn.1">Chinese Super League</option>
<option value="ned.1">Dutch Eredivisie</option>
<option value="eng.1">English Premier League</option>
<option value="fra.1">French Ligue 1</option>
<option value="ger.1">German Bundesliga</option>
<option value="idn.1">Indonesian Liga 1</option>
<option value="ita.1">Italian Serie A</option>
<option value="jpn.1">Japanese J League</option>
<option value="mys1">Malaysian Super League</option>
<option value="mex.1">Mexican Liga BBVA MX</option>
<option value="por.1">Portuguese Liga</option>
<option value="rus.1">Russian Premier League</option>
<option value="sgp.1">Singaporean Premier League</option>
<option value="esp.1">Spanish Primera División</option>
<option value="tha.1">Thai Premier League</option>
<option value="tur.1">Turkish Super Lig</option>
<option value="uga.1">Ugandan Super League</option>
</select>
</div>
<div className="standing-results">
{ loading ? <TailSpin color="#00BFFF" height={80} width={80} /> :
data.map((data, index) => (
<div key={data.team.id} className="standing-info">
<h1>
<span>{`${index+1}.`} <img src={data.team.logos[0].href} alt="#"/></span>
{data.team.shortDisplayName}
{JSON.stringify(data.stats[6].value)}
</h1>
</div>
))
}
</div>
</div>
);
};
export default Standings;

Why I can't get the right state when I try to console log inside on my onchange handler?

I have problem regarding on getting all the state inside of my HandlerInputChange the data already updated into 10 data however when I console it log inside of my handler it shows the default array value which is 5.
Question: How to get the all the state data inside of my handler?
Goal: To get all the state on my handler
Logs:
My UseState:
const [data, setData] = useState(defaultArray)
My Handler:
useEffect(() => {
console.log("data" , data)
}, [data])
const handleInputChange = (e, i) => {
const { name, value } = e.target;
const list = [...data];
console.log(list);
}
Add Rows Function:
const AddRows = () => {
//loop here the keys listed
let initialKey = 0;
const x = data.slice(-1);
initialKey = parseInt(x[0]['key']);
let newArr=[...Array(5)].map((_,i)=>{
let val=i + 1 +initialKey;
return {
key: ""+val+"",
customer: <select className="form-control" name="customer" onChange={(e,i) => handleInputChange(e,val)}>
<option disabled selected>Select Customer</option>
<option >LEXI INC / joseph</option>
<option >LEXI INC / james</option>
<option >LEXI INC / charlie</option>
<option >LEXI INC / pam</option>
<option >LEXI INC / regorio</option>
</select>,
bank: <select className="form-control" name="bank" onChange={(e,i) => handleInputChange(e,val)}>
<option disabled selected>Select Bank</option>
<option >BDO</option>
<option >MAY BANK</option>
<option >EAST WEST BANK</option>
<option >UNION BANK</option>
<option >BPI</option>
</select>,
branch: <input className="form-control" placeholder="Branch" name="branch" onChange={(e,i) => handleInputChange(e,val)}/>,
checkNo: <input type="number" className="form-control" name="checkNo" placeholder="Check No." onChange={(e,i) => handleInputChange(e,val)}/>,
checkDate: <input type="date" name="checkDate" className="form-control" onChange={(e,i) => handleInputChange(e,val)}/>,
amount: <input
name="amount"
className="form-control"
placeholder="Amount"
onChange={(e,i) => handleInputChange(e,val)}
/>,
remarks: <select className="form-control" name="remarks" onChange={(e,i) => handleInputChange(e,val)}>
<option disabled selected>Select Remarks</option>
<option >Test</option>
</select>
}
});
setData([...data, ...newArr]);
}
Button:
<button type="submit" class="btn btn-danger" onClick={() => AddRows()}>Add Row</button>
Your handleInputChange is not the problem. Normally, it will be return an array with 10 elements like the variable defaultArray.
perhaps the problem is line 1 and 3

Select all option in materialize multi select

Bootstrap multisleect has option for select all (for example here). Is this possible in materialize multi select?
Here is a smaller version: https://codepen.io/souvik1809/pen/rvNMyO
HTML
<div class = "row">
<label>Materialize Multi Select</label>
<select multiple class="select_all">
<option value="" disabled selected>Choose your option</option>
<option value = "1">Mango</option>
<option value = "24">Orange</option>
<option value = "3">Apple</option>
<option value = "4">Cucumber</option>
<option value = "5">Litchi</option>
</select>
</div>
JavaScript
$(document).ready(function() {
// $('select').val([1]);
$('select').formSelect();
$('select.select_all').siblings('ul').prepend('<li id=sm_select_all><span>Select All</span></li>');
$('li#sm_select_all').on('click', function () {
var jq_elem = $(this),
jq_elem_span = jq_elem.find('span'),
select_all = jq_elem_span.text() == 'Select All',
set_text = select_all ? 'Select None' : 'Select All';
jq_elem_span.text(set_text);
jq_elem.siblings('li').filter(function() {
return $(this).find('input').prop('checked') != select_all;
}).click();
});
});
You can add them like this:
https://codepen.io/anon/pen/XgEbRL?editors=1010
HTML:
<div class="input-field col s12">
<select multiple>
<option value="" disabled selected>Choose your option</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<label>Materialize Multiple Select</label>
</div>
<a class="btn" onClick="javascript:selectAll()">Select all</a>
<a class="btn" onClick="javascript:selectNone()">Select none</a>
JavaScript:
var activateOption = function(collection, newOption) {
if (newOption) {
collection.find('li.selected').removeClass('selected');
var option = $(newOption);
option.addClass('selected');
}
};
$(document).ready(function() {
$('select').material_select();
$('.test-input > .select-wrapper > .select-dropdown').prepend('<li class="toggle selectall"><span><label></label>Select all</span></li>');
$('.test-input > .select-wrapper > .select-dropdown').prepend('<li style="display:none" class="toggle selectnone"><span><label></label>Select none</span></li>');
$('.test-input > .select-wrapper > .select-dropdown .selectall').on('click', function() {
selectAll();
$('.test-input > .select-wrapper > .select-dropdown .toggle').toggle();
});
$('.test-input > .select-wrapper > .select-dropdown .selectnone').on('click', function() {
selectNone();
$('.test-input > .select-wrapper > .select-dropdown .toggle').toggle();
});
});
function selectNone() {
$('select option:selected').not(':disabled').prop('selected', false);
$('.dropdown-content.multiple-select-dropdown input[type="checkbox"]:checked').not(':disabled').prop('checked', '');
//$('.dropdown-content.multiple-select-dropdown input[type="checkbox"]:checked').not(':disabled').trigger('click');
var values = $('.dropdown-content.multiple-select-dropdown input[type="checkbox"]:disabled').parent().text();
$('input.select-dropdown').val(values);
console.log($('select').val());
};
function selectAll() {
$('select option:not(:disabled)').not(':selected').prop('selected', true);
$('.dropdown-content.multiple-select-dropdown input[type="checkbox"]:not(:checked)').not(':disabled').prop('checked', 'checked');
//$('.dropdown-content.multiple-select-dropdown input[type="checkbox"]:not(:checked)').not(':disabled').trigger('click');
var values = $('.dropdown-content.multiple-select-dropdown input[type="checkbox"]:checked').not(':disabled').parent().map(function() {
return $(this).text();
}).get();
$('input.select-dropdown').val(values.join(', '));
console.log($('select').val());
};

two level ng-options nested object

EDIT: Using only ng-options as much as possible.
How the data looks like:
vm.category = [
0: {
label: 'Label A',
children: [
{
label: 'Label A.1',
value: 'labelA1',
}
]
}
1: {},
2: {}
]
How it will look like in the HTML. Expected HTML
<select>
<optionGroup> Label A </optionGroup>
<option value="labelA1"> Label A.1 </option>
<option value="labelA2"> Label A.2 </option>
<optionGroup> Label B </optionGroup>
<option value="labelB1"> Label B.1 </option>
</select>
How to achieve this without changing the data structure as much as possible?
I tried ng-options="category.children.label group by category.label for category in vm.categoryTree". But the output is
<select>
<optionGroup> Label A </optionGroup>
<option> undefined </option>
<optionGroup> Label B </optionGroup>
<option> undefined </option>
</select>
Easiest way would be to map the data to a format more easily used by the ng-options "group by" expression
angular.module('so', []).controller('snippet', function() {
this.categoru = [{"label":"Label A","children":[{"label":"Label A.1","value":"labelA1"}]},{"label":"Label B","children":[{"label":"Label B.1","value":"labelB1"}]}];
this.options = this.categoru.reduce((flat, group) => {
Array.prototype.push.apply(flat, group.children.map(child => {
return Object.assign({
parent: group.label
}, child);
}));
return flat;
}, []);
console.log(this.options);
});
<form ng-app="so" ng-controller="snippet as vm">
<select ng-model="vm.selected"
ng-options="opt.label group by opt.parent for opt in vm.options track by opt.value">
</select>
<pre>vm.selected = {{vm.selected | json }}</pre>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
You can do this,
<select ng-model='theModel' ng-change="display(theModel)">
<optgroup ng-repeat='group in collection' label="{{group.Name}}">
<option ng-repeat='veh in group.Fields' value='{{group.Name}}::{{veh.Name}}'>{{veh.Name}}</option>
</optgroup>
</select>
DEMO

Getting selected item of ng repeat on a datalist

I'm using a array iteration to know which is the selected option. I'm insterested on id atribute of result. is there other way?
<input type="text" list="products" ng-model="query" />
<datalist id="products">
<option value="{{result.name}}" ng-repeat="result in results" >
</datalist>
...
$scope.search = function (query) {
$scope.results.forEach(function (result) {
if (result.name === query) {
// code here
}
}
}
...
Try this:
<datalist id="products">
<option value="{{result.name}}" ng-selected="query.id == result.id" ng-repeat="result in results" >
</datalist>

Resources