Show dialog in React - Material UI - html

I am learning ReactJS. I would like to display dialog when someone clicks on the icon.
Here is the code:
import React, { Component } from 'react';
import { GridList, GridTile } from 'material-ui/GridList';
import FlatButton from 'material-ui/FlatButton';
import Info from 'material-ui/svg-icons/action/info';
import { fullWhite } from 'material-ui/styles/colors';
import Dialog from 'material-ui/Dialog';
import RaisedButton from 'material-ui/RaisedButton';
(... class stuff, handleClose, handleOpen etc.)
showDialoga() {
const actions = [
<FlatButton
label="Cancel"
primary
onClick={this.handleClose}
/>,
<FlatButton
label="Submit"
primary
keyboardFocused
onClick={this.handleClose}
/>,
];
return (
<div>
<RaisedButton label="Dialog" onClick={this.handleOpen} />
<Dialog
title="Dialog With Actions"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
The actions in this window were passed in as an array of React objects.
</Dialog>
</div>
);
}
render() {
console.log(this.props);
return (
<div style={styles.root}>
<GridList
cellHeight={180}
style={styles.gridList}
padding={10}
>
{this.props.movieData.map(tile => (
<GridTile
key={tile.original_image}
title={tile.title}
actionIcon={<FlatButton
icon={<Info color={fullWhite} />}
style={style}
onClick={() => this.showDialoga()}
/>}
>
<img src={tile.original_image} />
</GridTile>
))}
</GridList>
</div>
);
}
}
I am able to pass other function like () => console.log('I am clicked') to onClick although I am not able to pass that showDialoga().
Any idea what is the problem?

I do not believe that's how you are supposed to use dialog.
Instead of passing return of React component on click, try setting the dialog opened state to be true/false. Also do not forget to bind this to the class level if you are using functions to render different components that has event listeners.

Related

How to change / toggle React state?

I am trying to toggle react state after the button click. After clicking button Work From Office should change to work From Home and vice versa. But it is not working. What am I dong wrong? I am able to change only once. Can we do with if statement? What is simple way?
** React **
import React, { Component } from 'react';
import './ChangeSchedule.css';
class ChangeSchedule extends Component {
constructor(){
super()
this.state = {
// work:'from office'
workFromOffice:true
}
}
changeMyWorkPlace(){
this.setState({
// work:'from Home'
workFromOffice:!this.state.workFromOffice
})
}
render(){
return(
<div>
<div class="schedule change">
<h3>Emplyoee Name: </h3>
<p>Today Pooja is work {this.state.work}</p>
{/* <button class="chageScheduleBtn " onClick = {()=> this.changeMyWorkPlace()}> Change My Schedule </button> */}
<button class="chageScheduleBtn " onClick = {()=> this.workFromOffice() ?'Home': 'Office'}> Change My Schedule </button>
</div>
</div>
)
}
}
export default ChangeSchedule;
You can use a ternary expression to display content for each state.
For example:
{this.state.workFromOffice ? " from Office" : " from Home"}
Now this button should work as you expect:
<button class="chageScheduleBtn" onClick={()=> this.changeMyWorkPlace()}>
Change My Schedule
</button>
See codesandbox for fully working example
You could do it as below. Just change the status when the click happen. And inside the button, use a ternary expression. Like so:
import { Component } from "react";
import "./ChangeSchedule.css";
class ChangeSchedule extends Component {
constructor() {
super();
this.state = {
// work:'from office'
workFromOffice: true,
};
}
changeMyWorkPlace() {
this.setState({
// work:'from Home'
workFromOffice: !this.state.workFromOffice,
});
}
render() {
return (
<div>
<div class="schedule change">
<h3>Emplyoee Name: </h3>
<p>Today Pooja is work {this.state.work}</p>
<button class="chageScheduleBtn " onClick={() => this.workFromOffice()}>
{this.state.workFromOffice ? "Work From Home" : "Work From Office"}
</button>
</div>
</div>
);
}
}
export default ChangeSchedule;
The answer is in the way you're structuring your state. You can make it really simple by just using one entry of the state - workFromOffice. Then, your click handler should care only about changing that state value to the opposite of what was set before. Example:
onClick={() => this.setState({ workFromOffice: !this.state.workFromOffice })}
When the changeMyWorkPlace function created, it captures your initial state and uses it everytime you run the function so only works once. You should instruct react to use up to date state.
try this way.
changeMyWorkPlace(){
this.setState((previousState) => ({
// work:'from Home'
workFromOffice:!previousState.workFromOffice
}))
}

React adding favorites with checkboxes

Objects
Favourites
im trying to do a website witch react and i use an api to recieve data. The Data i recieved gets put into a list and then i produce a button for every item in this list. Now i also produce a check box for every item in the list, but the production is in a seperate component. what i want to do ist that, if the checkbox of one item gets checked, the item should be stored in a cache and put out again as an button on a seperate page. My Question now is how do i do that?
Thank you in advance.
This is where i produce the checkbox:
import React from "react";
export default function Favcheck() {
return (
<>
<div class="favcheck">
Favorit
<input type="checkbox" name="name" class="checkbox" id="heart" />
</div>
</>
);
}
this is where the buttons are made:
import axios from "axios";
import * as React from "react";
import Favcheck from "./favcheck.jsx";
import Mensapage from "./mensapage.jsx";
import site from "./home.jsx";
export default function Mensbuttons(props) {
return (
<>
<div class="formcontainer">
<form method="get" action="/mensapage" id="mensaform">
<button type="submit" class="mensabutton" key={props.key}>
<div class="mensatext">{props.name}</div>
</button>
<br></br>
<Favcheck />
</form>
</div>
</>
);
}
and this is where the buttons are used:
import React,{ useState, useEffect } from "react";
import axios from 'axios';
import Nav from "./nav.jsx";
import Mensbuttons from "./mensbuttons.jsx";
export default function Home(props) {
let site="test";
const[posts,setPosts] = useState([])
useEffect(()=>{
axios.get('https://openmensa.org/api/v2/canteens?near[lat]=52.517037&near[lng]=13.38886&near[dist]=15')
.then(res =>{
setPosts(res.data)
})
.catch(err =>{
console.log(err)
})
},[])
console.log(posts);
return (
<>
<Nav />
<div class="header">
<h1>Mensen</h1>
</div>
{posts.map((list) => {
return <Mensbuttons name={list.name} key={list.id} />;
})}
</>
);
}
here are some mockup pictures
i want to get specific objects to the favourites page by checking the checkbox
here are the favourites
here are the buttons with checkboxes

React Chakra UI modal only shows overlay

I'm using Chakra UI in React with Typescript and having such a weird issue I trying to implement Modal with the following code in modal.tsx file.
import {
useDisclosure,
Button,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalCloseButton,
ModalBody,
ModalFooter,
} from "#chakra-ui/react";
export default function CustomModal() {
const { isOpen, onOpen, onClose } = useDisclosure();
return (
<>
<Button onClick={onOpen}>Open Modal</Button>
<Modal closeOnOverlayClick={false} isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Create your account</ModalHeader>
<ModalCloseButton />
<ModalBody pb={6}></ModalBody>
<ModalFooter>
<Button colorScheme="blue" mr={3}>
Save
</Button>
<Button onClick={onClose}>Cancel</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
);
}
once i click on Open Modal button it simply shows the overlay without actual content of the modal.
I tried to reproduce your problem and found that - For Chakra UI to work correctly, you need to set up the ChakraProvider at the root of your application.
import * as React from "react"
// 1. import `ChakraProvider` component
import { ChakraProvider } from "#chakra-ui/react"
function App({ Component }) {
// 2. Use at the root of your app
return (
<ChakraProvider>
<Component />
</ChakraProvider>
)}
Here is the running code sandbox link of your problem.
In App.js I wrapped the application in <ChakraProvider>.
Hope it works for you.
First Check You Wrappped Your App With ChakraProvider If Provided

how to parse values from JSON.stringified data in a text component sent from a different page

with regard to this tutorial "React Router Native - Passing Data" https://www.youtube.com/watch?v=SdOWxoH3HLg by #benawad user:4272160
I can't figure out how to extract bob or 5 from
{"val1:"bob","val2":5}
from the stringified string data in <Text>JSON.stringify(location.state)}</Text>
when passing data between pages
I've tried to contact #benawad through a comment, I've searched google and here for similar but found nil relevant. I tried a regex unsuccessfully but there has to be a better way anyway...
code is at https://github.com/benawad/react-router-native-example/tree/1_advanced
// Home.js
import React from "react";
import { View, Text, Button } from "react-native";
export default ({ history }) => (
<View>
<Text>This is the home page</Text>
<Button title="change page" onPress={() =>
history.push("/products", {val1: "bob", val2: 5})
/>
</View>
);
// Products.js
import React from "react";
import { View, Text, Button } from "react-native";
export default ({ history, location }) => (
<View>
<Text>Product 1</Text>
<Text>Product 2</Text>
<Text>{JSON.stringify(location.state)}</Text>
<Button title="change page" onPress={() => history.push("/")}/>
</View>
);
I thought about trying to JSON.parse the stringified data. No joy. I tried location.state.val but just got
TypeError: undefined is not an object (evaluating 'location.state.val')
You need to pass state through the history api. Change your Home component to
export default ({ history }) => (
<View>
<Text>This is the home page</Text>
<Button title="change page" onPress={() =>
history.push("/products", {val1: "bob", val2: 5)} />
</View>
);
and then access location.state.val1 and location.state.val2 directly in your Products component.
See https://github.com/benawad/react-router-native-example/blob/1_advanced/ChangePageButton.js#L9 for the similar history line in the tutorial code.
The JSON.stringify used in the example code is just there as an illustration so that the entire location.state can be displayed in a Text element.
You can pass props to history object,
<Button title="change page"
onPress={() => history.push({
pathname: '/',
state: { locationData: JSON.stringify(location.state) } //JSON.stringify needed if you want to pass object otherwise don't use.
})}
/>
In the component which is rendered with / route, you can access the props like,
{JSON.parse(props.location.state.locationData)} //Functional component
{JSON.parse(this.props.location.state.locationData)} //Class based component
Note: JSON.parse needed if object is being passed otherwise no need to use.

React JSON - Display data in a Card Slider

I have a local JSON file which I've converted to Javascript.
I am able to fetch the data by importing the JS file into my App.js.
This is my App.js file:
import React, { Component } from "react";
import CardData from "./data/db";
import "./App.css";
class App extends Component {
constructor() {
super();
this.state = {
CardData
};
}
render() {
return (
<div>
{this.state.CardData.map(cards => (
<div className="card">
<span>{cards.title}</span>
<br />
<span>{cards.subtitle}</span>
<br />
</div>
))}
</div>
);
}
}
export default App;
I want to be able to show 3 Cards, and then have the option to slide across to the remaining cards.
Something like this
However I am only able to show it in one div, is there a way to do it in the way I've called the JSON or is there a way to separate the JSON data by their ID?
Since you are looking for a simpler way to achieve the same result I would suggest switching your App to a stateless component, as it is never updating/using any state value :
import React from "react";
import CardData from "./data/db";
import "./App.css";
const App = props => (
<React.Fragment> //A fragment will not appear in your DOM
{CardData.map(({ title, subtitle }, index) => ( //Deconstructs each cards
<div className="card" key={index}>
<span>{title}</span>
<br />
<span>{subtitle}</span>
<br />
</div>
))}
</React.Fragment>
)
export default App;
But this component will never be able to render anything else than this specific JSON file, if you want it to be more generic, you should send your data via the component's props :
import React from "react";
import "./App.css";
const App = ({ cards }) => (
<React.Fragment>
{cards.map(({ title, subtitle }, index) => (
<div className="card" key={index}>
<span>{title}</span>
<br />
<span>{subtitle}</span>
<br />
</div>
))}
</React.Fragment>
)
export default App;
And in your parent component :
import CardData from "./data/db";
const Parent = props => <App cards={CardData}/>
You should also not forget about keys when mapping elements, as every mapped component should have a unique and persistent key.