AngularJS filter by dropdown value - angularjs

I have a problem with filter my data by category selected by dropdownlist.
Here how looks like my controller:
var category = {
"Dairy": 1,
"Bread": 2,
"Drink": 3,
"Spices": 4,
"Meat": 5
}
$scope.categories = [
{ text: "All", value: 0 },
{ text: "Dairy", value: 1 },
{ text: "Bread", value: 2 },
{ text: "Drink", value: 3 },
{ text: "Spices", value: 4 },
{ text: "Meat", value: 5 }
];
$scope.products = [
{ name: "Milk", value: 3.28, avaible: true, expireDate: "2016-04-29", category: category.Dairy },
{ name: "Serek wiejski", value: 1.28, avaible: false, expireDate: "2016-04-26", category: category.Dairy },
{ name: "Coca-cola", value: 6.98, avaible: true, expireDate: "2017-04-29", category: category.Drink },
{ name: "Corn", value: 0.99, avaible: true, expireDate: "2016-09-19", category: category.Spices },
{ name: "Ham", value: 9.00, avaible: true, expireDate: "2016-04-29", category: category.Meat },
{ name: "Bread", value: 3.78, avaible: true, expireDate: "2016-04-29", category: category.Dairy }
];
Here is HTML
<select ng-model="selectedCategory">
<option ng-repeat="cat in categories" value="{{cat.value}}">
{{cat.text}}
</option>
</select>
<div ng-repeat="product in products | filter: product.category == selectedCategory">
After I change value of dropdown the products are not being filtered. Just for id = 5 it works as expected.
Is condition product.category = selectedCategory wrong?

try this
<div ng-repeat="product in products | filter:{category:selectedCategory}">

Related

covert list into another new list with new property name

I have one list look like allsettings. I want to convert that list to a new list. Since I am new to react I don't have much idea, I tried by doing the below way but 1st item in the new list is always empty.
const [mySetting, setMySet] = useState([]);
useEffect(() => {
const allSettings = [
{ name: "Setting1", value: true, label: 1 },
{ name: "Setting2", value: true, label: 2 },
{ name: "Setting3", value: true, label: 3 },
{ name: "Setting4", value: false, label: 4 },
{ name: "Setting5", value: true, label: 5 },
{ name: "Setting6", value: true, label: 6 },
{ name: "Setting7", value: true, label: 7 }
];
const settings = [];
const allSettingsMap = allSettings.reduce((resMap, current) => {
settings.push(resMap);
return {
...resMap,
SettingID: current.label,
Name: current.name,
value: current.value
};
}, {});
setMySet(settings);
}, []);
//I want new list like this:
const newSettings = [
{ name: "Setting1", value: true, SettingID: 1 },
{ name: "Setting2", value: true, SettingID: 2 },
{ name: "Setting3", value: true, SettingID: 3 },
{ name: "Setting4", value: false, SettingID: 4 },
{ name: "Setting5", value: true, SettingID: 5 },
{ name: "Setting6", value: true, SettingID: 6 },
{ name: "Setting7", value: true, SettingID: 7 }
];
You can use array#map to rename a key in your object and keeping other keys intact. For each object, you can pick label and rename it to SettingID and keep other key-values same.
const allSettings = [ { name: "Setting1", value: true, label: 1 }, { name: "Setting2", value: true, label: 2 }, { name: "Setting3", value: true, label: 3 }, { name: "Setting4", value: false, label: 4 }, { name: "Setting5", value: true, label: 5 }, { name: "Setting6", value: true, label: 6 }, { name: "Setting7", value: true, label: 7 } ],
result = allSettings.map(({label, ...other}) => ({...other, SettingID: label}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can easily do it by map on array
const allSettings = [
{ name: "Setting1", value: true, label: 1 },
{ name: "Setting2", value: true, label: 2 },
{ name: "Setting3", value: true, label: 3 },
{ name: "Setting4", value: false, label: 4 },
{ name: "Setting5", value: true, label: 5 },
{ name: "Setting6", value: true, label: 6 },
{ name: "Setting7", value: true, label: 7 }
];
const newAllSettings = allSettings.map(item => {
return {
name: item.name,
value: item.value,
SettingID:item.label
};
});
console.log(newAllSettings)
Replace your allSettings.reduce method with this map method
const settings = [];
allSettings.map((setting) => {
const item = { ...setting };
const tempValue = item?.label;
// delete item label
delete item["label"];
item["SettingID"] = tempValue;
settings.push(item);
});

Modifying select for product variation in React Js

In a small ecommerce project (sourcing data from WooCommerce) in ReactJs i have a variable product
Besides all the product data i got two array object representing the product variations, one contains all the available attribute and options:
nodes: Array(3)
0:
id: "d2VpZ2h0OjMxOldlaWdodA=="
name: "Weight"
options: Array(2)
0: "250gr"
1: "500gr"
position: 0
variation: true
visible: true
1:
id: "cm9hc3Q6MzE6Um9hc3Q="
name: "Roast"
options: Array(3)
0: "Light"
1: "Medium"
2: "Dark"
position: 1
variation: true
visible: true
2:
id: "cGFja2FnaW5nOjMxOlBhY2thZ2luZw=="
name: "Packaging"
options: Array(2)
0: "Card"
1: "Tin"
position: 2
variation: true
visible: true
I save this one in a state and use it to build the select (3 select in this case)
then i have an array of object which contans all the available combinations, with price, id and so on:
nodes: Array(5)
0:
attributes:
nodes: Array(3)
0: {id: "NDB8fHdlaWdodHx8MjUwZ3I=", name: "weight", value: "250gr"}
1: {id: "NDB8fHJvYXN0fHxNZWRpdW0=", name: "roast", value: "Medium"}
2: {id: "NDB8fHBhY2thZ2luZ3x8Q2FyZA==", name: "packaging", value: "Card"}
id: "cHJvZHVjdF92YXJpYXRpb246NDA="
price: "€7,00"
variationId: 40
1:
attributes:
nodes: Array(3)
0: {id: "Mzh8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "Mzh8fHJvYXN0fHxEYXJr", name: "roast", value: "Dark"}
2: {id: "Mzh8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246Mzg="
price: "€12,00"
variationId: 38
2:
attributes:
nodes: Array(3)
0: {id: "Mzd8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "Mzd8fHJvYXN0fHxNZWRpdW0=", name: "roast", value: "Medium"}
2: {id: "Mzd8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246Mzc="
price: "€12,00"
variationId: 37
3:
attributes:
nodes: Array(3)
0: {id: "MzZ8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "MzZ8fHJvYXN0fHxMaWdodA==", name: "roast", value: "Light"}
2: {id: "MzZ8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
id: "cHJvZHVjdF92YXJpYXRpb246MzY="
price: "€12,00"
variationId: 36
4:
attributes:
nodes: Array(3)
0: {id: "MzR8fHdlaWdodHx8MjUwZ3I=", name: "weight", value: "250gr"}
1: {id: "MzR8fHJvYXN0fHxMaWdodA==", name: "roast", value: "Light"}
2: {id: "MzR8fHBhY2thZ2luZ3x8Q2FyZA==", name: "packaging", value: "Card"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246MzQ="
price: "€7,00"
variationId: 34
Basically, when i select something on any select, the other select shoould filter based on the avaialble variations: if i select 250gr as weight, the Dark Roast and the Tin Packaging sould be removed from their select since they arent combinable with 250gr; if i switch back to 500gr (or to "no option selected") they should reappear in the same place as they were before.
on the basic WooCommerce product page it already works this way (you can check its behaviour here: https://shop.popland.it/prodotto/coffee-bean/) but replicating it in ReactJs its harder than i was thinking.
At the moment im stuck on loop that generate the select with an empty onChange handler:
const [attr, setAttr] = useState(product.attributes);
<div>
{attr.nodes.map((attribute, l) => {
return (
<div key={l}>
<span>{attribute.name}</span>
<select
id={attribute.name}
onChange={handleChange}
data-attribute_name={`attribute_${attribute.name}`}
>
<option>Select option</option>
{attribute.options.map((option, o) => {
return (
<option key={o} value={option}>
{option}
</option>
);
})}
</select>
</div>
);
})}
</div>
Any suggetion/help on how to go on from here?
here is my solution.
/src/hooks.js
import { useState } from "react";
import { filterVariations, formatVariations } from "./helpers";
export function useVariations(product) {
const [state, setState] = useState({});
const filteredVariations = filterVariations(
product?.variations?.nodes,
state,
);
const formatedVariations = formatVariations(
filteredVariations,
product?.variations?.nodes,
);
return [formatedVariations, state, setState];
}
/src/helpers.js
export function filterVariations(variations, state) {
if (Object.keys(state).length === 0) {
return variations;
}
return Object.keys(state)?.reduce((accStateVars, currStateVar) => {
return accStateVars.reduce((accVars, currVar) => {
const filteredAttrsByName = currVar?.attributes?.nodes?.filter(
(attr) => currStateVar === attr?.name,
);
const withSelected = currVar?.attributes?.nodes?.findIndex(
(attr) => attr?.attributeId === state?.[currStateVar]?.value,
);
return [
...accVars,
{
attributes: {
nodes:
withSelected >= 0
? currVar?.attributes?.nodes
: filteredAttrsByName,
},
},
];
}, []);
}, variations);
}
export function formatVariations(filteredVariations, variations) {
const defaultSelects = variations?.reduce(
(accVars, currVar) => ({
...accVars,
...currVar?.attributes?.nodes?.reduce(
(accAttrs, currAttr) => ({ ...accAttrs, [currAttr.name]: {} }),
{},
),
}),
{},
);
return filteredVariations.reduce((accVars, currVar) => {
const filteredAttrs = currVar?.attributes?.nodes?.reduce(
(accAttrs, currAttr) => {
const exists =
0 <=
accVars[currAttr.name]?.options?.findIndex(
(option) => option.value === currAttr.attributeId,
);
return {
...accAttrs,
[currAttr.name]: {
placeholder: currAttr.label,
options: exists
? accVars[currAttr.name]?.options || []
: [
...(accVars[currAttr.name]?.options || []),
{ label: currAttr.value, value: currAttr.attributeId },
],
},
};
},
{},
);
return { ...accVars, ...filteredAttrs };
}, defaultSelects);
}
/src/App.js
import "./styles.css";
import Select from "react-select";
import { useVariations } from "./hooks";
const product = {
variations: {
nodes: [
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY5MHx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 304,
id: "NTY5MHx8cGFfY29sb3J8fGdyYXBoaXRl",
label: "Color",
value: "Graphite",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY5MHx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY5MHx8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 255,
id: "NTY4Nnx8cGFfc2l6ZXx8MTAtc3BlYWtlcg==",
label: "Size",
value: '10" Speaker',
},
{
name: "pa_color",
attributeId: 67,
id: "NTY4Nnx8cGFfY29sb3J8fGJlaWdl",
label: "Color",
value: "Beige",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY4Nnx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 337,
id: "NTY4Nnx8cGFfcGFsbGV0fHxwZWFjaA==",
label: "Pallet",
value: "Peach",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 255,
id: "NTY4N3x8cGFfc2l6ZXx8MTAtc3BlYWtlcg==",
label: "Size",
value: '10" Speaker',
},
{
name: "pa_color",
attributeId: 439,
id: "NTY4N3x8cGFfY29sb3J8fGZhdGFsLWFwcGxl",
label: "Color",
value: "Fatal Apple",
},
{
name: "pa_flavor",
attributeId: 319,
id: "NTY4N3x8cGFfZmxhdm9yfHx2YW5pbGxh",
label: "Flavor",
value: "Vanilla",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY4N3x8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY4OHx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 67,
id: "NTY4OHx8cGFfY29sb3J8fGJlaWdl",
label: "Color",
value: "Beige",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY4OHx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 337,
id: "NTY4OHx8cGFfcGFsbGV0fHxwZWFjaA==",
label: "Pallet",
value: "Peach",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY4OXx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 436,
id: "NTY4OXx8cGFfY29sb3J8fGJlbGdyYXZlcw==",
label: "Color",
value: "Belgraves",
},
{
name: "pa_flavor",
attributeId: 319,
id: "NTY4OXx8cGFfZmxhdm9yfHx2YW5pbGxh",
label: "Flavor",
value: "Vanilla",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY4OXx8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
],
},
};
export default function App() {
const [selects, state, setState] = useVariations(product);
function onChange(select, value) {
const newState = {
...state,
[select]: { ...value, name: select },
};
if (!value) {
delete newState[select];
}
setState(newState);
}
return (
<div className="App">
{Object.keys(selects).map((select) => (
<Select
isClearable
key={selects[select].placeholder}
placeholder={selects[select].placeholder}
// value={state[select]}
onChange={(o) => onChange(select, o)}
options={selects[select].options}
/>
))}
</div>
);
}
Playground

How to merge 2 objects array to make it one object and json output using angularjs

I have 2 object arrays and will use those value on checkbox for view. I want to merge 2 obj arrays to make it one json object file. help me please
$scope.fruits = [
{ name: 'apple', selected: true },
{ name: 'orange', selected: false },
{ name: 'pear', selected: true },
{ name: 'naartjie', selected: false }
];
$scope.color = [
{ name: 'red', selected: true },
{ name: 'green', selected: false },
{ name: 'orange', selected: true },
{ name: 'yellow', selected: false }
];
And the view,
<label ng-repeat="fruit in fruits" class="checkbox-inline">
<input type="checkbox" name="selectedFruits[]" value="{{fruitName}}" ng-model="fruit.selected"> {{fruit.name}}</label>
<label ng-repeat="color in colors" class="checkbox-inline">
<input type="checkbox" name="selectedColors[]" value="{{colorName}}" ng-model="color.selected"> {{color.name}}</label>
And the output i want like below:
[{
"name": "apple",
"color": "red",
"selected": true
},
{
"name": "orange",
"color": "yellow",
"selected": true},
{
"name": "pear",
"color": "green",
"selected": true}]
you can use map function for this.
var fruits = [
{ name: 'apple', selected: true },
{ name: 'orange', selected: false },
{ name: 'pear', selected: true },
{ name: 'naartjie', selected: false }
];
var color = [
{ name: 'red', selected: true },
{ name: 'green', selected: false },
{ name: 'orange', selected: true },
{ name: 'yellow', selected: false }
];
var arr = fruits.map((o,i)=>{
o.color = color[i].name;
return o;
});
console.log(arr)
Use Angular merge enter link description here
var mergedObject = angular.extend(object1, object2);
And manual way by ignoring null and missing values would be
this

How to select multiple selected value from select option

My controller code looks like
$scope.items = [{
heading: 'Sports',
types: [{
name: 'Football',
}, {
name: 'Persie',
}, {
name: 'Ronaldo',
}, {
name: 'Messy',
}],
id: '1'
}, {
heading: 'Cricket',
types: [{
name: 'Tendulkar',
}, {
name: 'Lara',
}, {
name: 'Ponting',
}],
id: '2'
}];
My view contains something like this :
How can I get the selected values of options when user clicks submit button
Here is the jsfiddle
I used ng-repeat to build the select and ng-options to fill them, you then have to use the relative ng-model to get the selections.
HTML:
<div ng-app ng-controller="MyCtrl">
<select class="select fancy" ng-repeat="(i, item) in items" ng-model="searchOption[i]" ng-options="type.name for type in item.types"></select>
<button ng-click="submitIt()">Submit</button>
</div>
Javascript:
function MyCtrl($scope) {
$scope.submitIt = function () {
console.log($scope.searchOption);
};
$scope.searchOption = [];
$scope.items = [{
heading: 'Sports',
types: [{
name: 'Football',
}, {
name: 'Persie',
}, {
name: 'Ronaldo',
}, {
name: 'Messy',
}],
id: '1'
}, {
heading: 'Cricket',
types: [{
name: 'Tendulkar',
}, {
name: 'Lara',
}, {
name: 'Ponting',
}],
id: '2'
}];
}

All values in array bound to same value

I'm trying to update values inside $scope.match.teams[0] with vaules for the players' names, but when I input in a single field, it is bound to every players' name for that team.
Controller:
$scope.match = {
teams: [
{
id: 0,
name: "",
players: [
{ id: 1, name: "" },
{ id: 2, name: "" },
{ id: 3, name: "" },
{ id: 4, name: "" },
{ id: 5, name: "" },
{ id: 6, name: "" },
{ id: 7, name: "" },
{ id: 8, name: "" },
{ id: 9, name: "" },
{ id: 10, name: "" },
{ id: 11, name: "" },
]
},
{
id: 1,
name: "",
players: [
{ id: 1, name: "" },
{ id: 2, name: "" },
{ id: 3, name: "" },
{ id: 4, name: "" },
{ id: 5, name: "" },
{ id: 6, name: "" },
{ id: 7, name: "" },
{ id: 8, name: "" },
{ id: 9, name: "" },
{ id: 10, name: "" },
{ id: 11, name: "" },
]
}
]
};
$scope.battingFirstSelected = function(){
switch ($scope.battingFirst.id) {
case 0:
$scope.battingSecond = $scope.match.teams[1];
case 1:
$scope.battingSecond = $scope.match.teams[0];
}
};
HTML:
Team batting first:
<select
ng-change="battingFirstSelected()"
ng-model="battingFirst"
ng-options="team.name for team in match.teams">
</select>
<div ng-repeat="player in battingFirst.players">
<input
class="form-control"
ng-model="match.teams[battingFirst.id].player.name"
value="" />
</div>
<div ng-repeat="player in match.teams[battingFirst.id].players">
{{ match.teams[battingFirst.id].player.name }}
</div>
The selection of the team works fine, it's just assigning the names that's the problem here.
The output of {{ match.teams[battingFirst.id] }} shows that I'm creating a new team every time I fill in one of the inputs, with a { player: {"name":"sdf"} } object attached to it.
You just need to try:
ng-model="player.name"
Your battingFirst is already a selected team from the above select. When you bind to players in this battingFirst, you bind correctly to players of the selected team.
<div ng-repeat="player in battingFirst.players">
<input
class="form-control"
ng-model="player.name"
value="" />
</div>
The problem you have is because ng-repeat creates child scopes. Therefore match.teams inside your ng-repeat is not the same as the match.teams of your parent scope.

Resources