I'm learning React and decided to check out JSON Forms ( https://jsonforms.io/docs/tutorial ).
I can get the seed app from https://github.com/eclipsesource/jsonforms-react-seed running, and I also experimented with moving all the form-related stuff into its own component, instead of putting it all in index.js. That works great in the seed app.
Then I decided to try to set up the demo form from the playground schema ( https://mozilla-services.github.io/react-jsonschema-form/ ) in the seed app, just to make sure I knew how to change a form.
This is where the wheels came off. Instead of a form, I get "No applicable renderer found."
I copied the three inputs in the playground ( schema, UISchema, and formData ). Below is the code from the separate component, with the schema, uischema, and data taken directly from the playground data jsonschema provides:
import { JsonForms } from '#jsonforms/react';
import React from 'react';
import { combineReducers, createStore } from 'redux';
import { Provider } from 'react-redux';
import { Actions, jsonformsReducer } from '#jsonforms/core';
import { materialFields, materialRenderers } from '#jsonforms/material-renderers';
const data = {
firstName: "Chuck",
lastName: "Norris",
age: 75,
bio: "Roundhouse kicking asses since 1940",
password: "noneed"
};
const schema = {
"title": "A registration form",
"description": "A simple form example.",
"type": "object",
"required": [
"firstName",
"lastName"
],
"properties": {
"firstName": {
"type": "string",
"title": "First name"
},
"lastName": {
"type": "string",
"title": "Last name"
},
"age": {
"type": "integer",
"title": "Age"
},
"bio": {
"type": "string",
"title": "Bio"
},
"password": {
"type": "string",
"title": "Password",
"minLength": 3
},
"telephone": {
"type": "string",
"title": "Telephone",
"minLength": 10
}
}
};
const uischema = {
"firstName": {
"ui:autofocus": true,
"ui:emptyValue": ""
},
"lastName": {
"ui:autofocus": true,
"ui:emptyValue": ""
},
"age": {
"ui:widget": "updown",
"ui:title": "Age of person",
"ui:description": "(earthian year)"
},
"bio": {
"ui:widget": "textarea"
},
"password": {
"ui:widget": "password",
"ui:help": "Hint: Make it strong!"
},
"telephone": {
"ui:options": {
"inputType": "tel"
}
}
};
const store = createStore(
combineReducers({ jsonforms: jsonformsReducer() }),
{
jsonforms: {
fields: materialFields,
renderers: materialRenderers
},
}
);
store.dispatch(Actions.init(data, schema, uischema));
function SampleForm() {
return (
<div>
<Provider store={store}>
<JsonForms />
</Provider>
</div>);
}
export default SampleForm;
index.js looks like this:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(
<App />,
document.getElementById('root')
);
registerServiceWorker();
and finally, the app itself, App.js, looks like this:
import React from 'react';
import './App.css';
import SampleForm from './sampleform';
const styles = {
container: {
padding: '1em'
},
title: {
textAlign: 'center',
padding: '0.25em'
},
dataContent: {
display: 'flex',
justifyContent: 'center',
borderRadius: '0.25em',
backgroundColor: '#cecece',
},
demoform: {
margin: 'auto'
}
};
const App = () => (
<div>
<SampleForm/>
</div>
);
export default App;
<JsonForms
schema={schema}
uischema={Generate.uiSchema(schema)}
data={data}
renderers={materialRenderers}
/>
https://github.com/eclipsesource/jsonforms/issues/923#issuecomment-374936319
Related
I am trying to make a demo project using a free API available in web. I am trying to fetch using js fetch method and I am using the latest react-router-dom package
App.js is setting up the route with appropriate loaders
App.js
import "./App.css";
import Root from "./layouts/Root";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import Posts from "./pages/Posts";
import { loader as allPostsLoader } from "./pages/Posts";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
Children: [{ index: true, element: <Posts />, loader: allPostsLoader }],
},
]);
function App() {
return (
<>
<RouterProvider router={router} />
</>
);
}
export default App;
Posts.js
import { json } from "react-router-dom";
import { useLoaderData } from "react-router-dom";
import PostsList from "../components/PostsList";
const Posts = () => {
const data = useLoaderData();
console.log(data);
return (
<PostsList posts={data} />
);
};
export default Posts;
export const loader = async () => {
const response = await fetch("https://dummyapi.io/data/v1/post", {
method: "GET",
headers: new Headers({
"app-id": "63e0971cd1c871fb16613cc4",
}),
body:undefined
});
if (!response.ok) {
throw json({ message: "Count not fetch data!!" }, { status: 500 });
}
return response;
};
PostsList.js
const PostsList = ({ posts }) => {
return (
<div className="all-post">
<h1>All Posts</h1>
<div className="posts-wrapper">
{posts.map((post) => {
<div key={post.id} className="post">
<div className="image">
<img src={post.image} alt="" />
</div>
<h2>{post.text}</h2>
<p>Publish Date: {post.publishDate}</p>
</div>
})}
;
</div>
</div>
);
};
export default PostsList;
Response from API
{
"data": [
{
"id": "60d21b4667d0d8992e610c85",
"image": "https://img.dummyapi.io/photo-1564694202779-bc908c327862.jpg",
"likes": 43,
"tags": [
"animal",
"dog",
"golden retriever"
],
"text": "adult Labrador retriever",
"publishDate": "2020-05-24T14:53:17.598Z",
"owner": {
"id": "60d0fe4f5311236168a109ca",
"title": "ms",
"firstName": "Sara",
"lastName": "Andersen",
"picture": "https://randomuser.me/api/portraits/women/58.jpg"
}
},
{
"id": "60d21b4967d0d8992e610c90",
"image": "https://img.dummyapi.io/photo-1510414696678-2415ad8474aa.jpg",
"likes": 31,
"tags": [
"snow",
"ice",
"mountain"
],
"text": "ice caves in the wild landscape photo of ice near ...",
"publishDate": "2020-05-24T07:44:17.738Z",
"owner": {
"id": "60d0fe4f5311236168a10a0b",
"title": "miss",
"firstName": "Margarita",
"lastName": "Vicente",
"picture": "https://randomuser.me/api/portraits/med/women/5.jpg"
}
}
],
"total": 873,
"page": 0,
"limit": 20
}
I am not able to see the app call in the Network section and now errors are shown as well.
I have facing a problem with getting data from json object with react. Here is my example data:
const data = [
{
"name": "Adele",
"age": "17",
"exampleValue": "Dummy"
},
{
"name": "Adele",
"age": "17"
}
]
But when i'm trying to get data from the object with "exampleValue". it showing me error.
Is there any way to solve it without adding "exampleValue" in second object?
To read the elements which may present in the node can be read by adding certain condition. Like in your cases you can check if the element in the json node present or not using "hasOwnProperty"
Example
import React, { useState, useEffect, useRef } from "react";
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default function App() {
const [arr, setArr] = useState([{
"name": "Adele",
"age": "17",
"exampleValue": "Dummy"
},
{
"name": "Adele",
"age": "17"
},
{
"name": "Adele",
"age": "17",
"exampleValue": "User"
}]);
const renderRow=()=>{
return arr.map((item, index)=>
<div style={{fontSize:18}}>
{item.hasOwnProperty("exampleValue")? item.exampleValue:null}
</div>
)
}
return (
<View style={styles.container}>
{renderRow()}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
}
});
Working example: https://snack.expo.dev/L_a4aNEL1
i'm trying to define my "Logo" as an image.
i tried to create a logo.js component, define it as an image and call it here, but i have absolutely no clue on how to solve that.
Here is my banner component,
import React from 'react'
import Banner from 'react-banner'
import 'react-banner/dist/style.css'
import Logo from '../Logo'
export default props => {
return (
<Banner
Logo = "My logo"
url={ window.location.pathname }
items={[
{ "content": "Quoi de neuf au tieks ?", "url": "/wassup" },
{ "content": "Les poucaves du jour", "url": "/lpdc", "children": [
{ "content": "Océane", "url": "/children/oceane" },
{ "content": "Mehdi", "url": "/children/mehdi" },
{ "content": "Yikes", "url": "/children/zemmeled" }
]}
]} />
)
}
if I understand well your question is: I can you pass a logo to the Banner Component ?
A quick look to the react-banner documentation and you can find :
"logo (node)
The image, text, or whatever else you may want to display in the left section of the banner.
url (string)"
https://skipjack.github.io/react-banner/customization
So I believe you can do as follow:
import React from 'react'
import Banner from 'react-banner'
import 'react-banner/dist/style.css'
import Logo from '../Logo'
export default props => {
return (
<Banner
Logo = "My logo"
logo=<Logo />
url={ window.location.pathname }
items={[
{ "content": "Quoi de neuf au tieks ?", "url": "/wassup" },
{ "content": "Les poucaves du jour", "url": "/lpdc", "children": [
{ "content": "Océane", "url": "/children/oceane" },
{ "content": "Mehdi", "url": "/children/mehdi" },
{ "content": "Yikes", "url": "/children/zemmeled" }
]}
]} />
)
}
As you can see on the code above, I pass the Logo component into the props logo of the BannerComponent from the librairy react-banner.
I have an object named data that contains information about book. The simplest thing I want to do is render the book name. I am trying like below. Not working.
const data = {
"book": {
"id": "2d320",
"name": "book 1",
"Chapters": [
{
"No": "1",
"date": "2010-04-22",
"plots": [
{
"name": "Hero"
}
]
},
{
"No": "2",
"date": "2010-04-22",
"plots": [
{
"name": "Heroine"
}
]
},
]}}
export class Books {
render() {
return (
<View>
<div>{data.book.name}</div>
</View>
);
}
}
div should not be used in react-native, just replace it with Text after importing it. Secondly, class-based components should extend React.Component like so
import React, { Component } from 'react';
import { Text, View } from 'react-native';
const data = {
book: {
id: '2d320',
name: 'book 1',
Chapters: [
{
No: '1',
date: '2010-04-22',
plots: [
{
name: 'Hero',
},
],
},
{
No: '2',
date: '2010-04-22',
plots: [
{
name: 'Heroine',
},
],
},
],
},
};
class Book extends Component {
render() {
return <View>
<Text>{data.book.name}</Text>
</View>;
}
}
export default Book;
Here is a snack displaying the output you want.
If you don't want to import Component from 'react' and like to export directly then may also use this syntax
export default class Book extends React.Component {
render() {
return (
<View>
<Text>{data.book.name}</Text>
</View>
);
}
}
I want to call the function using the key name from the array on the tab.screen component.
my code is like this:
import React from 'react';
import { Text, View, TouchableOpacity, Modal } from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
import Icon from 'react-native-vector-icons/FontAwesome5';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import Home from '../mainscreen/GeneralScreen';
import Core from '../mainscreen/CoreScreen';
import Docs from '../mainscreen/GeneralScreen';
import ESS from '../mainscreen/GeneralScreen';
import General from '../mainscreen/GeneralScreen';
import HR from '../mainscreen/GeneralScreen';
import Payroll from '../mainscreen/GeneralScreen';
import Server from '../mainscreen/CoreScreen';
const Tab = createBottomTabNavigator();
const tabcomponents = {
"Home" : Home,
"Core" : Core,
"Docs" : Docs,
"ESS" : ESS,
"General" : General,
"HR" : HR,
"Payroll" : Payroll,
"Server" : Server
};
class TabNavigator extends React.Component {
constructor() {
super();
this.state = {
dashboardtab:[],
}
this.tabnavigatorasync();
}
tabnavigatorasync = async () => {
try {
const dashboardtab = await AsyncStorage.getItem('dashboardtab');
const dashboardtabParse = JSON.parse(dashboardtab);
this.setState({dashboardtab: dashboardtabParse});
//console.log('isi dari tab navigator: ', this.state.dashboardtab);
//console.log('------------------------------------------------');
//console.log('isi dari tab navigator 2: ', this.state.dashboardtab2[0].label);
} catch (error) {
}
}
render(){
//console.log('dashboardtab', this.state.dashboardtab);
const tabnavigatorRender = this.state.dashboardtab.map((item, index) =>
const tabcomponentsrender = tabcomponents[item.admintab.label];
return <Tab.Screen name={item.admintab.label} component={tabcomponentsrender} key={index}/>
);
return(
<Tab.Navigator>
{tabnavigatorRender}
</Tab.Navigator>
)
}
}
export default TabNavigator;
the result appears an error like this:
Invariant Violation: View config getter callback for component Home must be a function (received undefined)
This is the contents of the array:
[
{
"tab_id": "home",
"order": 10,
"admintab": {
"label": "Home",
}
},
{
"tab_id": "core",
"order": 1,
"admintab": {
"label": "Core",
}
},
{
"tab_id": "docs",
"order": 2,
"admintab": {
"label": "Docs",
}
},
{
"tab_id": "ess",
"order": 50,
"admintab": {
"label": "ESS",
}
},
{
"tab_id": "general",
"order": 45,
"admintab": {
"label": "General",
}
},
{
"tab_id": "hr",
"order": 40,
"admintab": {
"label": "HR",
}
},
{
"tab_id": "payroll",
"order": 42,
"admintab": {
"label": "Payroll",
}
},
{
"tab_id": "server",
"order": 70,
"admintab": {
"label": "Server",
}
}
]
is there something wrong with the code i made?
In your case, you want to use Dynamic Component Names.
First of all import your tabs.
import Home from 'path_to_your_tab_component/Home';
import Core from 'path_to_your_tab_component/Core'; // and so on
Then pass them in the object and give them a key based on their names.
const components = {
"Home": Home
"Core": Core // and so on
}
Inside the map, create a component from this object.
const tabnavigator = this.state.dashboardtab.map((item, index) => {
const TabComponent = components[item.admintab.label];
return <Tab.Screen name={item.admintab.label} component={TabComponent} key={index}/>
});