How manage a json array of attributes for display in ReactJS - javascript

So, I have to return data from an API like the one below in the UI in React. Im a bit confused about the fact that in the attributes array, all data have the same names but point to different attributes. In a position it refers to name, the other gender and phone number. Whats the best way to deal with this type of api and return each atribute in the UI?
{
"data": [
{
"type": "Other",
"place": "US",
"attributes": [
{
"displayName": "name",
"value": "Jenna"
},
{
"displayName": "Gender",
"value": "Female"
},
{
"displayName": "Phone_number",
"value": "+12346543"
}
]
}
]
}
Code I have
import React from "react";
import People from "./data.json";
const Data = () => {
return (
<div>
{People.data.map((details) => (
<div>
<p>
Type: {details.type}
</p>
<p>
place: {details.place}
</p>
/*{ <p>name: {}</p> } */
/* { <p>gender: {}</p> */ }
/* {<p>phone number: {}</p> } */
</div>
))}
</div>
);
};
export default Data;

Use the method filter in details.attributes for select specifical displayName
details.attributes.filter(x => x.displayName === 'name')[0]

since you have nested array in this kind of api response you should iterate over the first list and then for each attributes list you can iterate and get your data. hope it will help, cheers.
import React from "react";
import People from "./data.json";
const Data = () => {
return (
<div>
{People.data.map((place) => (
<div>
// place data
{place.type}
{place.place}
{place.attributes.map(attribute => (
<div>
// attributes
{attribute.displayName}
{attribute.value}
</div>
)}
</div>
))}
</div>
);
};
export default Data;

import React from "react";
import People from "./data.json";
function App() {
const people = {
"data": [
{
"type": "Other",
"place": "US",
"attributes": [
{
"displayName": "name",
"value": "Jenna"
},
{
"displayName": "Gender",
"value": "Female"
},
{
"displayName": "Phone_number",
"value": "+12346543"
}
]
}
]
}
return (
<div>
{people.data.map((details) => (
<div>
<p>
Type: {details.type}
</p>
<p>
place: {details.place}
</p>
<p>
Name: {details.attributes.filter(x => x.displayName === 'name')[0].value}
</p>
<p>
Gender: {details.attributes.filter(x => x.displayName === 'Gender')[0].value}
</p>
<p>
Phone Number: {details.attributes.filter(x => x.displayName === 'Phone_number')[0].value}
</p>
</div>
))}
</div>
);
}
export default App;

Related

TypeError: Cannot read properties of undefined (reading 'map') (JavaScript array map)

In my React component, I am receiving the props, below is the component. I simply need to grab the props i.e. data and map it and render the data
Component
import * as React from "react";
import { Box } from "#chakra-ui/react";
import CourseCard from "./CourseCard";
import CourseGrid from "./CourseGrid";
const CardLayout = ({ data }) => {
console.log(data);
return (
<Box
maxW="7xl"
mx="auto"
px={{
base: "4",
md: "8",
lg: "12",
}}
py={{
base: "4",
md: "8",
lg: "12",
}}
>
<CourseGrid>
{data.getPs_courseList.map((course) => (
<CourseCard key={course.slug} course={course} />
))}
</CourseGrid>
</Box>
);
};
export default CardLayout;
Incoming Props
{
"getPs_courseList": [
{
"short_desc": "JavaScript for Beginners",
"slug": "javascript_for_beginners",
"price": "10$",
"trainer_name": "John",
"language": "English",
"level": "Beginner",
"length_in_minutes": "120"
},
{
"short_desc": "What is GraphQL?",
"slug": "what_is_graphql",
"price": "FREE",
"trainer_name": "Anita",
"language": "English",
"level": "Intermediate",
"length_in_minutes": "230"
}
]
}
when I am trying to use the map function like below, I am getting an error. Can anyone suggest what is it I am missing here?
{data.getPs_courseList.map((course) => (
<CourseCard key={course.slug} course={course} />
))}
Error
const CardLayout = ({ data }) => {
replace with
const CardLayout = ( data ) => {
Data is always filled? Maybe, when the component is called, data isn't true yet. So you can validate if Data is true before and then run de map method.
{ data &&
data.getPs_courseList.map((course) => (
<CourseCard key={course.slug} course={course} />
))}

How to fetch an array of objects and render it in the component as a normal text using React Hooks?

I want to display some cards information in my app fetching data from an API. Each customer has 1, 2 or 3 different cards, I'm using JWToken for authentication but I have not included it here. So, the API response is not static.
Request: GET "/xx/cards"
Response is an array of objects:
[
{
"cardId": "1",
"cardType": {
"3": "General Card"
},
"salutation": {
"1": "Mrs."
},
"firstName": "Test",
"lastName": "User",
"status": 'active',
"creationDate": "30.10.2020",
},
{
"cardId": "2",
"cardType": {
"2": "Special Card"
},
"salutation": {
"2": "Mr."
},
"firstName": "Test1",
"lastName": "User1",
"status": 'active',
"creationDate": "30.10.2020",
},
]
In The React Context:
const [cards, setCards] = useState<any>([]);
In MyCards.tsx component:
const MyCards: React.FC = () => {
const {
cards,
setCards,
} = React.useContext(AuthContext);
const [content, setContent] = useState([]);
useEffect(() => {
axios.get("/xx/cards").then(
(response) => {
setContent(response.data);
setCards(response.data);
},
(error) => {
const _content =
(error.response && error.response.data) ||
error.message ||
error.toString();
setContent(_content);
}
);
}, []);
return (
<React.Fragment>
<IonPage className="ion-page" id="main-content">
<IonContent className="ion-padding">
<h1>Your Cards</h1>
<p>{JSON.stringify(cards)}</p>
...HERE I should write some code but don't know what...
</IonContent>
</IonPage>
</React.Fragment>
);
};
export default MyCards;
I want to list the cards as a normal text (as following) in my component:
Mrs. Test User
Card Id: 1
Card Type: General Card
Mr. Test1 User1
Card Id: 2
Card Type: Special Card
How to achieve this ? I don't really know how to set state for an array of objects.
Any help would be appreciated. Thanks :)
a solution would be to use the map function on your array see here
return(
...
{
cards.map(card => (
<p>
{card.firstName} {card.lastname}<br/>
Card Id: {card.cardId}<br/>
...
</p>
))
}
...
)
like this but for me there is a probleme in api with is all the key number in object ..
better option for iterate is array of object like this :
[
{
"cardId": "1",
"cardType": "General Card",
"salutation": "Mrs.",
"firstName": "Test",
"lastName": "User",
"status": 'active',
"creationDate": "30.10.2020",
},
...
]
I think what you're looking for is mapping through your array of objects and just displaying them, something like this:
...
<p>{JSON.stringify(cards)}</p>
{cards?.map(card => (
<div>
<p>{Object.values(card.salutation)[0] card.firstName card.lastName}</p>
<p>Card Id: {card.cardId}</p>
<p>Card type: {Object.values(card.cardType)[0]}</p>
</div>
))}
...

React - live search filter and search buttons

I'm new to React and I'm trying to create a live search filter plus a couple of button filters that shows images. It gets dummy JSON-like data for now.
I've managed to create the live search (as below in the code) but I'm now stuck in creating the extra filtering on top of it. I'd like to have three button that says "all", "top", "great" next to the live search field.
How can I filter specifically to look for tag names? In my example when I click on "Top" or "Great" it should filter through the original list and show the related data.
Any tip is appreciated...thanks!
import React, { useState } from 'react';
function App() {
const dataList = [
{
"id": 1,
"tag": "Top",
"name": "bubb",
"image": "../img/bubb.jpg"
},
{
"id": 2,
"name": "lin bubb",
"tag": "Great",
"image": "../img/lin.jpg"
},
{
"id": 3,
"name": "smam",
"tag": "Top",
"image": "../img/smam.jpg"
},
{
"id": 2,
"name": "jumanji",
"tag": "Top",
"image": ""
},
{
"id": 2,
"name": "fruit spin",
"tag": "Great",
"image": ""
}
];
const [searchText, setSearchText] = useState("");
const [data, setData] = useState(dataList);
// exclude column list from filter
const excludeColumns = ["id", "tag", "image"];
// handle change event of search input
const handleChange = value => {
setSearchText(value);
filterData(value);
};
// filter records by search text
const filterData2 = (value) => {
//need to filter when tag selected
}
// filter records by search text
const filterData = (value) => {
const lowercasedValue = value.toLowerCase().trim();
if (lowercasedValue === "") setData(dataList);
else {
const filteredData = dataList.filter(item => {
return Object.keys(item).some(key =>
excludeColumns.includes(key) ? false : item[key].toString().toLowerCase().includes(lowercasedValue)
);
});
setData(filteredData);
}
}
return (
<div className="App">
Search: <input
style={{ marginLeft: 5 }}
type="text"
placeholder="Type to search..."
value={searchText}
onChange={e => handleChange(e.target.value)}
/>
<span onClick={filterData2("all")}>All</span>
<span onClick={filterData2("Top")}>Top</span>
<span onClick={filterData2("Great")}>Great</span>
<div className="box-container">
{data.map((data, i) => {
return <div key={i} className="box" style={{ backgroundColor: data.color }}>
<img src={data.image}></img>
</div>
})}
<div className="clearboth"></div>
{data.length === 0 && <span>No records found to display!</span>}
</div>
</div>
);
}
export default App;

Material Table Get and Set Filter Values

How can I get and set the filter values programmatically using material-table?
I want users to be able to save filter configurations as reports and recall them as needed.
Get works with a hook on change:
onFilterChange={(filters) => {
console.log('onFilterChange', filters);
}}
result is an array of filter definitions per column, looks like:
[
// [...]
{
"column": {
"title": "Date",
"field": "file_date",
"type": "date",
"tableData": {
"columnOrder": 3,
"filterValue": "2020-11-10T15:20:00.000Z",
"groupSort": "asc",
"width": "...", // lots of css calc stuff... :(
"additionalWidth": 0,
"id": 4
}
},
"operator": "=",
"value": "checked"
}
]
setting the filter on mount could/should work with defaultFilter at each column definition.
There are two parts to this, the get and the set.
Get - handled through the use of the tableRef prop on the MaterialTable component
Set - handled through the defaultFilter value on a column object.
import MaterialTable from "material-table";
import React, { useRef } from "react";
import { tableIcons } from "./tableIcons";
const firstNameFilter = 'Neil'
function App() {
const tableRef = useRef<any>();
return (
<div>
<button onClick={saveFilters(tableRef)}>Filters</button> // GET OCCURS HERE
<MaterialTable
tableRef={tableRef}
icons={tableIcons}
columns={[
{ title: "First", field: "name", defaultFilter: firstNameFilter }, // SET OCCURS HERE
{ title: "Last", field: "surname" }
]}
data={[
{ name: "Neil", surname: "Armstrong" },
{ name: "Lance", surname: "Armstrong" },
{ name: "Bob", surname: "Hope" }
]}
options={{ filtering: true }}
title="Reports"
/>
</div>
);
}
function saveFilters(tableRef: React.MutableRefObject<any>) {
return function handler() {
const columns = tableRef?.current?.state.columns.map((column: any) => ({
field: column.field,
filterValue: column.tableData.filterValue
}));
console.log(JSON.stringify(columns, null, 2));
};
}
export { App };

Dynamically create DOM in ReactJS from json string

I have following JSON string from which I need to dynamically create DOM of the form:
{
"formData": [{
"inputType": "text",
"type": "string",
"min": 10,
"label": "Enter Name:",
"objectId": "test1"
}],
"gridLayout": {
"rows": [
{
"column": [
{
"width": "4",
"id": "test1"
}
]
}
]
}
}
from the gridLayout object, I wish to create bootstrap style grid. For instance, first rowobject of the JSON's "rows" has 1 column in the columns object with width of 4. Thus, the layout for that row should be
<div class="row">
<div class="col-md-4" id="test1">
</div>
</div>
Later, using formData object of JSON, TextBox component should be appended to grid layout like so:
<div class="row">
<div class="col-md-4" id="test1">
<TextBox />
</div>
</div>
For now, I have written code to display the TextBox component as it is without the grid layout in following way.
Form.jsx:
class Form extends React.Component {
getComponent = (formObj, index) => {
let returnString;
if (formObj.inputType === 'text') {
returnString = (<TextBox key={index} />);
}
return returnString;
}
render() {
let formData = JSON.parse(this.getData()).formData;
return (
<React.Fragment> {formData.map((o, index) => this.getComponent(o, index))} </React.Fragment>
);
}
}
Thus now, how do I dynamically create the Grid Layout and insert the TextBox component in it?
A solution can be achieved by using a combination of array methods. Use Array#map to render your gridLayout divs as necessary. Use Array#find to find the props of the correct TextBox from formData.
I've simplified formData, but added more rows and columns to give you a complete picture.
const data = {
"formData": [{
"label": "Enter Name:",
"objectId": "test1"
}, {
"label": "Enter Address:",
"objectId": "test2"
}, {
"label": "Enter Number:",
"objectId": "test3"
}, {
"label": "Enter Something:",
"objectId": "test4"
}],
"gridLayout": {
"rows": [{
"column": [{
"width": "4",
"id": "test1"
}, {
"width": "4",
"id": "test2"
}]
},
{
"column": [{
"width": "6",
"id": "test3"
}, {
"width": "6",
"id": "test4"
}]
}
]
}
}
const TextBox = ({ label }) => (
<React.Fragment>
<label>{label}</label>
</React.Fragment>
);
const Form = ({ data: { formData, gridLayout } }) => {
return gridLayout.rows.map(row => {
return (
<div class="row">
{row.column.map(col => {
const textBoxProps = formData.find(data => data.objectId === col.id);
// REPLACE col- with col-md-. Done here to demonstrate layout in small snippet output area
return (
<div className={`col-${col.width} borderedCol`}>
<TextBox {...textBoxProps} />
</div>
);
})}
</div>
);
});
};
ReactDOM.render(<Form data={data} />, document.getElementById("app"));
/* ONLY for demo purposes */
.borderedCol {
border: 1px solid;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Categories

Resources