Recursive functions to render data till nth level of nesting react - javascript

const data = [
{
"laboaratory": [
{
"status": {
display: "Code",
value: "23123"
},
"observation": [
{
display: "Code",
value: "23123"
}
],
"resultValue": {
"quantity": [
{
display: "Code",
value: "23123"
}
],
"codeableConcept": [
{
display: "Code",
value: "23123"
},
{
display: "Code",
value: "23123"
}
]
}
},
{
"status": {
display: "Code",
value: "23123"
},
"observation": [
{
display: "Code",
value: "23123"
}
],
"resultValue": {
"quantity": [
{
display: "Code",
value: "23123"
}
],
"codeableConcept": [
{
display: "Code",
value: "23123"
},
{
display: "Code",
value: "23123"
}
]
}
}
]
},
{
"medications": [
{
"status": {
display: "medications - Code",
value: "23123"
},
"resultValue": {
"quantity": [
{
display: "medications- Code",
value: "23123"
},
{
display: "medications-Code",
value: "23123"
}
],
"codeableConcept": [
{
display: "medications-Code",
value: "23123"
},
{
display: "medications- Code",
value: "23123"
}
]
}
},
{
"status": {
display: "medications - Code",
value: "23123"
},
"resultValue": {
"quantity": [
{
display: "medications- Code",
value: "23123"
}
],
"codeableConcept": [
{
display: "medications-Code",
value: "23123"
}
]
}
},
{
"status": {
display: "medications - Code",
value: "23123"
},
"resultValue": {
"quantity": [
{
display: "medications- Code",
value: "23123"
}
],
"codeableConcept": [
{
display: "medications-Code",
value: "23123"
}
]
}
}
]
}
]
Data Dipslay Format in UI (HTML View with accordion header and table data and where we can open and close the accordion)
-> Laboratory(Main Heading) <h1> Laboratory<h1/>
-> status (Sub-heading) <h3>stats<h3/>
Code - 23123 (table data) <table><th>Code</th><tr></tr>23123<table/>
-> observation (Sub-heading)
code - 1232 (table data)
code -12312
-> ResultValue (Sub-heading)
-> quantity (Sub -sub heading)
code - 1232 (table data)
code -12312
-> codeableConcept (Sub -sub heading)
code - 1232 (table data)
code -12312
-> medications(Main Heading)
-> status (Sub-heading)
medications-Code - 23123 (table data)
-> observation (Sub-heading)
medications-code - 1232 (table data)
medications-code -12312
-> ResultValue (Sub-heading)
-> quantity (Sub -sub heading)
medications-code - 1232 (table data)
medications-code -12312
-> codeableConcept (Sub -sub heading)
medications-code - 1232 (table data)
medications-code -12312
How can we display the data in UI by using above datasets ,it might have more nested data .I have to write a generic recursive code while can handle dynamic data rendering in UI without breaking ? The above structure should be like tree structure with accordion so that we can open and close the class and its related sub classes .(Just like a DOM tree like data structure) .Let me know if any further details are needed.
the data will be rendered in HTML view .
I tried using map to render the data its is becoming nested and its not generic .How can we handle data till nth level by using recursion and show in UI ?
data.map((data) => {
Object.keys(data).map((header) => {
//console.log(header)
data[header].map((headerData) => {
if(Array.isArray(data[header])) {
//console.log(headerData)
} else {
console.log(headerData)
}
})
})
})
And how can we handle pagination for every keys(laboratory ,medications) if any of the key is having more than one object ?(Attached screenshot below on how pagination will look on class level)

I made this recursive component which seems to achieve what you want. Of course it is up to you to style it properly :
function RecursiveComponent({ content, level = 1 }) {
const Header = `h${ level }`
if (Array.isArray(content))
return <>{ content.map((e, i) => <RecursiveComponent content={e} key={i} level={level} />) }</>
if (typeof content === 'object') {
if (content.display && content.value)
return <div style={{ display: 'flex', gap: '1em', justifyContent: 'center' }}>
<span>{ content.display }</span>
<span>{ content.value }</span>
</div>
return <>{
Object.keys(content).map(key =>
<div key={key}>
<Header>{ key }</Header>
{<RecursiveComponent content={content[key]} level={level + 1} />}
</div>
)
}</>
}
return <span>{ content }</span>
}
Hope it helped you !

If I understood accurately what you wanted, this seems to do the job :
import { useState } from 'react'
const data = [
{
"laboaratory": [
{
"status": {
display: "Code",
value: "23123"
},
"observation": [
{
display: "Code",
value: "23123"
},
{
display: "Code",
value: "23123"
}
],
"resultValue": {
"quantity": [
{
display: "Code",
value: "23123"
},
{
display: "Code",
value: "23123"
}
],
"codeableConcept": [
{
display: "Code",
value: "23123"
},
{
display: "Code",
value: "23123"
}
]
}
},
{
"status": {
display: "Code",
value: "Value on page 2"
},
"observation": [
{
display: "Code",
value: "Value on page 2"
},
{
display: "Code",
value: "Value on page 2"
}
],
"resultValue": {
"quantity": [
{
display: "Code",
value: "Value on page 2"
},
{
display: "Code",
value: "Value on page 2"
}
],
"codeableConcept": [
{
display: "Code",
value: "Value on page 2"
},
{
display: "Code",
value: "Value on page 2"
}
]
}
}
]
},
{
"medications": [
{
"status": {
display: "medications - Code",
value: "23123"
},
"observation": [
{
display: "medications -Code",
value: "23123"
},
{
display: "medications- Code",
value: "23123"
}
],
"resultValue": {
"quantity": [
{
display: "medications- Code",
value: "23123"
},
{
display: "medications-Code",
value: "23123"
}
],
"codeableConcept": [
{
display: "medications-Code",
value: "23123"
},
{
display: "medications- Code",
value: "23123"
}
]
}
},
{
"status": {
display: "medications - Code",
value: "Medication value on page 2"
},
"observation": [
{
display: "medications -Code",
value: "Medication value on page 2"
},
{
display: "medications- Code",
value: "Medication value on page 2"
}
],
"resultValue": {
"quantity": [
{
display: "medications- Code",
value: "Medication value on page 2"
},
{
display: "medications-Code",
value: "Medication value on page 2"
}
],
"codeableConcept": [
{
display: "medications-Code",
value: "Medication value on page 2"
},
{
display: "medications- Code",
value: "Medication value on page 2"
}
]
}
}
]
}
]
function App() {
return <RecursiveComponent content={data} />
}
function PaginatedComponent ({ content, level }) {
const [page, setPage] = useState(0)
const l = content.length - 1;
return <>
<div>
<button onClick={() => setPage(page => page - 1)} disabled={page === 0}>{'<'}</button>
<span>{ page + 1 } / { l + 1 }</span>
<button onClick={() => setPage(page => page + 1)} disabled={page === l}>{'>'}</button>
</div>
<RecursiveComponent level={level + 1} content={content[page]}></RecursiveComponent>
</>
}
function RecursiveComponent({ content, level = 1, paginated = level === 1 }) {
const Header = `h${ level }`
if (Array.isArray(content))
return <>{ content.map((e, i) => <RecursiveComponent content={e} key={i} level={level} />) }</>
if (paginated)
return <>{
Object.keys(content).map(key =>
<div key={key}>
<Header>{ key }</Header>
<PaginatedComponent key={key} content={content[key]} level={level} />
</div>
)
}</>
if (typeof content === 'object') {
if (content.display && content.value)
return <div style={{ display: 'flex', gap: '1em', justifyContent: 'center' }}>
<span>{ content.display }</span>
<span>{ content.value }</span>
</div>
return <>{
Object.keys(content).map(key =>
<div key={key}>
<Header>{ key }</Header>
<RecursiveComponent content={content[key]} level={level + 1} />
</div>
)
}</>
}
return <span>{ content }</span>
}
Hope it helped you !

Related

json filter nested array with javascript

I want to pull with javascript: {"subNav0", "subNav1", "subNav2", "subNav3", "subNav4", "subNav5"}.
my json:
var data = {
"menus":{
"GrandparentNav0":{
"name":"TopNav",
"items":[
{
"name":"ParentNav0",
"iconClass":"",
"items":[
{
"name":"ParentNav1",
"iconClass":"",
"items":[
{
"name":"subNav0",
"iconClass":""
},
{
"name":"subNav1",
"iconClass":""
},
{
"name":"subNav2",
"iconClass":""
},
{
"name":"subNav3",
"iconClass":""
},
{
"name":"subNav4",
"iconClass":""
},
{
"name":"subNav5",
"iconClass":""
}
]
},
]
}
]
}
},
};
i know basic filter of an array:
data .forEach(function(o) {
o.variable = o.variable.filter(s => s.value == value);
});
I dont know how to get through menus, GrandparentNav0 to pull the subNav(s)
By "pull the subNav(s)" do you mean like accessing it through something like bracket notation?
let subNavs = data['menus']['GrandparentNav0']['items'][0]['items']
console.log(subNavs)
/* would return
[
{
"name": "subNav0",
"iconClass": ""
},
{
"name": "subNav1",
"iconClass": ""
},
{
"name": "subNav2",
"iconClass": ""
},
{
"name": "subNav3",
"iconClass": ""
},
{
"name": "subNav4",
"iconClass": ""
},
{
"name": "subNav5",
"iconClass": ""
}
]
*/
Here is a solution using object-scan. This might be overkill for your requirements, however as you run into other use cases it's a Swiss army knife that makes these types of data interactions very clean
// const objectScan = require('object-scan');
const data = { menus: { GrandparentNav0: { name: 'TopNav', items: [ { name: 'ParentNav0', iconClass: '', items: [ { name: 'ParentNav1', iconClass: '', items: [ { name: 'subNav0', iconClass: '' }, { name: 'subNav1', iconClass: '' }, { name: 'subNav2', iconClass: '' }, { name: 'subNav3', iconClass: '' }, { name: 'subNav4', iconClass: '' }, { name: 'subNav5', iconClass: '' } ] } ] } ] } } };
const result = objectScan(['menus.GrandparentNav0.items[0].items[0].items[*].name'], { reverse: false, rtn: 'value' })(data);
console.log(result);
// => [ 'subNav0', 'subNav1', 'subNav2', 'subNav3', 'subNav4', 'subNav5' ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#14.0.0"></script>
Disclaimer: I'm the author of object-scan

Show data to Ag Grid Vue

I am trying to load data into the VueJS table using the ag Grid vue plugin that I have in a template, I have tried several ways but I am not getting the result I am looking for ..., getting the following result:
{
"users": [
{
"id": 1,
"client_id": 1,
"cop_id": null,
"role_id": null,
"name": "Bart",
"email": "correo.123#gmail.com",
"created_at": null,
"updated_at": null
}
]
}
then I have my Vue view in this way, and sorry for including all the code, but since the template is working with everything that comes, I prefer to deliver all the detail, I have tried to make changes to the created method with axios, but I did not It works, unfortunately I can't load the data into the table, I hope you can guide me to fix my loading error.
<template>
<div id="page-user-list">
<!-- AgGrid Table -->
<ag-grid-vue
ref="agGridTable"
:components="components"
:gridOptions="gridOptions"
class="ag-theme-material w-100 my-4 ag-grid-table"
:columnDefs="columnDefs"
:defaultColDef="defaultColDef"
:rowData="rowData"
rowSelection="multiple"
colResizeDefault="shift"
:animateRows="true"
:floatingFilter="true"
:pagination="true"
:paginationPageSize="paginationPageSize"
:suppressPaginationPanel="true"
:enableRtl="$vs.rtl">
</ag-grid-vue>
<vs-pagination
:total="totalPages"
:max="10"
v-model="currentPage" />
</div>
</template>
<script>
import { AgGridVue } from "ag-grid-vue"
import '#sass/vuexy/extraComponents/agGridStyleOverride.scss'
import vSelect from 'vue-select'
import axios from 'axios'
// Store Module
//import moduleUserManagement from '#/store/user-management/moduleUserManagement.js'
// Cell Renderer
import CellRendererLink from "./cell-renderer/CellRendererLink.vue"
import CellRendererStatus from "./cell-renderer/CellRendererStatus.vue"
import CellRendererVerified from "./cell-renderer/CellRendererVerified.vue"
import CellRendererActions from "./cell-renderer/CellRendererActions.vue"
export default {
components: {
AgGridVue,
vSelect,
// Cell Renderer
CellRendererLink,
CellRendererStatus,
CellRendererVerified,
CellRendererActions,
},
data() {
return {
// Filter Options
roleFilter: { label: 'Todos', value: 'all' },
roleOptions: [
{ label: 'Todos', value: 'all' },
{ label: 'Administador', value: 'admin' },
{ label: 'Usuario', value: 'user' },
{ label: 'Staff', value: 'staff' },
],
statusFilter: { label: 'Todos', value: 'all' },
statusOptions: [
{ label: 'Todos', value: 'all' },
{ label: 'Activo', value: 'active' },
{ label: 'Desactivado', value: 'deactivated' },
{ label: 'Bloqueado', value: 'blocked' },
],
isVerifiedFilter: { label: 'Todos', value: 'all' },
isVerifiedOptions: [
{ label: 'Todos', value: 'all' },
{ label: 'Si', value: 'yes' },
{ label: 'No', value: 'no' },
],
departmentFilter: { label: 'Todos', value: 'all' },
departmentOptions: [
{ label: 'Todos', value: 'all' },
{ label: 'Vendido', value: 'sales' },
{ label: 'Departamento', value: 'development' },
{ label: 'Administrado', value: 'management' },
],
searchQuery: "",
// AgGrid
gridApi: null,
gridOptions: {},
defaultColDef: {
sortable: true,
resizable: true,
suppressMenu: true
},
columnDefs: [
{headerName: 'ID', field: 'id', width: 125, filter: true, checkboxSelection: true, headerCheckboxSelectionFilteredOnly: true, headerCheckboxSelection: true },
{headerName: 'Username', field: 'client_id', filter: true, width: 210, cellRendererFramework: 'CellRendererLink'},
{headerName: 'Email', field: 'email', filter: true, width: 225 },
{headerName: 'Nombre', field: 'name', filter: true, width: 200 },
{headerName: 'Comuna', field: 'cop_id', filter: true, width: 150},
{headerName: 'Role', field: 'role_id', filter: true, width: 150},
{headerName: 'Acciones', width: 150, cellRendererFramework: 'CellRendererActions'},
],
// Cell Renderer Components
components: {
CellRendererLink,
CellRendererStatus,
CellRendererVerified,
CellRendererActions,
}
}
},
watch: {
roleFilter(obj) {
this.setColumnFilter("role", obj.value)
},
statusFilter(obj) {
this.setColumnFilter("status", obj.value)
},
isVerifiedFilter(obj) {
let val = obj.value === "all" ? "all" : obj.value == "yes" ? "true" : "false"
this.setColumnFilter("is_verified", val)
},
departmentFilter(obj) {
this.setColumnFilter("department", obj.value)
},
},
computed: {
usersData() {
return this.users.data
},
paginationPageSize() {
if(this.gridApi) return this.gridApi.paginationGetPageSize()
else return 10
},
totalPages() {
if(this.gridApi) return this.gridApi.paginationGetTotalPages()
else return 0
},
currentPage: {
get() {
if(this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1
else return 1
},
set(val) {
this.gridApi.paginationGoToPage(val - 1)
}
}
},
methods: {
setColumnFilter(column, val) {
const filter = this.gridApi.getFilterInstance(column)
let modelObj = null
if(val !== "all") {
modelObj = { type: "equals", filter: val }
}
filter.setModel(modelObj)
this.gridApi.onFilterChanged()
},
resetColFilters() {
// Reset Grid Filter
this.gridApi.setFilterModel(null)
this.gridApi.onFilterChanged()
// Reset Filter Options
this.roleFilter = this.statusFilter = this.isVerifiedFilter = this.departmentFilter = { label: 'All', value: 'all' }
this.$refs.filterCard.removeRefreshAnimation()
},
updateSearchQuery(val) {
this.gridApi.setQuickFilter(val)
}
},
created(){
//let users = /apps/user/user-list/
axios.get('api/users')
.then(res => {
let users = res.data.users;
})
}
}
</script>
<style lang="scss">
#page-user-list {
.user-list-filters {
.vs__actions {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-58%);
}
}
}
</style>

React-Table not rendering data

I am trying to render some data in a react-table component however the data doesn't load. I have tested out with dummy data of the exact same format and it works fine. However when I make an API call and get data of the same format and push it to the list of data i'm passing to the react-table the table does not render it. Please help me identify the issue. Cheers
Setting up the columns:
columns: [
{
Header: "Employee ID",
accessor: "EmployeeID"
},
{
Header: "First Name",
accessor: "FirstName"
},
{
Header: "Last Name",
accessor: "LastName"
},
{
Header: "Date of Birth",
accessor: "DateOfBirth",
},
{
Header: "Status",
accessor: "Status",
},
{
Header: "Gender",
accessor: "Gender",
},
{
Header: "UpdatedDateUTC",
accessor: "UpdatedDateUTC",
}
]
What the data looks like:
{"EmployeeID":"63c571b3-bff0-4ce1-94f7-255c235580fa","FirstName":"Clive","LastName":"Thomas","Status":"ACTIVE","DateOfBirth":"/Date(697248000000+0000)/","Gender":"M","UpdatedDateUTC":"/Date(1533706298000+0000)/"}
My API call and how I'm saving the data item to state. (I console logged the value of the data I'm getting and it is in the correct format)
fetch('http://localhost:3100/employees')
.then((resp) => {
return resp.json()
})
.then((data) => {
let temp = this.state.posts;
temp.push(data.Employees[1])
this.setState({posts: temp})
console.log(this.state.posts)
})
.catch((error) => {
console.log(error, "catch the hoop")
})
The state and the 'posts' list storing the posts in state at bottom (with dummy data):
state = {
title: "Choose an Endpoint",
activeOrg: "Orginisation",
isExpanded: false,
activeLink: 0,
authLink:'',
response: '',
post: '',
responseToPost: '',
show: false,
modalContent:"",
token:'',
verifier:'',
org:'',
orginisations: [
{ id: 1, name: "ANU"},
{ id: 2, name: "Bar"},
{ id: 3, name: "FANG"},
{ id: 4, name: "Atlassian"}
],
list: [
{ id: 1, name: "Employees" },
{ id: 2, name: "Leave Applications" },
{ id: 3, name: "Pay Items" },
{ id: 4, name: "Payroll Calendars" },
{ id: 5, name: "Pay Runs" },
{ id: 6, name: "Pay Slips" },
{ id: 7, name: "Settings" },
{ id: 8, name: "Superfund Products" },
{ id: 9, name: "Timesheets" }
],
columns: [
{
Header: "Employee ID",
accessor: "EmployeeID"
},
{
Header: "First Name",
accessor: "FirstName"
},
{
Header: "Last Name",
accessor: "LastName"
},
{
Header: "Date of Birth",
accessor: "DateOfBirth",
},
{
Header: "Status",
accessor: "Status",
},
{
Header: "Gender",
accessor: "Gender",
},
{
Header: "UpdatedDateUTC",
accessor: "UpdatedDateUTC",
}
],
posts: [
{"EmployeeID":"63c571b3-bff0-4ce1-94f7-255c235580fa","FirstName":"Clive","LastName":"Thomas","Status":"ACTIVE","DateOfBirth":"/Date(697248000000+0000)/","Gender":"M","UpdatedDateUTC":"/Date(1533706298000+0000)/"}
]
}
Render function:
render() {
let myClass=""
let EndpointList = (
<div>
{this.state.list.map((i) => {
i.id === this.state.activeLink ? myClass="endpoint activeLink" : myClass="endpoint"
return <Endpoint
key={i.id}
name={i.name}
myClass={myClass}
clicked={(event) => this.handleClickEndpoint(i, i.id)}/>
})}
</div>
);
let orgContainer = ""
this.state.isExpanded ? orgContainer="orgItem expanded" : orgContainer="orgItem notExpanded"
let OrgList = (
<div className={orgContainer}>
{this.state.orginisations.map((o) => {
return <Orginisation
key={o.id}
name={o.name}
clicked={(event) => this.handleClickOrg(o,o.id)}
></Orginisation>
})}
</div>
);
var activeContent=<ReactTable columns={this.state.columns} data={this.state.posts} noDataText={"Loading..."}></ReactTable>
// const columns = Object.keys(this.state.data[0]).map((key, id)=>{
// console.log(key)
// return {
// Header: key,
// accessor: key,
// }
// })
return (
<Router>
<Route path='/' exact render={
() => {
return (
<div className='authenticateContainer'>
<a href={this.state.authLink} className='fill-div'>Click to Auntheticate</a>
</div>
)
}
}/>
<Route path='/home' render={
() => {
return (
<div>
<div className='sideBar'>
<div className='logoHolder'>
<img className='logo' alt='Logo' src={'./Assets/logo.png'}></img>
</div>
{EndpointList}
{OrgList}
<div style={{}} className="org button" onClick={this.expandOrg}>
<img className="orgLogo" alt='Logo' src={'./Assets/orgLogo.png'}></img>
{this.state.activeOrg}
</div>
</div>
<div className="container" id={this.state.title}>
{/* <button onClick={() => { this.setCredentials() }}>CLICK ME</button> */}
<div className="contentContainer">
<div className="head">
{this.state.title}
</div>
{activeContent}
</div>
</div>
</div>
)
}
} />
</Router>
);
}
}
Instantiating the react-table (also in render function above):
var activeContent=<ReactTable columns={this.state.columns} data={this.state.posts} noDataText={"Loading..."}></ReactTable>
I have also printed the dummy data that is successfully being inserted into the list as well as the API data which is not. As you can see they are clearly identical:
Not sure if this will resolve your issue, but IMO you should refactor this to be
fetch('http://localhost:3100/employees')
.then((resp) => {
return resp.json()
})
.then((data) => {
let temp = [...this.state.posts]
temp.push(data.Employees[1])
this.setState({
posts: temp,
data: data
})
console.log(this.state.posts) //this will not have the newest values yet, setState is async
})
.catch((error) => {
console.log(error, "catch the hoop")
})
It's not good practice to perform manipulations on react state
Why are you pushing Employees[1]? That would be the second record.

How to get objects in array of object in React Native

I'm kind of lost to access some info in my static data. Here's the data :
{
"info1": {
"label": "label",
"class": "class-css",
"title": "title",
"text": "text",
"number": "20",
"tags": [
{
"name": "#twitter"
},
{
"name": "#myspace"
}
]
},
"info2": {
"label": "label",
"class": "class-css",
"title": "title",
"text": "text",
"number": "20",
"tags": [
{
"name": "#instagram"
},
{
"name": "#facebook"
}
]
}
}
Then I get the first info like that :
this.setState({
currentLabel: this.state.labels["info1"]
})
This is why I want and then I want to display info in a component and it's working until I try to get tags information. I tried a .map() but without success and error.
<View>
<Text>{infoDetail.title}</Text>
<Text>{infoDetail.text}</Text>
<Text>How do I get "tags" information</Text>
</View>
Is it possible to access these objects in the array "tags" ?
yes you can call tags as follows infoDetail.tags and do map on it
render(){
const tagItems = infoDetail && infoDetail.tags.map((item, index) => {
return <Text key={index}>{item.name}</Text>
});
return(
<View>
<Text>{infoDetail.title}</Text>
<Text>{infoDetail.text}</Text>
{tagItems}
</View>
)
}
Here is a full working code. Since your labels state property is an object, you need to map it somehow. I've chosen Object.values here. You can use Object.keys or even Object.entries according to your needs.
I've used a separate Info component and passed the values to it, then render there. In this component, we are again mapping the tags, then rendering the list.
class App extends React.Component {
state = {
labels: {
info1: {
label: "label1",
class: "class-css",
title: "title",
text: "text",
number: "20",
tags: [
{
name: "#twitter",
},
{
name: "#myspace",
},
],
},
info2: {
label: "label2",
class: "class-css",
title: "title",
text: "text",
number: "20",
tags: [
{
name: "#instagram",
},
{
name: "#facebook",
},
],
},
},
}
render() {
const { labels } = this.state;
return (
<div>
{
Object.values( labels ).map( value =>
<Info label={value} key={value.label} /> )
}
</div>
);
}
}
const Info = ( props ) => {
const { title, text, tags } = props.label;
const tagList = tags.map( tag => <p key={tag.name}>{tag.name}</p> );
return (
<div style={{ border: "1px solid gray", marginTop: "-1px" }}>
<p>{title}</p>
<p>{text}</p>
<div>{tagList}</div>
</div>
);
};
ReactDOM.render(
<App />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Update
If your data is totally static then #Xavi A.'s method is a good option. I don't know how is your list but I provide a simple code including something like you want here.
const labels = {
info1: {
label: "label1",
class: "class-css",
title: "title",
text: "text",
number: "20",
tags: [
{
name: "#twitter"
},
{
name: "#myspace"
}
]
},
info2: {
label: "label2",
class: "class-css",
title: "title",
text: "text",
number: "20",
tags: [
{
name: "#instagram"
},
{
name: "#facebook"
}
]
}
};
class App extends React.Component {
state = {
currentLabel: Object.keys(labels)[0]
};
handleInfoChange = info => this.setState({ currentLabel: info });
renderList = () => (
<ul>
{Object.keys(labels).map(info => (
<Item key={info} info={info} onClick={this.handleInfoChange} />
))}
</ul>
);
render() {
const { currentLabel } = this.state;
return (
<div>
{this.renderList()}
<Info currentLabel={currentLabel} />
</div>
);
}
}
const Item = props => {
const { info, onClick } = props;
const handleClick = () => onClick(info);
return <li onClick={handleClick}>{info}</li>;
};
const Info = props => {
const { currentLabel } = props;
const { title, text, tags } = labels[currentLabel];
const tagList = tags.map(tag => <p key={tag.name}>{tag.name}</p>);
return (
<div style={{ border: "1px solid gray", marginTop: "-1px" }}>
<p>{title}</p>
<p>{text}</p>
<div>{tagList}</div>
</div>
);
};
ReactDOM.render( <App />, document.getElementById( "root" ) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Probably something like this.
<Text>{infoDetail.tags.map(tag => {/*render */})}</Text>
You can try Object.keys() and Array.prototype.reduce() to get your favorite data:
const data = {
"info1": {
"label": "label",
"class": "class-css",
"title": "title",
"text": "text",
"number": "20",
"tags": [
{
"name": "#twitter"
},
{
"name": "#myspace"
}
]
},
"info2": {
"label": "label",
"class": "class-css",
"title": "title",
"text": "text",
"number": "20",
"tags": [
{
"name": "#instagram"
},
{
"name": "#facebook"
}
]
}
};
const tags = Object.keys(data).reduce((result, key) => {
return result.concat(data[key].tags);
}, [])
console.log(tags);
/* tags = [
{
"name": "#twitter"
},
{
"name": "#myspace"
},
{
"name": "#instagram"
},
{
"name": "#facebook"
}
] */
No need to save all the static data in your state, you can keep your state cleaner by just saving the selected label:
onLabelSelect = label => {
//label will be "info1" for example
this.setState({
currentLabel: label
})
}
Then in your render:
render(){
//get infoDetail from staticData
const infoDetail = staticData[this.state.currentLabel]
return (
<View>
<Text>{infoDetail.title}</Text>
<Text>{infoDetail.text}</Text>
{infoDetail.tags.map( ({name}) => <Text>name</Text>)}
</View>
)
}
Note about the map. This:
{infoDetail.tags.map( ({name}) => <Text>name</Text>)}
is a shorter version of:
{infoDetail.tags.map( item => {
return <Text>item.name</Text>
})}

Google column chart - column values don't match axis

I have a column chart as follows:
I've added the values of the data, and as you can see the columns don't make sense in relation to the Y axis - why is this?
The chart options:
var options = {
title: 'Task Estimates',
backgroundColor: { fill: 'transparent' },
chartArea: { width: '50%' },
height: '400px',
hAxis: { direction: -1, slantedText: true, slantedTextAngle: 45, title: 'Tasks' },
};
var url = "http://theurl";
$.getJSON(url, function (jsonChartData) {
var data = new google.visualization.DataTable(jsonChartData);
var chart = new google.visualization.ColumnChart(chartHtmlElement);
chart.draw(data, options);
});
The json is:
{
"cols":[
{ "id":"A", "label":"Task", "type":"string", "role":null },
{ "id":"B", "label":"Days Estimated", "type":"number", "role":null },
{ "id":"C", "label":"Days Actual", "type":"number", "role":null }
],
"rows":[
{ "c":[ { "v":"Task 3" }, { "v":"7" }, { "v":"4" } ] },
{ "c":[ { "v":"Task 1" }, { "v":"10" }, { "v":"24" } ] },
{ "c":[ { "v":"Task 2" }, { "v":"100" }, { "v":"0" } ] }
],
"p":null
}
What am I doing wrong? Is there something else I need to specify to make the axis work correctly?
JSFIDDLE
http://jsfiddle.net/6K3Wc/1/
You are entering your numbers as strings, when they should be entered as numbers:
{
"cols":[
{
"id":"A",
"label":"Task",
"type":"string",
"role":null
},
{
"id":"B",
"label":"Days Estimated",
"type":"number",
"role":null
},
{
"id":"C",
"label":"Days Actual",
"type":"number",
"role":null
}
],
"rows":[
{
"c":[
{
"v":"Task 3"
},
{
"v":7
},
{
"v":4
}
]
},
{
"c":[
{
"v":"Task 1"
},
{
"v":10
},
{
"v":24
}
]
},
{
"c":[
{
"v":"Task 2"
},
{
"v":100
},
{
"v":0
}
]
}
],
"p":null
}

Categories