Can't use .map() on array from Untappd Business API - reactjs

I'm working with the unTappd API to create a tap list for a website. I've used axios to pull in the data and store it in state. So far I've been able to connect to the api and display data with that conditional. The conditional was returning true and I was able to display the brewery.name but once I added the .map it was showing undefined. I've checked and brewery.items is truthy so I'm not sure whats up. Here's the output from the console.log
Object
created_at : "2016-12-24T03:46:21.229877Z"
description : ""
id :39418
items : (13) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
menu_id : 10416
name : "Beer List"
position : 0
public : true
type : "Section"
updated_at : "2018-09-03T21:55:14.232759Z"
__proto__ : Object
Output of the items objects:
Array(13)
0
:
{id: 6101131, section_id: 39418, position: 0, untappd_id: 2638818, label_image: "https://untappd.akamaized.net/site/brewery_logos/brewery-219856_0fbfb.jpeg", …}
1
:
{id: 4449771, section_id: 39418, position: 1, untappd_id: 2465457, label_image: "https://untappd.akamaized.net/site/brewery_logos/brewery-219856_0fbfb.jpeg", …}
2
:
{id: 6908154, section_id: 39418, position: 2, untappd_id: 801790, label_image: "https://untappd.akamaized.net/site/beer_logos/beer-801790_dd500_sm.jpeg", …}
3
:
{id: 5356739, section_id: 39418, position: 3, untappd_id: 1238244, label_image: "https://untappd.akamaized.net/site/beer_logos/beer-1238244_5ba42_sm.jpeg", …}
4
:
{id: 8086786, section_id: 39418, position: 4, untappd_id: 2719716, label_image: "https://untappd.akamaized.net/site/brewery_logos/brewery-219856_0fbfb.jpeg", …}
5
:
{id: 7623610, section_id: 39418, position: 5, untappd_id: 2791052, label_image: "https://untappd.akamaized.net/site/beer_logos/beer-2791052_0985c_sm.jpeg", …}
6
:
{id: 5882390, section_id: 39418, position: 6, untappd_id: 1238253, label_image: "https://untappd.akamaized.net/site/beer_logos/beer-1238253_bf376_sm.jpeg", …}
7
:
{id: 7723598, section_id: 39418, position: 7, untappd_id: 2800225, label_image: "https://untappd.akamaized.net/site/brewery_logos/brewery-219856_0fbfb.jpeg", …}
8
:
{id: 7975683, section_id: 39418, position: 8, untappd_id: 2707563, label_image: "https://untappd.akamaized.net/site/brewery_logos/brewery-219856_0fbfb.jpeg", …}
9
:
{id: 7548213, section_id: 39418, position: 9, untappd_id: 2767218, label_image: "https://untappd.akamaized.net/site/brewery_logos/brewery-219856_0fbfb.jpeg", …}
10
:
{id: 7975604, section_id: 39418, position: 10, untappd_id: 2820742, label_image: "https://untappd.akamaized.net/site/brewery_logos/brewery-219856_0fbfb.jpeg", …}
11
:
{id: 7777162, section_id: 39418, position: 11, untappd_id: 2587293, label_image: "https://untappd.akamaized.net/site/beer_logos/beer-2587293_49972_sm.jpeg", …}
12
:
{id: 7777158, section_id: 39418, position: 12, untappd_id: 2681664, label_image: "https://untappd.akamaized.net/site/beer_logos/beer-2681664_e47db_sm.jpeg", …}
length
:
13
Here's the component that I'm working with: I've only set up that conditional for testing purposes. If I were to remove the beers map the page runs fine and displays the menu name.
I'm confused what I'm doing wrong here to map this function. I had trouble with this before which is why I map through section in the response. Any ideas would be helpful!
import { Component } from "react";
import axios from 'axios';
class Untappd extends Component {
constructor(){
super();
this.state = {
brewery: []
}
}
componentWillMount() {
axios({
method:'get',
url:'https://business.untappd.com/api/v1/menus/10416?full=true',
headers: {
"authorization": "Basic UN_API_KEY_HERE"
}
})
.then(res => {
let section = res.data.menu.sections.map((section, index) => {
return section
});
this.setState({ brewery: section["0"] });
console.log(this.state.brewery);
});
}
render() {
const { brewery } = this.state
const beers = brewery.items.map((beer, index) => {
<li key={index}>{beer.id}</li>
})
return(
<div>
<h1>{brewery && <h1 style={{zIndex: "9999",position: "absolute", color: "red"}}>{brewery.name}</h1>}</h1>
<ul>{beers}</ul>
</div>
)
}
}
export default Untappd;

You aren't returning anything in your brewery.items.map call
const beers = brewery.items.map((beer, index) => {
// this will not return
<li key={index}>{beer.id}</li>
});
You should do this to return your <li />. (Or you can use an explicit return statement in your anonymous function)
const beers = brewery.items.map((beer, index) => (
<li key={index}>{beer.id}</li>
));

within the map we may have to return the li.
const beers = brewery.items.map((beer, index) => (
return <li key={index}>{beer.id}</li>
));

Here's my updated code that is working after thinking about it a little harder. Now I have the tap list I need. Only problem is that it doesn't load until a second after the page is fully rendered. Anyone have any ideas of what could cause this?
import { Component } from "react";
import axios from 'axios';
class Untappd extends Component {
constructor(){
super();
this.state = {
brewery: []
}
}
componentDidMount() {
axios({
method:'get',
url:'https://business.untappd.com/api/v1/menus/10416?full=true',
headers: {
"authorization": "Basic AUTH_TOKEN_HERE"
}
})
.then(res => {
let items = res.data.menu.sections["0"].items.map((items)=>{
return items
})
this.setState({ brewery: items });
});
}
render() {
const { brewery } = this.state
const beers = brewery.map((beer, index) => {
return(
<li key={index}>{beer.name}</li>
);
});
console.log(brewery)
return(
<div>
<h1>Beer List</h1>
<ul>{beers}</ul>
</div>
)
}
}
export default Untappd;

Related

navigating results in changes of state in react after passing state to Link component

I'm making a purchase invoice app in react.
There are two pages in the app now.
One is a page to create new invoice which can be saved to database and exported to excel file. (Invoice.js)
The other is a page of a list of invoices each of them having modify/delete button. (Invoices.js)
When an invoice in the list's modify button is clicked, it links to the creation-page, and the invoice data, which is a state, are passed as parameter.
Without passing invoice data to the creation page, navigating had no problem at all.
However, after I put 'state' property to the Link component, the following error occurs.
Invoices.js:21
Uncaught TypeError: Cannot read properties of undefined (reading 'substring')
at Invoices.js:21:1
at Array.filter ()
at Invoices.js:21:1
at invokePassiveEffectCreate (react-dom.development.js:23487:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)
at invokeGuardedCallback (react-dom.development.js:4056:1)
at flushPassiveEffectsImpl (react-dom.development.js:23574:1)
at unstable_runWithPriority (scheduler.development.js:468:1)
at runWithPriority$1 (react-dom.development.js:11276:1)
Here are my source codes
// App.js
const App = () => {
return (
<BrowserRouter>
<Container maxWidth="lg">
<NavBar />
<Routes>
<Route path="/" exact element={<Navigate to="/invoice/create" />} />
<Route path="/invoice/create" element={<Invoice />} />
<Route path="/invoice/view" element={<Invoices />} />
</Routes>
</Container>
</BrowserRouter>
);
};
// Invoices.js
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getInvoices } from '../../actions/invoices';
import InvoiceRow from './InvoiceRow';
const Invoices = () => {
const [month, setMonth] = React.useState(new Date().getMonth() + 1);
const invoices = useSelector((state) => state.invoices);
const dispatch = useDispatch();
const [invoicesCurrent, setInvoicesCurrent] = React.useState([]);
useEffect(() => {
dispatch(getInvoices());
}, [dispatch]);
useEffect(() => {
setInvoicesCurrent(invoices.filter((invoice) => Number(invoice.invoiceDate.substring(5, 7)) === month));
}, [invoices, month, dispatch]);
...
// Link component used: invoice is the one of invoice in invoices state
<Link to='/invoice/create'
state={{ ...invoice }}>
<Button>Modify</Button>
</Link>
// Invoice.js
const InvoiceComponent = () => {
const location = useLocation();
const invoice = location.state;
const [company, setCompany] = useState(invoice ? invoice.company : '');
const [employee, setEmployee] = useState(invoice ? invoice.employee : '');
const [invoiceDate, setInvoiceDate] = useState(invoice ? invoice.invoiceDate : new Date());
const [orderId, setOrderId] = useState(invoice ? invoice.orderId : '');
const [companyTel, setCompanyTel] = useState(invoice ? invoice.companyTel : '');
const [companyFax, setCompanyFax] = useState(invoice ? invoice.companyFax : '');
const items = useSelector((state) => state.items);
const dispatch = useDispatch();
useEffect(() => {
const last = document.getElementById(`row-${items.length - 1}-0`);
if (last != null) last.focus();
}, [items.length]);
useEffect(() => {
if (invoice) {
dispatch(updateItems(invoice.items));
}
}, [dispatch, invoice]);
...
I must share current app behavior.
When 'Modify' button clicked, creation page is loaded with invoice data.
Then navigating with 'Go back', 'Go forward', or clicking a link to any of both pages shows the upper error.
in the useEffect hook in Invoices.js that calls setInvoicesCurrent,
when I console.log(invoices), it is not an array of invoice, rather it is an array of other state(items), which was used in Invoice.js
Refreshing the page makes all thing reset.
Is there any guideline for managing redux store when navigating?
// console.log(invoices) in useEffect calling setInvoicesCurrent
// Normally opened: invoices (6) [{…}, {…}, {…}, {…}, {…},
{…}] 0: {_id: '1', company: 'cmp1', employee: 'e1', invoiceDate:
'2022-01-07T05:14:15.482Z', orderId: '', …} 1: {_id: '2', company:
'cmp2', employee: 'e1', invoiceDate: '2022-01-07T05:14:15.482Z',
orderId: '', …} 2: {_id: '3', company: 'comp3', employee: 'e1',
invoiceDate: '2022-01-07T05:14:15.482Z', orderId: '', …} 3: {_id:
'4', company: 'comp4', employee: 'e1', invoiceDate:
'2022-01-07T05:14:15.482Z', orderId: '', …} 4: {_id: '5', company:
'comp5', employee: 'e1', invoiceDate: '2022-01-07T05:14:15.482Z',
orderId: '', …} 5: {_id: '6', company: 'comp6', employee: 'e1',
invoiceDate: '2022-01-07T13:10:56.380Z', orderId: '', …} length: 6
[[Prototype]]: Array(0)
Each Array has the following data
0:
company: "cmp1"
companyFax: "1222222222" companyTel: "122331232" employee:
"e1" invoiceDate: "2022-01-07T05:14:15.482Z" items:
Array(2) 0: {name: 'item1', spec: 'spec1', qty: 1, price: 10000,
total: 10000, …} 1: {name: 'item2', spec: 'spec2', qty: 20,
price: 1000, total: 20000, …} length: 2 [[Prototype]]:
Array(0) modifiedOn: "2022-01-07T05:25:14.771Z" orderId:
""
__v: 0
_id: "1"
// console.log(invoices) when ERROR occurs: invoices (6)
[Array(2), Array(2), Array(2), Array(2), Array(2), Array(2)] 0:
Array(2) 0: {name: 'item1', spec: 'spec1', qty: 1, price:
10000, total: 10000, …} 1: {name: 'item2', spec: 'spec2', qty:
20, price: 1000, total: 20000, …} length: 2
[[Prototype]]: Array(0) 1: Array(2) 0: {name: 'item1',
spec: 'spec1', qty: 1, price: 10000, total: 10000, …} 1: {name:
'item2', spec: 'spec2', qty: 20, price: 1000, total: 20000, …}
length: 2 [[Prototype]]: Array(0) 2: (2) [{…}, {…}]
3: (2) [{…}, {…}] 4: (2) [{…}, {…}] 5: (2) [{…}, {…}]
length: 6 [[Prototype]]: Array(0)
You should not destructure the array to an object, It creates an object.
use like below
// Invoices.js
<Link to="/invoice/create" state={{ invoice }}>
<Button>Modify</Button>
</Link>;
// Invoice.js
const { invoice } = location.state;
Note:
const a = [1,2,3];
console.log({...a}); // {0: 1, 1: 2, 2: 3}

How to properly map results from api fetch react

I've got my fetch request setup and properly retrieving the data from the API. However, I'm receiving the 'Unhandled Rejection (TypeError): items.map is not a function' error when I try to map the results into list items. How am I meant to map out the 'titles' into deliverables?
Here's my current setup:
Output of fetch request
{1: {…}, 2: {…}, 3: {…}, 4: {…}, 6: {…}, 7: {…}, 8: {…}, 9: {…}}
1:
entries: "598"
id: "1"
title: "Newsletter SignUp"
__proto__: Object
2: {id: "2", title: "Contact Page Form", entries: "663"}
3: {id: "3", title: "Sidebar RFI", entries: "114"}
4: {id: "4", title: "White Paper Email Sign-Up", entries: "72"}
6: {id: "6", title: "White Paper Registration", entries: "84"}
7: {id: "7", title: "Services RFI", entries: "766"}
__proto__: Object
Code to fetch / render from api
componentDidMount() {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "Basic XXX");
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch("https://www.example.com/wp-json/gf/v2/forms", requestOptions)
.then(res => res.json())
.then(
(result) => {
console.log(result);
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const { error,
isLoaded,
items
} = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div>
<div>
{items.map(item => (
<li key={item.title}>
{item.title}
</li>
))}
</div>
</div>
);
}
}
This is a question about javascript basics, not react or apis. The question is really how to map over an object with object as values.
One way is to get the keys (like SomoKRoceS shows) is Object.keys:
Object.keys(obj).map(key => (
<li key={obj[key].title}>
{items[obj].title}
</li>
))
Another way is to "for in" :
for (const key in obj) {
if (obj.hasOwnProperty(prop)) {
list.push(<li key={obj[key].title}>{items[obj].title}</li>)
}
}
return list;
Another way is Object.values:
Object.values(obj).map(val => <li key={val.title}>{val.title}</li>)
You can do something like this:
export default class Example extends React.Component {
// Your state will look something like this after the get request
state = {
result: {
1: { id: "1", title: "Contact Page Form", entries: "663" },
2: { id: "2", title: "Contact Page Form", entries: "663" },
3: { id: "3", title: "Sidebar RFI", entries: "114" },
4: { id: "4", title: "White Paper Email Sign-Up", entries: "72" },
6: { id: "6", title: "White Paper Registration", entries: "84" },
7: { id: "7", title: "Services RFI", entries: "766" }
}
};
renderResult = () => {
const res = Object.values(this.state.result);
return res.map(item => <div>{item.title}</div>);
};
render() {
return <div>{this.renderResult()}</div>;
}
}
Live demo here: https://codesandbox.io/s/polished-river-kueyq?file=/src/App.js:51-738
map() is a method applied on arrays. You can create an array of all indexes of the object, and then map over it - for each element, get the value of that key from the original object.
So you can do something like this:
return (
<div>
<div>
{Object.keys(items).map(item => (
<li key={items[item].title}>
{items[item].title}
</li>
))}
</div>
</div>
);
Object.keys(items) will create an array of all keys in items which is [1,2,3,...], then the map will iterate over that array and you will be able to access the desired object with that key with items[item].

Get return function to display the categorized results on the web page

I have the following Alignments.js react component using the new useState and useEffect React hooks, which works great by the way. It displays a list of alignments:
import React, {useState, useEffect} from 'react';
import './App.css';
import {Link} from 'react-router-dom';
function Alignments() {
useEffect(() => {
fetchItems();
},[]);
const [items, setItems] = useState([]);
const fetchItems = async () => {
const data = await fetch('http://localhost:3001/alignments');
const items = await data.json();
setItems(items);
console.log(items);
};
return (
<div>
{items.map(item => (
<ul align="left" key={item.id}>
<h2><Link to={`/alignments/${item.alignment}`}> {item.alignment}</Link></h2>
</ul>
))}
</div>
);
}
export default Alignments;
console.log(items)
(30) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {id: 1, aligngrp1: "I124", aligngrp2: "I124", alignment: "I124", length: 9699.999985122007, …}
1: {id: 2, aligngrp1: "I124", aligngrp2: "Cross_Streets", alignment: "12th", length: 1535.818272652023, …}
2: {id: 3, aligngrp1: "I124", aligngrp2: "Cross_Streets", alignment: "13th", length: 391.437434891255, …}
3: {id: 4, aligngrp1: "I124", aligngrp2: "Cross_Streets", alignment: "4th", length: 1032.43200821333, …}
4: {id: 5, aligngrp1: "I124", aligngrp2: "Cross_Streets", alignment: "6th", length: 999.9999994234385, …}
27: {id: 28, aligngrp1: "I124", aligngrp2: "Ramps", alignment: "Ramp_O", length: 927.6421496634126, …}
28: {id: 29, aligngrp1: "I124", aligngrp2: "Ramps", alignment: "Ramp_P", length: 1418.010004687435, …}
29: {id: 30, aligngrp1: "I124", aligngrp2: "Ramps", alignment: "Ramp_R", length: 444.908879095785, …}
Okay, so now that I've fetched these alignments from my database, and they're sitting in this items array, I want to put them in categories based on a column in the table called 'aligngrp2'. Where do I add the following code so that it runs after the fetch has completed?
const cats = items.reduce((catsSoFar, { aligngrp2, alignment }) => {
if (!catsSoFar[aligngrp2]) catsSoFar[aligngrp2] = [];
catsSoFar[aligngrp2].push(alignment);
return catsSoFar;
}, {});
console.log(cats);
};
or even better,
const cats = _.groupBy(items, 'aligngrp2');
I don't believe I can just add this arbitrarily to the Alignments component (which is what I did just to see a console.log of it). It shows 3 arrays, one for each aligngrp2, just the way I want it to be displayed on the web page:
{I124: Array(1), Cross_Streets: Array(12), Ramps: Array(17)}
I124: Array(1)
0: "I124"
length: 1
__proto__: Array(0)
Cross_Streets: Array(12)
0: "12th"
1: "13th"
2: "4th"
3: "6th"
length: 12
__proto__: Array(0)
Ramps: Array(17)
14: "Ramp_O"
15: "Ramp_P"
16: "Ramp_R"
length: 17
__proto__: Array(0)
Now to modify the return function in Alignments.js to display the alignments grouped by aligngrp2. If I change items.map to cats.map, it gives an error that cats.map is not a function. I tried different code to try to display this but to no avail. Do I unset items and then somehow re-add the newly grouped items? Can't figure out how to get the return function to display the new grouped list of alignments.
you can use this Function:
const groupBy = (items, key) =>
items.reduce(
(result, item) => ({
...result,
[item[key]]: [...(result[item[key]] || []), item],
}),
{},
)
then you can get the result :groupedData = groupBy(items, 'aligngrp2')
You could use Lodash,
Let cats = _.groupBy(items, item => item.aligngrp2);
UPDATE
I appreciate #Maria-Elena 's solution, it prevents using a huge library as lodash, if it works I advice using it instead of my solution
Example code to display, I didn't try the code :
cats.map((item, index) => { return ( <div key={index}> <strong>{item.aligngpr2}</strong> { Object.keys(item).map((key, i) => { return ( <ul ><li>{item[Key]}</li></ul> ) }) } </div> ) }

Using React to display List of Cruise Ships by Cruise Line

At the moment I am doing a website on cruise ships using React.
I have got so far with it, but now I am stumped on how I can show List of Ships based on the specific Cruise Lines.
Note: that this is on the Cruise Lines Page.
Here is a link to my repository (https://github.com/RobertWSON/Personal-ship-project/tree/practice-animation-react-slick) and the up to date code is on practice-animation-react-slick branch
I have used map function in listofShips.jsx component
This website example I found doesn't use react, but shows ships based on specific cruise.
I also want to have my list expand and collapse for the specific cruise lines and I might use Accordian to do this.
The code below is what I have in my ListofShips component, but this is only good for displaying all cruise ships, which I don't want.
import React from 'react'
import {Link} from 'react-router-dom'
import {getAllShips} from '../api/api'
class ListofShips extends React.Component {
constructor(props){
super(props)
this.state = {
shipList: []
}
this.setUpShips = this.setUpShips.bind(this)
}
componentDidMount(){
console.log('cdm')
this.setUpShips()
}
setUpShips() {
console.log('getallships')
getAllShips()
.then(res =>{
this.setState({
shipList: res
})
})
}
buildShipName(ship) {
return ship.cruise_line ? (ship.cruise_line + ': ' + ship.ship_name) : ship.ship_name
}
render() {
return (
<React.Fragment>
{this.state.shipList.map(ship => {
return <li className="shipsList" key={ship.cruise_line + '-' + ship.ship_name}><Link to={`/ship/${ship.id}`} >{this.buildShipName(ship)}</Link></li>
})}
</React.Fragment>
// </div>
)
}
}
export default ListofShips
My expected result is to have lists of ships for specific cruise lines.
I would also like to have expanding and collapsing lists for each cruise line.
If you want to filter the result to a specific cruise line, the easiest solution would be Array.prototype.filter method.
// Copied from seeds/ships.js
const ships = [
{
id: 1,
cruise_line: "Royal Caribbean",
ship_name: "Symphony of the Seas",
img: "/images/Symphone-of-the-Seas-heading-left-OU2.jpg",
Year: 2018,
Gross_Tonnage: 228081,
Passenger_Full_Capacity: 6680,
Double_Occupancy_Passenger_Capacity: 5518,
Length: 362.1,
Beam: 47.448,
Draft: 9.322,
Height: 72.5,
Loaded_Displacement: 120000,
Deadweight: 18095,
Review: ''
},
{
id: 5,
cruise_line: "Fred Olsen",
ship_name: "Boudicca",
img: "/imagwes/Boudicca_at_Funchal_2016_(bigger).jpg",
Year: 1973,
Gross_Tonnage: 28372,
Passenger_Full_Capacity: 900,
Double_Occupancy_Passenger_Capacity: 880,
Length: 206.96,
Beam: 25.22,
Draft: 7.55,
Height: 45,
Loaded_Displacement: 21156,
Deadweight: 5956,
Review: ''
},
{
id: 6,
cruise_line: "Fred Olsen",
ship_name: "Black Watch",
img: '',
Year: 1972,
Gross_Tonnage: 28613,
Passenger_Full_Capacity: 868,
Double_Occupancy_Passenger_Capacity: 804,
Length: 205.47,
Beam: 25.20,
Draft: 7.55,
Height: 45,
Loaded_Displacement: 20704,
Deadweight: 5656,
Review: ''
},
];
// "Royal Caribbean" only
const shipsOne = ships.filter(ship => ship.cruise_line === 'Royal Caribbean');
// "Fred Olsed" only
const shipsTwo = ships.filter(ship => ship.cruise_line === 'Fred Olsen');
console.log(shipsOne); // Ship with ID 1
console.log(shipsTwo); // Ships with ID 5, 6
If you want to group the ships by cruise lines, your best bet is Array.prototype.reduce method.
// Copied from seeds/ships.js
const ships = [
{
id: 1,
cruise_line: "Royal Caribbean",
ship_name: "Symphony of the Seas",
img: "/images/Symphone-of-the-Seas-heading-left-OU2.jpg",
Year: 2018,
Gross_Tonnage: 228081,
Passenger_Full_Capacity: 6680,
Double_Occupancy_Passenger_Capacity: 5518,
Length: 362.1,
Beam: 47.448,
Draft: 9.322,
Height: 72.5,
Loaded_Displacement: 120000,
Deadweight: 18095,
Review: ''
},
{
id: 5,
cruise_line: "Fred Olsen",
ship_name: "Boudicca",
img: "/imagwes/Boudicca_at_Funchal_2016_(bigger).jpg",
Year: 1973,
Gross_Tonnage: 28372,
Passenger_Full_Capacity: 900,
Double_Occupancy_Passenger_Capacity: 880,
Length: 206.96,
Beam: 25.22,
Draft: 7.55,
Height: 45,
Loaded_Displacement: 21156,
Deadweight: 5956,
Review: ''
},
{
id: 6,
cruise_line: "Fred Olsen",
ship_name: "Black Watch",
img: '',
Year: 1972,
Gross_Tonnage: 28613,
Passenger_Full_Capacity: 868,
Double_Occupancy_Passenger_Capacity: 804,
Length: 205.47,
Beam: 25.20,
Draft: 7.55,
Height: 45,
Loaded_Displacement: 20704,
Deadweight: 5656,
Review: ''
},
];
const groupedShips = ships.reduce((acc, cur) => {
const currentCruiseLine = cur.cruise_line;
if (acc[currentCruiseLine]) {
return {
...acc,
[currentCruiseLine]: [...acc[currentCruiseLine], cur],
};
}
return {
...acc,
[currentCruiseLine]: [cur],
};
}, {});
console.log(groupedShips);

Issue while getting data from a web service (Angular 4)

I'm trying to get data from web service API
All i get is the data on console.
the web service requires ID so i post the id first and then getting data that related to that ID inside the web service, this is my component.
HTML:
<form #educationForm="ngForm" method="post">
<select [(ngModel)]="type_id" name="type_id" class="rounded-inputs20 col-md-2" id="getGrades">
<option selected="selected">Education type...</option>
<option id="" *ngFor="let type_id of name_en" [ngValue]="type_id.id">{{type_id.name_en}}</option>
</select>
</form>
<input type="button" name="previous" class="previous action-button-previous" value="Previous"/>
<input type="button" name="next" class="next action-button (click)="onSubmitGrade(educationForm)" value="next"/>
<fieldset>
<div class="col-md-12 text-center row schools">
<div class="col-md-6" *ngFor="let grade of grades">
<h6 style="font-size: 26px;" name="grades">
{{grade.name}}<input [value]="grade.id" id="select-all-grades6" type="checkbox">
</h6>
<br>
</div>
</div>
</fieldset>
TS:
private educationType() {
return this._http.get('https://crm.easyschools.org/api/
en/schools/create/educationtypes')
.subscribe(type_id => {
this.id = type_id.id;
this.name_en = type_id.data;
console.log(type_id.data);
});
}
onSubmitGrade(form: NgForm) {
let formData: FormData = new FormData();
// debugger;
formData.append('education_type_id', this.type_id);
this._http.post('https://crm.easyschools.org/api/en/schools/
create/getgrades', formData)
.subscribe(grades => {
// this.type_id = this.education_type_id;
this.id = this.type_id.id;
this.name = grades.data;
console.log(grades.data);
}, (err: HttpErrorResponse) => {
console.log(err);
});
}
The response i get from the console is:
(13) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0
:
{id: 11, name: "Elementary", lessons_per_day: 5, lesson_duration:
"08:21:20", day_start_at: "08:24:27", …}
1
:
{id: 13, name: "Secondary", lessons_per_day: 6, lesson_duration:
"09:25:25", day_start_at: "10:29:00", …}
2
:
{id: 16, name: "Castor Sharp", lessons_per_day: 12, lesson_duration:
"00:00:12", day_start_at: "17:30:00", …}
3
:
{id: 17, name: "Ifeoma Cochran", lessons_per_day: 12, lesson_duration:
"00:00:04", day_start_at: "23:09:00", …}
4
:
{id: 18, name: "Jermaine Tyson", lessons_per_day: 12, lesson_duration:
"00:00:14", day_start_at: "18:01:00", …}
5
:
{id: 19, name: "Quin Wells", lessons_per_day: 12, lesson_duration:
"00:00:04", day_start_at: "11:25:00", …}
6
:
{id: 20, name: "Hiram Coffey", lessons_per_day: 12, lesson_duration:
"00:00:04", day_start_at: "06:14:00", …}
7
:
{id: 21, name: "Shad Floyd", lessons_per_day: 12, lesson_duration:
"00:00:04", day_start_at: "21:01:00", …}
8
:
{id: 22, name: "Oleg Ball", lessons_per_day: 12, lesson_duration:
"00:00:41", day_start_at: "00:08:00", …}
9
:
{id: 23, name: "Ivory Gates", lessons_per_day: 12, lesson_duration:
"00:00:41", day_start_at: "16:33:00", …}
10
:
{id: 24, name: "Serina Edwards", lessons_per_day: 12, lesson_duration:
"00:00:41", day_start_at: "13:51:00", …}
11
:
{id: 25, name: "dsos", lessons_per_day: 44, lesson_duration:
"00:00:45",
day_start_at: "12:30:00", …}
12
:
{id: 26, name: "Nissim Hurley", lessons_per_day: 12, lesson_duration:
"00:00:04", day_start_at: "10:33:00", …}
length
:
13
__proto__
:
Array(0)
I need to be able to display the data on the console on the screen, but my code is not showing anything.
Feel free to use the API links to test and show me what is missing in my code.
I do not see anywhere you have grades declared in your template, have a variable declared and assign the response data to the variable.
grades :any = [];
and then
this._http.post('https://crm.easyschools.org/api/en/schools/ create/getgrades', formData) .subscribe(result=> { this.grades = result.data;}, (err: HttpErrorResponse) => { console.log(err); }); }
or with the existing template replace grades with name,
<div class="col-md-6" *ngFor="let grade of name"

Resources