React Context Api with Json - javascript

I have nested json and arrays that are located in there. So the thing I am trying to do is this. I want to make a Search functionality, that 'functionality' would go through the arrays and based on a specific Id it would display the name of that specific object in the array. I have tried with Context api to share the state globally, I know its not the cleanest way of doing it, anyway it is giving me an error in FreeToPlayComponent ".filter is not a function".
Context
import React, { useState, useContext } from 'react';
export const SearchContext =React.createContext(null)
export default function SearchProvider({children}) {
const [searchValue, setSearchValue] = React.useState("");
function filterProduct(product) {
return product.name.toLowerCase().includes(searchValue.toLowerCase());
}
return(
<SearchContext.Provider value ={{filterProduct, searchValue, setSearchValue}}>
{children}
</SearchContext.Provider>
); }
json
[
{
"freetoplay": [{
"id": "0",
"image": "src=fsdf",
"price": "60$",
"name": "CS Go"
},
{
"id": "1",
"image": "src=fsdf",
"price": "6$",
"name": "Fifa"
}
],
"action": [{
"id": "2",
"image": "src=fsdf",
"price": "60$",
"name": "doom"
},
{
"id": "3",
"image": "src=fsdf",
"price": "66$",
"name": "cyberpunk"
}
],
"adventure": [
{
"id": "4",
"image": "src=fsdf",
"price": "60$",
"name": "indiana "
},
{
"id": "5",
"image": "src=fsdf",
"price": "43$",
"name": "torchlight"
}
]
}
]
Search Component
import React from 'react'
import './Search.css'
import { SearchContext } from './SearchContext';
function Search() {
const {searchValue, setSearchValue}=React.useContext(SearchContext);
return (
<div className='search'>
<form className="search__Form">
<input className="search__Input" type="text"
value ={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
type='text'
placeholder='Search '/>
</form>
</div>
)
}
export default Search
import React from 'react'
import Header from './Header'
import './App.css';
import SlideShow from './SlideShow';
import Routes from './Routes';
import data from "./data.json";
import SearchProvider from "./SearchContext";
function App() {
return (
<div className="app">
<SearchProvider>
<Header />
<SlideShow />
<Routes />
</SearchProvider>
</div>
);
}
export default App;
import React from 'react'
import data from "./data.json";
import {
Link
} from "react-router-dom";
import { SearchContext } from './SearchContext';
function FreeToPlay() {
const {filterProduct}=React.useContext(SearchContext);
return (
<>
<div className='All' >
{data[0].filter(filterProduct).freetoplay.map((product) => {
return (
<div className='f2p' key={product.id}>
<img src={product.image}></img>
<h2>{product.name}</h2>
<h5>{product.price}</h5>
<Link
to={`/payment/${product.id}`}
className='link'
>
Buy Now
</Link>
</div>
);
})}
</div>
</>
);
}
export default FreeToPlay

Your JSON data appears to be invalid, it has an extraneous opening curly bracket before the "action" key.
json
[
{
"freetoplay": [{
"id": "0",
"image": "src=fsdf",
"price": "60$",
"name": "CS Go"
},
{
"id": "1",
"image": "src=fsdf",
"price": "6$",
"name": "Fifa"
}
],
{ // <-- remove this!!
"action": [{
"id": "2",
"image": "src=fsdf",
"price": "60$",
"name": "doom"
},
{
"id": "3",
"image": "src=fsdf",
"price": "66$",
"name": "cyberpunk"
}
],
"adventure": [
{
"id": "4",
"image": "src=fsdf",
"price": "60$",
"name": "indiana "
},
{
"id": "5",
"image": "src=fsdf",
"price": "43$",
"name": "torchlight"
}
]
}
]
Also, based on the data shape and what your filterProduct function does
function filterProduct(product) {
return product.name.toLowerCase().includes(searchValue.toLowerCase());
}
it seems you should also be filtering the category/product array versus the outer array of categories/products since the category/product elements have the "name" property.
Change
data[0].filter(filterProduct).freetoplay.map
to
data[0].freetoplay.filter(filterProduct).map

Related

"TypeError: Cannot read property 'filter' of undefined" and similarly for other array functions like map using ReactJS and redux

I am following a tutorial and when at this point I'm getting stuck. It gives me TypeError: Cannot read property 'filter' of undefined when I try to filter through the Product array. I was implementing the same functionality using Axios according to the tutorial and it was working. The instructor then changed to redux and I followed the same steps and that's when I got the error. I'm pretty new to React and completely new to Axios and Redux and I've been trying to find out what's wrong but I'm getting nowhere.
Here's my ProductScreens.jsx where the error occurs:
import React, { useEffect } from "react";
import Rating from "../Components/rating.jsx";
import { useDispatch, useSelector } from "react-redux";
import { listProducts } from "../actions/productActions.js"
function Sale({product}){
if("salePrice" in product){
return <li>Sale Price: ₹{product.salePrice}</li>;
}
else
return null;
}
export default function ProductsScreen(props){
const dispatch = useDispatch();
const productList = useSelector( state => state.productList);
const {loading,error,products} = productList;
useEffect(() =>{
dispatch(listProducts());
},[dispatch]);
const product = products.filter(prod => prod.category === props.match.params.category && prod.subcategory === props.match.params.subcategory);
return (
<div className="container-fluid main-cards">
<div className="row">
{
product.map(product => (
<div key={product._id} className="col-12 col-md-6 col-lg-4 main-card-item">
<div className="card">
</img>
<div className="card-body product-card list-group">
<h5 className="card-title">{product.name}</h5>
<p className="card-text">{product.description}</p>
<ul className="list-unstyled mt-3 mb-4">
<li>Price: ₹{product.price}</li>
<Sale product={product}/>
<li>Buy Now</li>
<li>
<Rating rating={product.rating} numReview={product.numReview}/>
</li>
</ul>
</div>
</div>
</div>
))};
</div>
</div>
)
}
Here is my productActions.js
import Axios from "axios";
import { PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS, PRODUCT_LIST_FAIL } from "../constants/productConstants"
export const listProducts = () => async (dispatch) =>{
dispatch({
type: PRODUCT_LIST_REQUEST,
});
try {
const {data} = await Axios.get('/api/products');
dispatch({type: PRODUCT_LIST_SUCCESS, payload : data});
}catch(error){
dispatch({type: PRODUCT_LIST_FAIL, payload: error.message});
}
}
Here's my productReducers.js
export const productListReducer = (state = {loading: true, products: [] }, action) =>{
switch(action.type){
case PRODUCT_LIST_REQUEST :
return {loading: true};
case PRODUCT_LIST_SUCCESS:
return {loading: false, products: action.payload};
case PRODUCT_LIST_FAIL :
return {loading: false, error: action.payload};
default:
return state;
}
}
And my productConstants.js
export const PRODUCT_LIST_REQUEST = "PRODUCT_LIST_REQUEST";
export const PRODUCT_LIST_SUCCESS = "PRODUCT_LIST_SUCCESS";
export const PRODUCT_LIST_FAIL = "PRODUCT_LIST_FAIL";
I've tried solving it but I can't find out what's wrong. I did console.log(products) instead of const product = products.filter(prod => prod.category === props.match.params.category && prod.subcategory === props.match.params.subcategory); in ProductScreens.jsx and also replaced the contents of return with <h1></h1> and got back the following object:
[
{
"_id": "1",
"name": "example1",
"category": "example category1",
"subcategory": "example subcategory1",
"image": [
{
"_id": "image1",
"name": "/images/example1.jpg"
}
],
"mainImage": "/images/example1.jpg",
"price": "19000",
"brand": "brand1",
"rating": 4.5,
"numReview": 10,
"description": "some description for example1."
},
{
"_id": "2",
"name": "example2",
"category": "example category1",
"subcategory": "example subcategory1",
"image": [
{
"_id": "image2",
"name": "/images/example2.jpg"
}
],
"mainImage": "/images/example2.jpg",
"price": "16791",
"salePrice": "15500",
"brand": "brand2",
"rating": 4.7,
"numReview": 10,
"description": "some description for example2."
},
{
"_id": "3",
"name": "example",
"category": "example category2",
"subcategory": "example subcategory3",
"image": [
{
"_id": "image3",
"name": "/images/example3-1.jpg"
},
{
"_id": "image4",
"name": "/images/example3-2.jpg"
},
{
"_id": "image5",
"name": "/images/example3-3.jpg"
},
{
"_id": "image6",
"name": "/images/example3-4.jpg"
}
],
"mainImage": "/images/example3-1.jpg",
"price": "8549",
"salePrice": "7200",
"brand": "brand3",
"rating": 3,
"numReview": 10,
"description": "some description for example3."
},
{
"_id": "4",
"name": "example4",
"category": "example category3",
"subcategory": "example subcategory4",
"image": [
{
"_id": "image7",
"name": "/images/example4.jpg"
}
],
"mainImage": "/images/example4.jpg",
"price": "450",
"brand": "brand4",
"rating": 4.5,
"numReview": 10,
"description": "some description for example4."
},
{
"_id": "5",
"name": "example5",
"category": "example category1",
"subcategory": "example subcategory2",
"image": [
{
"_id": "image8",
"name": "/images/example5.jpg"
}
],
"mainImage": "/images/example5.jpg",
"price": "30000",
"salePrice": "27000",
"brand": "brand5",
"rating": 4.5,
"numReview": 10,
"description": "some description for example5"
}
]
Looking at the object above, filter() should work but it's not. Moreover, the above object was the same object I got when I used axios and it worked fine then. So I have no idea why it's not working anymore.
Also when I try to console.log(products._id) or any other property, I get the same TypeError. I tried console.log(products[0]) thinking maybe I have to do that to get the first object since its an array of objects, I got TypeError: Cannot read property '0' of undefined.
So I figured it out. I found two solutions. First, Turns out I was getting two objects before the PRODUCT_LIST_SUCCESS action occured. In the first object, the products was an empty array from the initial state and in the second object which was receieved from PRODUCT_LIST_REQUEST action, there was only a loading property so products was undefined. So I changed the switch case statement in productsReducers.js for PRODUCT_LIST_REQUEST to return {loading: true, products: []}; and that did the trick.
My second solution is to check if loading is true or false and only execute my code and render the page if loading is false.
I haven't been an avid programmer so I don't know best programming practices but I'm using the second solution.

context.params.id gives error in nextjs. cannot define property 'id' of undefined

I trying to fetch data from a json file(response.json), which is running in localhost:8000/response.json.
Here is my code in pages/test.js:
import React from "react";
import Link from "next/link";
import Image from "next/image";
import Card from "#material-ui/core/Card";
import CardActions from "#material-ui/core/CardActions";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import Grid from "#material-ui/core/Grid";
import Typography from "#material-ui/core/Typography";
import { makeStyles } from "#material-ui/core/styles";
import Container from "#material-ui/core/Container";
import _ from "lodash"
// components
import Navbar from "components/Navbars/AuthNavbar.js";
import Footer from "components/Footers/Footer.js";
export const getStaticPaths = async () => {
const res = await fetch("http://localhost:8000/response.json");
const data = await res.json();
const paths = data.data.map((gallery) => {
return {
params: { id: gallery.id },
};
});
return {
paths: paths,
fallback: false,
};
};
export const getStaticProps = async (context) => {
const id = context.params.id;
const res = await fetch("http://localhost:8000/response1.json");
const data = await res.json();
const thumbnail_ = data.data.filter(parentid => parentid.parent_id == id)
return {
props: { image_data: thumbnail_ },
};
};
export default function Landing({ image_data }) {
console.log(image_data)
return (
<div>
</div>
);
}
My response.json file:
{
"data": [
{
"collection": null,
"id": 1,
"image_thumbanil": "https://images.pexels.com/photos/434090/pexels-photo-434090.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"images_id": null,
"item": null,
"name": "Animals",
"title": "Animals"
},
{
"collection": null,
"id": 2,
"image_thumbanil": "https://images.pexels.com/photos/5703286/pexels-photo-5703286.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"images_id": null,
"item": null,
"name": "Birds",
"title": "Birds"
},
{
"collection": null,
"id": 3,
"image_thumbanil": "https://images.pexels.com/photos/3802510/pexels-photo-3802510.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"images_id": null,
"item": null,
"name": "Car",
"title": "Cars"
},
{
"collection": null,
"id": 4,
"image_thumbanil": "https://images.pexels.com/photos/40904/bmw-k-1300-metallic-motorcycle-40904.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"images_id": null,
"item": null,
"name": "Bikes",
"title": "Bikes"
},
{
"collection": null,
"id": 5,
"image_thumbanil": "https://images.pexels.com/photos/3220368/pexels-photo-3220368.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"images_id": null,
"item": null,
"name": "Fishes",
"title": "Fishes"
},
{
"collection": null,
"id": 6,
"image_thumbanil": "https://images.pexels.com/photos/1040880/pexels-photo-1040880.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"images_id": null,
"item": null,
"name": "Actors",
"title": "Actors"
},
{
"collection": null,
"id": 7,
"image_thumbanil": "https://images.pexels.com/photos/6896193/pexels-photo-6896193.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"images_id": null,
"item": null,
"name": "Actresses",
"title": "Actresses"
},
{
"collection": null,
"id": 8,
"image_thumbanil": "https://images.pexels.com/photos/37859/sailing-ship-vessel-boat-sea-37859.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"images_id": null,
"item": null,
"name": "Ships",
"title": "Ships"
}
]
}
The error is get is:
TypeError: Cannot read property 'id' of undefined
My goal is to display images with parent_id = 1, I want that id to increment by one for every time the program runs. For eg.) when I run the next app, I want to get display items with parent_id = 1 and then 2 and so on..
If you use params from getStaticProps in a page your js file must be named aka [id].js.
Doc here.

Filterring array that is located in Json properly

Hello again stackoverflow community. I have F2P component who is is 'maping' objects in json and displaying them. In that Component is located a buy Now link which leads to the payment page and Component. What should happen is this, when I press on the Link it should display image class and name of that Component, but for some reason nothing happens. Why is that and what should I do to fix it?
import React from 'react'
import data from "../data.json";
import {
Link
} from "react-router-dom";
function FreeToPlay({product}) {
return (
<>
<div className='All' >
{data[0].freetoplay.map((product) => {
return (
<div className='f2p' key={product.id}>
<img src={product.image}></img>
<h2>{product.name}</h2>
<h5>{product.price}</h5>
<Link
to={`/payment/${product.id}`}
className='link'
>
Buy Now
</Link>
</div>
);
})}
</div>
</>
);
}
export default FreeToPlay
json
[
{
"freetoplay": [
{
"id": "0",
"image": "src=fsdf",
"price": "60$",
"name": "CS Go"
},
{
"id": "1",
"image": "src=fsdf",
"price": "6$",
"name": "Fifa"
}
],
{
"action": [
{
"id": "2",
"image": "src=fsdf",
"price": "60$",
"name": "doom"
},
{
"id": "3",
"image": "src=fsdf",
"price": "66$",
"name": "cyberpunk"
}
],
"adventure": [
{
"id": "4",
"image": "src=fsdf",
"price": "60$",
"name": "indiana "
},
{
"id": "5",
"image": "src=fsdf",
"price": "43$",
"name": "torchlight"
}
],
}
]
import React from 'react'
import { useParams, Link } from "react-router-dom";
import data from "../data.json";
function Payment() {
const { productId } = useParams();
const filteredData = data.filter((product) => product.id === productId)[0];
return (
<div className='Payment'>
<img src={filteredData.image}></img>
<h1>{filteredData.price}</h1>
<h1>{filteredData.name}</h1>
</div>
)
}
export default Payment
Routes
function Routes() {
return (
<div>
{data.map((product) =>
<Router>
<SideBar />
<Route path="/payment/:productId">
<Payment/>
</Route>
<Switch>
<Route path="/action">
<Action key={product.id} product={product} />
</Route>
<Route path="/freetoplay">
<FreeToPlay key={product.id} product={product} />
</Route>
</Switch>
</Router>
)}
</div>
)
}
export default Routes

Displaying data based on json object not working

I am fetching a JSON from a file in one ReactJS component and trying to display it but I don't know why something is not working.
what am I doing wrong?
App.js
import React from 'react';
import Home from './components/Home';
import GameIntro from './components/GameIntro';
import {BrowserRouter,Switch,Route} from 'react-router-dom';
function App() {
return (
<div className='container mt-5 py-5'>
<div className="row">
<div className="col-md-6 offset-md-3">
<BrowserRouter>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/intro' component={GameIntro} />
</Switch>
</BrowserRouter>
</div>
</div>
</div>
)
}
export default App;
JSON file:
gamedata.js
export const gdatas = [
{
"data": [
{
"id": 0,
"image": "https://images.unsplash.com/photo-1492725764893-90b379c2b6e7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Mom"
},
{
"id": 1,
"image": "https://images.unsplash.com/photo-1482235225574-c37692835cf3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Dad"
}
]
},
{
"data": [
{
"id": 2,
"image": "https://images.unsplash.com/photo-1551445523-324a0fdab051?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Apple"
},
{
"id": 3,
"image": "https://images.unsplash.com/photo-1553279768-865429fa0078?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Mango"
},
{
"id": 4,
"image": "https://images.unsplash.com/photo-1502741338009-cac2772e18bc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Blueberry"
}
]
},
{
"data": [
{
"id": 5,
"image": "https://images.unsplash.com/photo-1459411621453-7b03977f4bfc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "broccoli"
},
{
"id": 6,
"image": "https://images.unsplash.com/photo-1531170887152-6b21ba4ce8ae?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "cucumber"
},
{
"id": 7,
"image": "https://images.unsplash.com/photo-1564874997803-e4d589d5fd41?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "tomato"
},
{
"id": 8,
"image": "https://images.unsplash.com/photo-1506807803488-8eafc15316c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "beetroot"
}
]
},
{
"data": [
{
"id": 9,
"image": "https://images.unsplash.com/photo-1518674660708-0e2c0473e68e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Pen"
},
{
"id": 10,
"image": "https://images.unsplash.com/photo-1516962215378-7fa2e137ae93?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Pencil"
},
{
"id": 11,
"image": "https://images.unsplash.com/photo-1541963463532-d68292c34b19?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Book"
},
{
"id": 12,
"image": "https://images.unsplash.com/photo-1527239441953-caffd968d952?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Papers"
},
{
"id": 13,
"image": "https://images.unsplash.com/photo-1551818014-7c8ace9c1b5c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60",
"word": "Pendrive"
}
]
}
]
the file in which i am trying to display JSON is this:
GameIntro.js
import React from 'react';
import {gdatas} from './gamedata';
const GameIntro = () => {
const gameData = gdatas.map(gd => {
gd.data.map(elm =>(
<div className="card">
<img src={elm.image} className="card-img-top" alt={elm.word} />
<div className="card-body">
<h5 className="card-title mt-3">{elm.word}</h5>
</div>
</div>
))
})
return (
<div className='container'>
<div className="row">
<div className="col-md-6">
{gameData}
</div>
</div>
</div>
)
}
export default GameIntro;
This component GameIntro.js is unable to display JSON.
You are not returning any data from the map function.
Add the return and add a key and you good to go:
const GameIntro = () => {
const gameData = gdatas.map(gd => {
return gd.data.map(elm =>(
<div key={elm.id} className="card">
<img src={elm.image} className="card-img-top" alt={elm.word} />
<div className="card-body">
<h5 className="card-title mt-3">{elm.word}</h5>
</div>
</div>
))
});
return (
<div className='container'>
{gameData}
</div>
)
}

How to retain a selected value while going through the router in Angular

I am very new to angular (currently I believe I am using angular 2) and I'm trying to build an app which will enable a user to select and customise a bundle of products. In order to do this I have imported a JSON file of the product details into the app as follows.
{
"data": {
"adverts": [],
"bundles": [{
"id": "1",
"name": "Bronze Bundle",
"price": {
"installation": "99.99",
"recurring": "23.99"
},
"products": ["1", "2", "3", "4", "9", "10", "15", "15"]
}, {
"id": "2",
"name": "Silver Bundle",
"price": {
"installation": "99.99",
"recurring": "23.99"
},
"products": ["1", "2", "2", "2", "2", "4", "9", "10", "15", "15"]
}, {
"id": "3",
"name": "Gold Bundle",
"price": {
"installation": "99.99",
"recurring": "25.99"
},
"products": ["1", "2", "4", "5", "9", "10", "15", "15"]
}, {
"id": "4",
"name": "Build Your Own Bundle",
"price": {
"installation": "49.99",
"recurring": "9.99"
},
"products": ["1", "10"]
}],
"products": [{
"id": "1",
"name": "Product 1",
"price": {
"upfront": null,
"installation": "0.00",
"recurring": "0.00"
}
}, {
"id": "3",
"name": "Product 3",
"price": {
"upfront": "132.00",
"installation": "9.60",
"recurring": "2.75"
}
}, {
"id": "4",
"name": "Product 4",
"price": {
"upfront": "60.00",
"installation": "9.60",
"recurring": "1.25"
}
}, {
"id": "2",
"name": "Product 2",
"price": {
"upfront": "60.00",
"installation": "9.60",
"recurring": "1.25"
}
},{
"id": "5",
"name": "Product 5",
"price": {
"upfront": "228.00",
"installation": "9.60",
"recurring": "4.75"
}
}, {
"id": "6",
"name": "Product 6",
"price": {
"upfront": "96.00",
"installation": "9.60",
"recurring": "2.00"
}
}]
}
}
My next goal was to import the bundle values into an App component (in this case with the class OrderComponent) and create a select method which would enable a user to select a bundle.
import { Component, Input, OnInit } from '#angular/core';
import { Headers, Http, Response } from '#angular/http';
import { Bundle } from './bundle';
import { Peripherals } from './peripherals';
import { OrderInfo } from './order.service';
#Component({
selector: 'my-order',
template: `
<h1>Select Bundle</h1>
<ul class="bundles">
<li *ngFor="let bundledata of Bundle"
[class.selected]="bundledata === selectedBundle"
(click)="onSelect(bundledata)" >
<h2>{{bundledata.id}}: {{bundledata.name}}</h2>
<p>{{bundledata.description}}</p>
</li>
</ul>
<bundle-detail [bundle]="this.selectedBundle"></bundle-detail>
`,
providers: [OrderInfo]
})
export class OrderComponent {
constructor(private orderInfo: OrderInfo) { }
selectedBundle: Bundle;
Bundle: {};
getBundles(): void {
this.Bundle = this.orderInfo.getBundles();
}
ngOnInit(): void {
this.getBundles();
}
onSelect(bundledata: Bundle): void {
this.selectedBundle = bundledata;
};
My problem now is that when I navigate to another component in the App the value of this.selectedBundle resets to it's default value of null.
What I would like to happen is that the app remembers which bundle has been selected so that I can use this data at a later point. If anyone could point me in the right direction on how to do this I would greatly appreciate it.
My routing method is coded into the App Component st follows
import { Component } from '#angular/core';
import { Bundle } from './bundle';
import { Peripherals } from './peripherals';
import { OrderInfo } from './order.service';
#Component({
selector: 'my-app',
template: `
<nav>
<a routerLink="/dashboard">Dashboard</a>
<a routerLink="/order">Order</a>
<a routerLink="/customise">Customise Bundle</a>
</nav>
<router-outlet></router-outlet>
`
})
export class AppComponent {
title = 'Bundle App';
}
and this is referenced in the App Module
NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot([
{
path: '',
redirectTo: '/dashboard',
pathMatch: 'full'
},
{
path: 'dashboard',
component: DashboardComponent
},
{
path: 'order',
component: OrderComponent
},
{
path: 'customise',
component: ProductDetailComponent
}
])
],
As you navigate from one route to another, a component is destroyed and a new component is initiated. Note that this is not the case if the newly routed component is a child of the first component but let us not dig deep into this hole.
The solution to this issue is to have a singleton service that holds the state of of the "selectedBundle". "selectedBundle" in your component now is a function that gets its data form the service. In your component typescript and html replace selectedBundle by the selectedBundle() function resolution
export class OrderComponent {
constructor(private orderInfo: OrderInfo
private bundleService: BundleService
) { }
Bundle: {};
getBundles(): void {
this.Bundle = this.orderInfo.getBundles();
}
ngOnInit(): void {
this.getBundles();
}
onSelect(bundledata: Bundle): void {
this.bundleService.setSelected(bundledata)
};
selectedBundle(){
return this.bundleService.getSelected()
}
Here is the new service
import { Injectable } from '#angular/core';
#Injectable()
export class BundleService {
selectedBundle: Bundle
setSelected(bundledata: Bundle) {
this.selectedBundle = bundledata;
}
getSelected() {
return this.selectedBundle
}
}

Categories