Add selected class to each clicked item in ngFor - css

Issue: With the current code, when i click an item, it correctly adds the "selected" class to the clicked item, but when i click another option, the "selected" class gets removed from it and gets added to the newly clicked item.
Wanted: I want to have the selected class added to all items which have been selected, my code is below, would appreciate any help:
My Html:
<form (ngSubmit)="onSubmit()">
<div *ngFor="let event of groupSelections; let i = index;" class="row">
<div class="col-12">
<div class="row">
<div *ngFor="let team of event?.Actors; first as isFirst" class="col-6">
<div class="row">
<div *ngIf="isFirst" class="col-6">
<div>
{{ team?.ActorName }}
</div>
</div>
<div class="col-6">
<div [className]="selectedValue == team?.Players ?'selected':''">
<select (change)="getSelections(team, event, $event, team?.Players)">
<option value="none" selected disabled hidden>SELECT</option>
<option value="" *ngFor="let player of team?.Players; let j = index">
{{ player?.Name }}
</option>
</select>
</div>
</div>
<div *ngIf="!isFirst" class="col-6">
<div>
{{ team?.ActorName }}
</div>
</div>
</div>
</div>
</div>
</div>
My function:
getSelections(actors, event, selectedOption, player): any {
const selections = [];
this.selectedTeam = actors;
this.selectedTeamPlayers = actors.Players;
this.gameEvent = event;
this.selectedValue = player;
selections.push({
EventId: this.gameEvent.EventId,
ActorId: this.selectedTeam.ActorId,
EventActorId: this.selectedTeam.EventActorId,
Score: 1,
Position: 1,
PlayerPosition: this.player.Position,
PlayerPoint: this.player.Point,
});
this.playerSelections = selections;
}
My Data:
groupSelections = [
{
"PromotionId": 5,
"Events": [
{
"Actors": [
{
"ActorId": 33,
"ActorName": "Italy",
"Players": [
{
"Name": " Mattia De Sciglio (D)",
"Position": "DEFENDER",
"Point": 5
},
{
"Name": "Bryan Cristante (M)",
"Position": "MIDFIELDER",
"Point": 3
}
]
},
{
"ActorId": 34,
"ActorName": "Turkey",
"Players": [
{
"Name": " Zeki Çelik (D)",
"Position": "DEFENDER",
"Point": 5
},
{
"Name": "Ozan Tufan (M)",
"Position": "MIDFIELDER",
"Point": 3
}
]
}
]
},
{
"Actors": [
{
"ActorId": 77,
"ActorName": "Slovakia",
"Players": [
{
"Name": "Mattia Perin (G)",
"Position": "GOALKEEPER",
"Point": 10
},
{
"Name": "Bryan Cristante (M)",
"Position": "MIDFIELDER",
"Point": 3
}
]
},
{
"ActorId": 78,
"ActorName": "Sweden",
"Players": [
{
"Name": " Zeki Çelik (D)",
"Position": "DEFENDER",
"Point": 5
},
{
"Name": "Ozan Tufan (M)",
"Position": "MIDFIELDER",
"Point": 3
}
]
}
]
}
]
}

Usually you should add a selected field to your Players object. Then you can set it to true and consider it when adding the additional class.
But let's do it with a simple array first.
TS file
selectedPlayers: Array<string> = [];
// check whether the players object is in the list
isSelectedPlayer(players: any): boolean {
return this.selectedPlayers.findIndex(element => element === players) > -1;
}
getSelections(actors, event, selectedOption, player): any {
const selections = [];
this.selectedTeam = actors;
this.selectedTeamPlayers = actors.Players;
this.gameEvent = event;
// add the selection to your list, if is not in it
if (this.selectedPlayers.findIndex(element => element === player) === -1) {
this.selectedPlayers.push(player);
}
selections.push({
EventId: this.gameEvent.EventId,
ActorId: this.selectedTeam.ActorId,
EventActorId: this.selectedTeam.EventActorId,
Score: 1,
Position: 1,
PlayerPosition: this.player.Position,
PlayerPoint: this.player.Point,
});
this.playerSelections = selections;
}
HTML
<div [className]="gameEvent == event && isSelectedPlayer(team?.Players) ? 'selected':''">

Related

How to style dynamically added nested elements in react

I was dynamically adding nested categories and subacatogories in react. I want to hide and show the sub-categories on clicking or hovering main-category. I wanted to show/hide subcatogories(mobiles, tv, laptops) on clicking Accessories and wanna show/hide Noodles on clicking groceries. Please help
My Code:
import React from "react";
function App(props) {
const categoriesList = [
{
id: "1",
name: "Accessories",
slug: "accessories",
children: [
{
id: "2",
name: "Mobiles",
slug: "mobiles",
},
{
id: "3",
name: "TV",
slug: "tv",
},
{
id: "4",
name: "Laptops",
slug: "laptops",
children: [
{
id: 5,
name: "Dell",
slug: "dell",
},
],
},
],
},
{
id: "6",
name: "Books",
slug: "books",
// children: undefined,
},
{
id: "7",
name: "Groceries",
slug: "groceries",
children: [
{
id: "8",
name: "Noodles",
slug: "noodles",
},
],
},
];
const renderCategories = (categories) => {
let myCategories = [];
for (const category of categories) {
myCategories.push(
<li className="category-list" key={category.name}>
{category.name}
{category?.children?.length > 0 ? (
<ul className="nested-category">
{renderCategories(category.children)}
</ul>
) : null}
</li>
);
}
return myCategories;
};
return (
<div className="app">
<ul className="main">{renderCategories(categoriesList)}</ul>
</div>
);
}
You need a state like categoryToBeDisplayed and then just have an onClick on the category li tag
for (const category of categories) {
myCategories.push(
<li className="category-list" key={category.name} onClick={() => setCategory(category.name)}>
{category.name}
{category?.children?.length > 0 && categoryToBeDisplayed === category.name ? (
<ul className="nested-category">
{renderCategories(category.children)}
</ul>
) : null}
</li>
);
}
And if you want multiple to be open at once just have the state accept an array and check if categoryToBeDisplayed.includes(category.name)

Unable to get results using map in Nextjs wordpress headless cms

I am developing headless WordPress with NExtjs.
menuItems is props that contain an object. when I console.log(menuItems ) it shows output in the console similar to "const menu" but when I map "menu" it maps perfectly but when I map menuItems, the site gives me the error that it is not defined.
code under className "navi-2" is not working
<pre>
import Link from "next/link";
function NavBar({ menuItems }) {
console.log(menuItems )
const menu = {
"menuItemse": {
"edges": [
{
"node": {
"uri": "/",
"title": "home link",
"target": null,
"label": "Home"
}
},
{
"node": {
"uri": "/about-us/",
"title": null,
"target": null,
"label": "About Us"
}
},
{
"node": {
"uri": "/portfolio/",
"title": null,
"target": null,
"label": "Portfolio"
}
},
{
"node": {
"uri": "/services/",
"title": null,
"target": null,
"label": "Services"
}
},
{
"node": {
"uri": "/contact-us/",
"title": null,
"target": null,
"label": "Contact Us"
}
}
]
}
}
return(
<>
<nav className="navi">
{menu.menuItemse.edges.map(it => (
<Link href={it.node.uri}><a>{it.node.label}</a></Link>
) )}
</nav>
<nav className="navi-2">
{menuItems.menuItems.edges.map(item => (
<Link href={item.node.uri}><a>{item.node.label}</a></Link>
) )}
</nav>
</>
)
}
export default NavBar
</pre>

Can't display retrieved data from Strapi in the UI, but can see them in the console Using Next.Js

I am trying to retrieve data from strapi using the NextJs as the front-end. The problem is that I can't display them on the UI, but I can see them in the console.
I used Graphql for querying the data using this commend:
query {
menus(filters: {language: {code: {eq: "en"}}}) {
data {
attributes {
Entry {
title
link
}
}
}
}
}
, I got this:
{
"data": {
"menus": {
"data": [
{
"attributes": {
"Entry": [
{
"title": "home",
"link": "/home.html"
},
{
"title": "classes",
"link": "./calss.html"
},
{
"title": "events",
"link": "/events.html"
},
{
"title": "news",
"link": "/news.html"
},
{
"title": "reosurces",
"link": "./resources.html"
},
{
"title": "links",
"link": "./links.html"
}
]
}
}
]
}
}
}
and this is how the UI handled:
const mainMenuAdapter = (menuData) => {
return menuData.map(md => {
const entry = md['attributes']['Entry']
console.log('title', entry)
return {
link: entry.link,
title: entry.title,
}
})
}
I use useContext;
const { menuData } = useContext(GlobalContext)
const menus = mainMenuAdapter(menuData)
here is how the mapping is handled.
<div className="bg-green-400 relative filosofia_regular bg-grayDark flex-wrap md:flex flex-row items-end md:justify-around p-2 lg:justify-evenly text-center mx-auto w-full">
{!!menus && menus.map((menu, i) => {
return (
<div key={i}>
<Link href="/">
<a className="text-gray-100 px-2 text-sm lg:text-2xl xl:text-4xl whitespace-nowrap">
{t(menu.title)}
</a>
</Link>
{i < menus.length - 1 && (
<a className="text-white">|</a>
)}
</div>
);
})}
</div>
and here is the console.
(6) [{…}, {…}, {…}, {…}, {…}, {…}]
0:
link: "/home.html"
title: "home"
__typename: "ComponentEntryComEntry"
[[Prototype]]: Object
1: {title: 'classes', link: './calss.html', __typename: 'ComponentEntryComEntry'}
2: {title: 'events', link: '/events.html', __typename: 'ComponentEntryComEntry'}
3: {title: 'news', link: '/news.html', __typename: 'ComponentEntryComEntry'}
4: {title: 'reosurces', link: './resources.html', __typename: 'ComponentEntryComEntry'}
5: {title: 'links', link: './links.html', __typename: 'ComponentEntryComEntry'}
length: 6
[[Prototype]]: Array(0)
Can anyone please tell me what I am missing?
Thanks

react-table TypeError: Cannot read properties of undefined (reading 'forEach')

TypeError: Cannot read properties of undefined (reading 'forEach')
This is an error message I get when I am trying to render OrderTable component. I struggled fixing it for a good few hours and I don't have idea what is wrong.
Other almost similar tables works fine.
const orderProducts = useSelector((state) => state.orders.order.products)
I use this structure instead of state.orders.order because from serializer I got nested data that does not works. Tried to take products from order after selector and it does not also work. Data seems to be fine, but I attach JSON anyway.
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getOrder } from "../../features/orders/orderSlice";
import {
useTable,
useRowSelect,
useSortBy,
useFilters,
useGlobalFilter,
} from "react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from "#mui/material";
import Paper from "#mui/material/Paper";
import KeyboardArrowUpIcon from "#mui/icons-material/KeyboardArrowUp";
import KeyboardArrowDownIcon from "#mui/icons-material/KeyboardArrowDown";
import TableContainer from "#mui/material/TableContainer";
import IndeterminateCheckbox from "../Checkbox";
import ColumnFilter from "../ColumnFilter";
// import GlobalFilter from "../GlobalFilter";
const OrderTable = () => {
const dispatch = useDispatch();
useEffect(() => {
const id = window.location.pathname.split("/orders/order/").pop();
dispatch(getOrder(id));
}, []);
const loading = useSelector((state) => state.orders.loading);
const orderProducts = useSelector((state) => state.orders.order.products);
const data = React.useMemo(() => orderProducts, [orderProducts]);
const columns = React.useMemo(
() => [
{ Header: "ID", accessor: "id", Filter: ColumnFilter },
{ Header: "Nazwa", accessor: "product.title", Filter: ColumnFilter },
{ Header: "Ilość", accessor: "quantity", Filter: ColumnFilter },
{ Header: "Cena", accessor: "product.price", Filter: ColumnFilter },
{ Header: "Wartość", accessor: "total_price", Filter: ColumnFilter },
{
Header: "Zamówiony",
accessor: (d) => (d.ordered ? "Tak" : "Nie"),
Filter: ColumnFilter,
},
],
[]
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
state,
setGlobalFilter,
prepareRow,
selectedFlatRows,
} = useTable(
{ columns, data },
useGlobalFilter,
useFilters,
useSortBy,
useRowSelect,
(hooks) => {
hooks.visibleColumns.push((columns) => [
// Let's make a column for selection
{
id: "selection",
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
),
},
...columns,
]);
}
);
const { globalFilter } = state;
return (
<>
{loading ? (
"loading"
) : (
<TableContainer component={Paper} sx={{ ml: 3, mt: 2 }}>
<Table {...getTableProps()} size="small">
<TableHead>
{headerGroups.map((headerGroup) => (
<TableRow {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<TableCell {...column.getHeaderProps()}>
<div {...column.getSortByToggleProps()}>
{column.render("Header")}
{column.isSorted ? (
column.isSortedDesc ? (
<KeyboardArrowUpIcon fontSize="small" />
) : (
<KeyboardArrowDownIcon fontSize="small" />
)
) : (
""
)}
</div>
<div>
{column.canFilter ? column.render("Filter") : null}
</div>
</TableCell>
))}
</TableRow>
))}
</TableHead>
<TableBody {...getTableBodyProps()}>
{rows.map((row) => {
prepareRow(row);
return (
<TableRow {...row.getRowProps()}>
{row.cells.map((cell) => {
return (
<TableCell {...cell.getCellProps()}>
{cell.render("Cell")}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
)}
</>
);
};
export default OrderTable;
JSON
{
"id": 37,
"products": [
{
"id": 68,
"product": {
"id": 1,
"created": "2021-11-11T02:01:15.897446Z",
"active": true,
"title": "Kapustka",
"description": "biała",
"quantity": -143,
"price": "3.24",
"category": 1
},
"quantity": 8,
"total_price": "25.92",
"ordered": true,
"user": 1
},
{
"id": 69,
"product": {
"id": 2,
"created": "2021-11-12T17:16:43.422467Z",
"active": true,
"title": "Marchew",
"description": null,
"quantity": 10,
"price": "2.00",
"category": null
},
"quantity": 11,
"total_price": "22.00",
"ordered": true,
"user": 1
},
{
"id": 70,
"product": {
"id": 5,
"created": "2021-11-13T20:03:01.336712Z",
"active": true,
"title": "Makaron",
"description": null,
"quantity": 0,
"price": "0.00",
"category": null
},
"quantity": 1,
"total_price": "0.00",
"ordered": true,
"user": 1
},
{
"id": 71,
"product": {
"id": 6,
"created": "2021-11-13T20:03:12.384605Z",
"active": true,
"title": "Pomidor",
"description": null,
"quantity": 0,
"price": "0.00",
"category": null
},
"quantity": 1,
"total_price": "0.00",
"ordered": true,
"user": 1
}
],
"title": "Zamowienie",
"created": "2021-11-13T19:26:59.545602Z",
"value": "49.92",
"is_paid": false,
"ordered": true,
"user": 1
}

ASP.NET (C#) jQuery JSON data problem

My JSON Data
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
jQuery code:
$(document).ready(function() {
$("#Button1").click(function() {
var asd = "test";
$.get("CallBack.Aspx", { asd: asd }, function(data) {
$.each(data, function() {
})
})
})
})
I need menuitem in values how to make ?
"menuitem": [
{ "value": "New", "onclick": "CreateNewDoc()" } ]
$.getJSON() fits probably better.
After that,
$.each(data.menu.popup.menuitem, function(i, v) {
//Your code here
});

Resources