I want to pass the selected date as a parameter when the showtime button is clicked. I couldn't find a way and I'm new to React. looking for suggestions.
Following is my code
import React, { useEffect, useState }from "react";
import PropTypes from "prop-types";
import { makeStyles } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Tabs from "#material-ui/core/Tabs";
import Tab from "#material-ui/core/Tab";
import PhoneIcon from "#material-ui/icons/Phone";
import FavoriteIcon from "#material-ui/icons/Favorite";
import PersonPinIcon from "#material-ui/icons/PersonPin";
import HelpIcon from "#material-ui/icons/Help";
import ShoppingBasket from "#material-ui/icons/ShoppingBasket";
import ThumbDown from "#material-ui/icons/ThumbDown";
import ThumbUp from "#material-ui/icons/ThumbUp";
import Typography from "#material-ui/core/Typography";
import Box from "#material-ui/core/Box";
import { DateRangeSharp } from "#material-ui/icons";
import { List, ListItem, ListItemText } from "#material-ui/core";
import Button from '#material-ui/core/Button';
import queryString from 'query-string';
import { Link, useLocation } from 'react-router-dom';
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`scrollable-force-tabpanel-${index}`}
aria-labelledby={`scrollable-force-tab-${index}`}
{...other}
>
{value === index && (
<Box p={3}>
<Typography>{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.any.isRequired,
value: PropTypes.any.isRequired
};
function a11yProps(index) {
return {
id: `scrollable-force-tab-${index}`,
"aria-controls": `scrollable-force-tabpanel-${index}`,
};
}
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
width: "100%",
backgroundColor: theme.palette.background.paper
}
}));
export default function ScrollableTabsButtonForce() {
const classes = useStyles();
const [value, setValue ] = React.useState(0);
const [venuesDates, setvenuesDates] = React.useState([]);
const [showtimesData] = React.useState([]);
useEffect(() => {
const url = "http://sandbox-api.tickets.lk/v1/movie/3232/showtime";
const requestOptions = (token) => {
return ({
method: 'GET',
headers: { 'Content-Type': 'application/json', 'client_token': 'ebd86470-7e90-4ece-9e89-1b6d4d2cbb61' }
})
};
const fetchData = async () => {
try {
const response = await fetch(url, requestOptions());
const json = await response.json();
// console.log(json);
// console.log(json.data.venueDateShowtime)
setvenuesDates(json.data.venueDateShowtime);
}
catch (error) {
console.log("error",error);
}
};
fetchData();
})
const search = useLocation().search;
const Mid = new URLSearchParams(search).get('movieid');
const Mname = new URLSearchParams(search).get('name');
// console.log(Mname)
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<AppBar
position="static"
style={{ background: "#333545", minHeight: 60 }}
>
<Tabs
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons="on"
indicatorColor="secondary"
textColor="primary"
aria-label="scrollable force tabs example"
style={{ minHeight: 60 }}
wrapped
>
{venuesDates.map((showtdates) => {
return (
<Tab
label={showtdates.date}
{...a11yProps(0)}
style={{ color: "#fff", fontSize: 20, minHeight: 60 }}
/>
);
})}
</Tabs>
</AppBar>
{/* map over dates and create TabPanel */}
{/* // check if theater property exists and create a list of theaters as an example */}
{venuesDates.map((date, idx) => {
const venues = date.hasOwnProperty("venues")
? date.venues.map((venues) => (
<ListItem>
<ListItemText
primary={venues.venue}
secondary={venues.venueId}
/>
{date.venues.map((date)=> {
const showtimes = venues.hasOwnProperty("showtimes")
? venues.showtimes.map((showtimes) => (
// <ListItemText primary={showtimes.showtime} />
<Link to={'/seat-booking?movieid=' + Mid +"&name=" + Mname + "&theater=" + venues.venueId +
"&movieDate=" + "showtdates.date" + "&showtimes=" + showtimes.showtimeId}
style={{ textDecoration: 'none', color: 'white' }}>
<Button variant="contained" color="primary" style={{margin:5}}>
{showtimes.showtime}
</Button>
</Link>
))
:null;
return(
<List>{showtimes}</List>
)
})}
</ListItem>
))
: null;
return (
<TabPanel value={value} index={idx}>
<List>{venues}</List>
</TabPanel>
);
})}
</div>
);
}
I really want to get the selected date from the Tab heading and pass as a parameter as mentioned below.
I need to change the "&movieDate=" + "showtdates.date" ===> as "&movieDate=" + (selected tab heading name)
{date.venues.map((date)=> {
const showtimes = venues.hasOwnProperty("showtimes")
? venues.showtimes.map((showtimes) => (
// <ListItemText primary={showtimes.showtime} />
<Link to={'/seat-booking?movieid=' + Mid +"&name=" + Mname + "&theater=" + venues.venueId +
"&movieDate=" + "showtdates.date" + "&showtimes=" + showtimes.showtimeId}
style={{ textDecoration: 'none', color: 'white' }}>
<Button variant="contained" color="primary" style={{margin:5}}>
{showtimes.showtime}
</Button>
</Link>
))
:null;
return(
<List>{showtimes}</List>
)
})}
Related
I have implemented an MUI card grid to display contents of my infinite scroll. However, the last two elements of the returned contents are showing up larger for some reason. Also the grid wont display cards side by side without a map function, which I cannot use or my infinite scroll breaks.
All data is mock data
Any solutions to either part would be wonderful!
Infinite Scroll Component
`
import { useRef, useCallback, useState, useEffect } from 'react'
import {
Box,
CardMedia,
CardContent,
Grid,
Paper,
Typography,
} from "#mui/material";
import { styled } from '#mui/material/styles';
import CountryListCard from '../CountryListCard/CountryListCard';
import Card4 from '../CountryListCard/HomeCards/HomeCountryCard'
import { useInfiniteQuery } from 'react-query'
import { getPostsPage } from '../../services/countries.service'
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
gridContainer: {
paddingLeft: "40px",
paddingRight: "40px",
}
});
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
...theme.typography.body2,
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
}));
const HomeScroll = () => {
const classes = useStyles();
const {
fetchNextPage, //function
hasNextPage, // boolean
isFetchingNextPage, // boolean
data,
status,
error
} = useInfiniteQuery('/country', ({ pageParam = 1 }) => getPostsPage(pageParam), {
getNextPageParam: (lastPage, allPages) => {
return lastPage.length ? allPages.length + 1 : undefined
}
})
const intObserver = useRef()
const lastPostRef = useCallback(country => {
if (isFetchingNextPage) return
if (intObserver.current) intObserver.current.disconnect()
intObserver.current = new IntersectionObserver(countries => {
if (countries[0].isIntersecting && hasNextPage) {
console.log('We are near the last post!')
fetchNextPage()
}
})
if (country) intObserver.current.observe(country)
}, [isFetchingNextPage, fetchNextPage, hasNextPage])
if (status === 'error') return <p className='center'>Error: {error.message}</p>
const content = data?.pages.map(pg => {
return pg.map((country, i) => {
if (pg.length === i + 1) {
return (
<Grid container spacing={2}>
<Grid item xs>
<CountryListCard ref={lastPostRef} key={country.id} country={country} />
</Grid>
</Grid>
)
}
return (
<Grid container spacing={2}>
<Grid item xs={6}>
<CountryListCard key={country.id} country={country} />
</Grid>
</Grid>
)
})
})
return (
<>
<Grid container spacing={2}>
<Grid item xs={6}>
{content}
</Grid>
</Grid>
{/* <Review ref={lastPostRef} key={country._id} country={country} review={review}/> */}
{isFetchingNextPage && <p className="center">Loading More Posts...</p>}
<p className="center">Back to Top</p>
</>
)
}
export default HomeScroll;
Card Components
`
import {
CardMedia,
CardContent,
CardActions,
Grid,
Box,
Paper,
Typography,
} from "#mui/material";
import { makeStyles } from "#material-ui/core/styles";
import { styled } from '#mui/material/styles';
import React, { useState, useEffect, useContext } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import MenuList from "../menu/menuItem";
import Flash from "../../components/Flash";
import { AuthContext } from "../../services/auth.context";
import Card4 from './HomeCards/HomeCountryCard';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
...theme.typography.body2,
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
}));
const useStyles = makeStyles({
gridContainer: {
paddingLeft: "40px",
paddingRight: "40px"
}
});
const CountryListCard = React.forwardRef(({ country }, ref) => {
const location = useLocation();
const navigate = useNavigate();
const { isAuthenticated, user } = useContext(AuthContext);
const classes = useStyles();
const rows =[{
country: country,
}]
const postBody = (
<>
<Card4 country={country} key={country.id}/>
</>
)
const content = ref
? <div ref={ref}>{postBody}</div>
: <div>{postBody}</div>
const handleViewClick = () => {
navigate(`/country/${country._id}`);
};
return (
<>
{location.state?.message && (
<Flash type={location.state.type} message={location.state.message} />
)}
{content}
{user && isAuthenticated && (
<Grid item xl={6} md={6} sm={12} xs={12}>
<MenuList countryId={country._id} />
</Grid>
)}
</>
);
})
export default CountryListCard;
`
`
import {
Rating,
Grid,
} from "#mui/material";
import React, { useState, useEffect, useContext } from "react";
import { useNavigate } from "react-router-dom";
import { Card, Col, Row, Button, Text } from "#nextui-org/react";
const Card4 = ({ country }) => {
const navigate = useNavigate();
const handleViewClick = () => {
navigate(`/country/${country._id}`);
};
return (
<>
<Card isPressable>
<Card.Body css={{ p: 0 }}>
<Card.Image
src={country.images[0].image}
objectFit="cover"
width="100%"
height={140}
alt={country.title}
/>
<Rating name="simple-controlled" value={country.overallRating} readOnly/>
</Card.Body>
<Card.Footer css={{ justifyItems: "flex-start" }}>
<Row wrap="wrap" justify="space-between" align="center">
<Text b>{country.title}</Text>
<Button flat auto rounded color="secondary"
onClick={handleViewClick}
>
<Text
css={{ color: "inherit" }}
size={12}
weight="bold"
transform="uppercase"
>
View Country
</Text>
</Button>
</Row>
</Card.Footer>
</Card>
</>
);
};
export default Card4
Picture of the problem
picture](https://i.stack.imgur.com/QObLp.png)
I tried adding the mui code to all different elements, I tried using a map function instead of infinite scroll but that was unfeasible, I tried other frontend libraries and got the same issues. I also tried changing all kinds of different spacing and sizing of elements.
I'm wanting to pass a state from my WeatherComponent through to my UserForm component and ideally would like to do this without making the UserForm a child component. At the moment I have the UserForm as a child component and that component is working fine when I render it because it's getting the weather state from the WeatherComponent. But now when I want to render my WeatherComponent it renders the UserComponent as well.
Is there another way I could use useContext or a method that doesn't rely on making a child component?
WeatherComponent:
import axios from 'axios';
import { useEffect, useState, createContext } from 'react';
import { Weather } from '../types';
import { MdWbSunny } from 'react-icons/md';
import { IoIosPartlySunny } from 'react-icons/io';
import { BsFillCloudSnowFill } from 'react-icons/bs';
import { Title, Text, Container } from '#mantine/core';
import UserForm from './UserForm';
export const WeatherContext = createContext<any>(null);
const WeatherComponent = () => {
const [weather, setWeather] = useState<Weather | null>();
const fetchWeatherData = async () => {
const response = await axios.get('http://mock-api-call/weather/get-weather');
setWeather(response.data.result.weather);
};
useEffect(() => {
fetchWeatherData();
}, []);
return (
<Container>
<WeatherContext.Provider value={weather?.forcast}>
<UserForm />
</WeatherContext.Provider>
<Title order={2}>
{weather?.forcast === 'Sunny' ? (
<MdWbSunny data-testid="sunny" />
) : weather?.forcast === 'Snowing' ? (
<BsFillCloudSnowFill data-testid="snowing" />
) : (
<IoIosPartlySunny data-testid="overcast" />
)}
</Title>
<Text size="xl" data-testid="forcast">
{weather?.forcast}
</Text>
<Text size="lg" data-testid="temp">
Temp: {`${weather?.min} to ${weather?.max}`}
</Text>
<Text size="md" data-testid="description">
{weather?.description}
</Text>
</Container>
);
};
export default WeatherComponent;
UserForm:
import React, { useContext, useState } from 'react';
import { Container, Title, TextInput, Button, Group, Header } from '#mantine/core';
import { useStateWithLocalStorage } from './UseStateWithLocalStorage';
import { WeatherContext } from './WeatherComponent';
import { MdWbSunny } from 'react-icons/md';
import { BsFillCloudSnowFill } from 'react-icons/bs';
import { IoIosPartlySunny } from 'react-icons/io';
const UserForm = () => {
const [inputValue, setInputValue] = useStateWithLocalStorage('', 'form');
const [show, setShow] = useState(true);
const weatherIcon = useContext(WeatherContext);
function handleChange(event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
setInputValue(() => ({
[event.target.name]: event.target.value,
}));
}
return (
<Header height={56} mb={120}>
<Container
style={{
display: 'flex',
flexDirection: 'row',
backgroundColor: 'gray',
justifyContent: 'space-between',
color: 'white',
alignItems: 'center',
padding: '10px',
fontSize: '25px',
fontWeight: 'bold',
boxShadow: '0 3px 6px 0 #555',
}}
>
<Group>
<Title order={2}>Welcome </Title>
{show && (
<TextInput
type="text"
name="name"
id="name"
placeholder="enter your name"
onChange={handleChange}
value={inputValue.name}
/>
)}
{show && <Button onClick={() => setShow((prev) => !prev)}>SAVE</Button>}
<Title order={2}>{inputValue.name ? inputValue.name : ''}</Title>
</Group>
<Group style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Title order={2}>
{weatherIcon === 'Sunny' ? (
<MdWbSunny data-testid="sunny" />
) : weatherIcon === 'Snowing' ? (
<BsFillCloudSnowFill data-testid="snowing" />
) : (
<IoIosPartlySunny data-testid="overcast" />
)}
</Title>
</Group>
</Container>
</Header>
);
};
export default UserForm;
I'm using asp.net core and react typescript and I would like to use paginatedEntity from my API and use it to create pagination in react. Any leads, please?
Below is the code:
import { Card, CardActionArea } from "#material-ui/core";
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";
import { Grid, Item } from "semantic-ui-react";
import LoadingComponent from "../../app/layout/LoadingComponent";
import { PagingParams } from "../../app/stores/pagination";
import { useStore } from "../../app/stores/store";
import { makeStyles, createStyles } from '#material-ui/core/styles';
import Pagination from '#material-ui/lab/Pagination';
import React from "react";
const useStyles = makeStyles((theme) =>
createStyles({
root: {
'& > * + *': {
marginTop: theme.spacing(2),
},
},
}),
);
export default observer(function AllProduct() {
const { productStore } = useStore();
const [, setLoadingPage] = useState(false);
const classes = useStyles();
const [page, setPage] = React.useState(1);
const handleChange = (_event: React.ChangeEvent<unknown>, value: number) => {
setPage(value);
};
function handleGetPage() {
setLoadingPage(true);
productStore.setPagingParams(new PagingParams(page));
productStore.loadProducts().then(() => setLoadingPage(false));
}
useEffect(() => {
productStore.loadProducts();
}, [productStore])
if (productStore.loadingInitial) return <LoadingComponent />
return (
<Grid style={{ marginTop: '7em' }}>
<Grid.Column width='5' id='FilterHeightSide'>
</Grid.Column>
<Grid.Column width='10'>
<div className={classes.root}>
{
productStore.products.map((product: any) =>
<Grid.Column key={product.id} width='10'>
<Card>
<CardActionArea >
<Item.Group>
<Item>
<Item.Image id='MainPhotoItems' style={{ marginLeft: '1em', marginTop: '1em' }} src={product.mainPhotoUrl} />
<Item.Content>
<Item.Header style={{ marginTop: '0.5em' }}>{product.productName}</Item.Header>
<Item.Meta style={{ marginTop: '1.5em' }}>
<span id="TextPrice" className='price'>${product.priceIncTax}</span>
<span className='stay'></span>
</Item.Meta>
<Item.Description><img src={product.brandPhotoUrl} alt="brand"
id="LogoBrandItem" /></Item.Description>
</Item.Content>
</Item>
</Item.Group>
</CardActionArea>
</Card>
</Grid.Column>
)
}
<Pagination count={productStore.totalPages} onChange={handleChange} onClick=
{handleGetPage} page={page} />
</div>
</Grid.Column>
</Grid>
)
})
I'm using asp.net core and react typescript and I would like to use paginatedEntity from my API and use it to create pagination in react. Any leads, please?
Well i finally find the solution :
import { Card, CardActionArea } from "#material-ui/core";
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";
import { Grid, Item } from "semantic-ui-react";
import LoadingComponent from "../../app/layout/LoadingComponent";
import { PagingParams } from "../../app/stores/pagination";
import { useStore } from "../../app/stores/store";
import { makeStyles, createStyles } from '#material-ui/core/styles';
import Pagination from '#material-ui/lab/Pagination';
import React from "react";
const useStyles = makeStyles((theme) =>
createStyles({
root: {
'& > * + *': {
marginTop: theme.spacing(2),
},
},
}),
);
export default observer( function AllProduct(){
const {productStore }=useStore();
const [, setLoadingPage] = useState(false);
const classes = useStyles();
const [page, setPage] = React.useState(1);
const handleChange = (_event: React.ChangeEvent<unknown>, value: number) => {
setLoadingPage(true);
productStore.setPagingParams(new PagingParams(productStore.pagingParams.pageNumber=value));
productStore.loadProducts().then(()=>setPage(value)).then(() => setLoadingPage(false));
};
useEffect(()=> {
productStore.loadProducts();
},[productStore])
if(productStore.loadingInitial ) return <LoadingComponent/>
return(
<Grid style={{marginTop:'8em'}}>
<Grid.Column width='5' id='FilterHeightSide'>
</Grid.Column>
<Grid.Column width='10'>
<div className={classes.root}>
{
productStore.products.map((product:any)=>
<Grid.Column key={product.id} width='10'>
<Card>
<CardActionArea >
<Item.Group>
<Item>
<Item.Image id='MainPhotoItems' style={{marginLeft:'1em' , marginTop:'1em'}} src={product.mainPhotoUrl} />
<Item.Content>
<Item.Header style={{marginTop:'0.5em'}}>{product.productName}</Item.Header>
<Item.Meta style={{marginTop:'1.5em'}}>
<span id="TextPrice" className='price'>${product.priceIncTax}</span>
<span className='stay'></span>
</Item.Meta>
<Item.Description><img src={product.brandPhotoUrl} alt="brand" id="LogoBrandItem" /></Item.Description>
</Item.Content>
</Item>
</Item.Group>
</CardActionArea>
</Card>
</Grid.Column>
)
}
<Pagination count={productStore.totalPages} page={page} onChange={handleChange} />
</div>
</Grid.Column>
</Grid>
)
})
i hope that will help others :)
I have a form in react where I'm using a Material UI TextField. I want a value present in the TextField and I can see that it is being set when I use the Inspect option of Google Chrome. In addition to that, I see that the type="hidden". I have changed this to type="text" and to no avail, the value is still not presented. Curious if anyone here has any understanding as to why this would happen. Below is the primary code that is causing the problem:
<TextField
name="Property"
select
fullWidth
margin="normal"
className={clsx(selectInputStyle.margin, selectInputStyle.textField, selectInputStyle.root)}
value={viewProperties[index].name}
onChange={this.handleSelectChange}
>
{propertyKeys.map((key, index) => (
<MenuItem value={key} key={index}>
{key}
</MenuItem>
))}
</TextField>
Here is the full code file just for a complete context of what is going on.
import React, { Component } from 'react';
import { Container, Form, Button, Row, Col, Nav, NavItem, NavLink, Input, FormGroup } from 'reactstrap';
import { connect } from 'react-redux';
import { reduxForm, FieldArray, arrayRemoveAll } from 'redux-form/immutable';
import * as Immutable from 'immutable';
import _ from 'lodash';
import { bindActionCreators } from 'redux';
import BlockUi from 'react-block-ui';
import MaterialButton from '#material-ui/core/Button';
import DeleteIcon from '#material-ui/icons/Delete';
import { makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Tabs from '#material-ui/core/Tabs';
import Tab from '#material-ui/core/Tab';
import MenuItem from '#material-ui/core/MenuItem';
import Select from '#material-ui/core/Select';
import InputMaterial from '#material-ui/core/Input';
import FormControl from '#material-ui/core/FormControl';
import TextField from '#material-ui/core/TextField';
import OutlinedInput from '#material-ui/core/OutlinedInput';
import clsx from 'clsx';
import { AvText, AvSelect } from '../forms/components';
import { showNotification, loadPayerProperties, updatePayerProperties } from '../actions';
class PayerPropertiesEditor extends Component {
constructor(props) {
super(props);
this.uploadRef = React.createRef();
this.state = {
errors: [],
refeshProperties: false,
blocking: false
};
this.showButton = false;
this.divPadding = { padding: '20px' };
this.doSubmit = this.doSubmit.bind(this);
this.handleInvalidSubmit = this.handleInvalidSubmit.bind(this);
this.renderProperties = this.renderProperties.bind(this);
this.handleSelectChange = this.handleSelectChange.bind(this);
this.useStyles = makeStyles(theme => ({
button: {
margin: theme.spacing(1)
},
leftIcon: {
marginRight: theme.spacing(1)
},
rightIcon: {
marginLeft: theme.spacing(1)
},
iconSmall: {
fontSize: 20
},
root: {
display: 'flex',
flexWrap: 'wrap'
},
formControl: {
margin: theme.spacing(1),
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing(2)
},
container: {
display: 'flex',
flexWrap: 'wrap'
},
input: {
margin: theme.spacing(1)
}
}));
}
componentDidMount() {
this.setState({ view: 'payer' });
}
componentDidUpdate(prevProps) {
const { loadPayerProperties } = this.props;
if (this.state.refeshProperties) {
this.props.arrayRemoveAll('payerPropertiesEditorForm', 'properties');
loadPayerProperties();
this.setState({ refeshProperties: false });
this.setState({ blocking: false });
this.showButton = false;
}
if (!prevProps.properties && this.props.properties) {
this.props.change('properties', Immutable.fromJS(this.props.properties));
}
}
doSubmit(values) {
const { updatePayerProperties } = this.props;
return new Promise(resolve => {
this.setState({
blocking: true
});
updatePayerProperties(values.toJS(), () => {
this.setState({ refeshProperties: true });
});
resolve();
});
}
handleInvalidSubmit() {
this.props.showNotification({
level: 'error',
message: 'Errors were found.'
});
}
handleSelectChange(event) {
console.log(event);
}
renderProperties({ fields }) {
const inputUseStyles = makeStyles(theme => ({
root: {
display: 'flex',
flexWrap: 'wrap'
},
formControl: {
margin: theme.spacing(1),
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing(2)
},
container: {
display: 'flex',
flexWrap: 'wrap'
},
margin: {
margin: theme.spacing(1)
},
textField: {
flexBasis: 200
},
input: {
margin: theme.spacing(1)
}
}));
const selectInputStyle = inputUseStyles().input;
const useStyles = this.useStyles();
const { formProperties, unsetPropertiesKeys } = this.props;
const viewProperties = formProperties[`${this.state.view}`];
const propertyKeys = unsetPropertiesKeys[`${this.state.view}`];
return (
<div maxWidth="sm" className={selectInputStyle.root}>
{fields.map((property, index) => (
<Row
key={index}
style={{
display: viewProperties[index].action === 'remove' ? 'none' : ''
}}
>
<Col xs={5}>
<TextField
select
fullWidth
margin="normal"
className={clsx(selectInputStyle.margin, selectInputStyle.textField, selectInputStyle.root)}
value={viewProperties[index].name}
onChange={this.handleSelectChange}
>
{propertyKeys.map((key, index) => (
<MenuItem value={key} key={index}>
{key}
</MenuItem>
))}
</TextField>
</Col>
<Col xs={5}>
<AvText
name={`${property}.value`}
onChange={() => {
if (viewProperties[index].action !== 'add') {
this.props.change(`${property}.action`, 'update');
this.showButton = true;
}
}}
/>
</Col>
<Col xs={1}>
<MaterialButton
variant="contained"
className="{classes.button}"
onClick={() => {
fields.remove(index);
if (viewProperties[index].action !== 'add') {
fields.insert(
index,
Immutable.fromJS(Object.assign({}, viewProperties[index], { action: 'remove' }))
);
this.showButton = true;
}
}}
>
Delete
<DeleteIcon className={useStyles.rightIcon} />
</MaterialButton>
</Col>
</Row>
))}
<Row>
<Col xs={12}>
<Button
color="primary"
onClick={() => {
fields.push(
Immutable.fromJS({
owner: this.props.ownerKeys[this.state.view],
action: 'add'
})
);
this.showButton = true;
}}
>
Add Property
</Button>
</Col>
</Row>
<br />
{this.showButton === true && (
<Row>
<Col xs={12}>
<Button color="primary" type="submit">
Submit
</Button>
</Col>
</Row>
)}
</div>
);
}
render() {
const { handleSubmit, properties, payerName, chsId, parentChsId } = this.props;
const formStyles = makeStyles(theme => ({
root: {
display: 'flex',
flexWrap: 'wrap'
},
formControl: {
margin: theme.spacing(1),
minWidth: 120
},
selectEmpty: {
marginTop: theme.spacing(2)
}
}));
const navItems = ['payer', 'clearinghouse', 'parent'].map(key => (
<Tab
textColor="primary"
key={key}
label={
key === 'payer'
? 'PAYER: ' + payerName
: key === 'clearinghouse'
? 'CLEARING HOUSE: ' + chsId
: 'PARENT: ' + parentChsId
}
onClick={() => this.setState({ view: key })}
/>
));
const overrides = this.state.view === 'payer' ? ['clearinghouse'] : this.state.view === 'parent' ? ['parent'] : [];
const readonly = properties
? overrides
.filter(key => key !== this.state.view)
.map(key => properties[key])
.reduce((acc, val) => acc.concat(val), [])
.map((property, idx) => {
return (
<Row key={idx}>
<Col xs={5}>
<FormGroup>
<Input value={property.name} disabled />
</FormGroup>
</Col>
<Col xs={5}>
<FormGroup>
<Input value={property.value} disabled />
</FormGroup>
</Col>
</Row>
);
})
: [];
return (
<BlockUi tag="div" blocking={this.state.blocking} className="my-2">
<Container maxWidth="sm">
<AppBar position="static" color="default">
<Tabs variant="fullWidth" textColor="primary">
{navItems}
</Tabs>
</AppBar>
<FormControl
fullWidth
className="mt-4"
onSubmit={handleSubmit(this.doSubmit)}
ref={form => (this.formRef = form)}
>
{readonly}
<FieldArray
name={`properties.${this.state.view}`}
component={this.renderProperties}
rerenderOnEveryChange
/>
</FormControl>
</Container>
</BlockUi>
);
}
}
const mapStateToProps = state => {
const {
payerPropertiesStore: {
payer: { payerId, payerName, chsId, parentChsId },
properties,
propertyKeys
},
form: {
payerPropertiesEditorForm: {
values: { properties: formProperties }
}
}
} = state.toJS();
const unsetPropertiesKeys = {};
for (const view of ['payer', 'clearinghouse', 'parent']) {
unsetPropertiesKeys[view] = propertyKeys.filter(key => !_.find(formProperties[view], { name: key }));
}
const ownerKeys = { payer: payerId, clearinghouse: chsId, parent: parentChsId };
return { formProperties, properties, ownerKeys, unsetPropertiesKeys, payerId, payerName, chsId, parentChsId };
};
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
showNotification,
loadPayerProperties,
updatePayerProperties,
arrayRemoveAll
},
dispatch
);
export default reduxForm({
form: 'payerPropertiesEditorForm',
enableReinitialize: true,
initialValues: Immutable.fromJS({ properties: {} })
})(
connect(
mapStateToProps,
mapDispatchToProps
)(PayerPropertiesEditor)
);
In the TextField you are setting value from viewProperties like,
value={viewProperties[index].name}
You are getting data in viewProperties from formProperties based on this.state.view
const viewProperties = formProperties[`${this.state.view}`];
As you are setting view state in componentDidMount, on intial render view is not set and don't have value so you are not getting any value from formProperties.
You need to have a default state,
this.state = {
errors: [],
refeshProperties: false,
blocking: false,
view: 'payer' // default set
};
I started to use material ui tabs and I'm having issues with the font size of the Tab labels because they are really small...
This is my code:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Tabs from '#material-ui/core/Tabs';
import Tab from '#material-ui/core/Tab';
import Typography from '#material-ui/core/Typography';
function TabContainer(props) {
return (
<Typography component="div" style={{ padding: 8 * 3 }}>
{props.children}
</Typography>
);
}
TabContainer.propTypes = {
children: PropTypes.node.isRequired,
};
const styles = theme => ({
root: {
flexGrow: 1,
backgroundColor: theme.palette.background.paper,
},
tabRoot: {
backgroundColor: theme.palette.background.paper,
flexGrow: 1,
color: 'black',
fontWeight: 'bold'
}
});
class SimpleTabs extends React.Component {
state = {
value: 0,
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
const { value } = this.state;
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs className={classes.tabRoot} value={value} onChange={this.handleChange}>
<Tab label="Item One" />
<Tab label="Item Two" />
</Tabs>
</AppBar>
{value === 0 && <TabContainer>Item One</TabContainer>}
{value === 1 && <TabContainer>Item Two</TabContainer>}
{value === 2 && <TabContainer>Item Three</TabContainer>}
</div>
);
}
}
SimpleTabs.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(SimpleTabs);
Is there any way to increase the size of those labels?
Material-ui Tab component label prop type is node. So if you want to add styles you need to put plain text inside div or span, o another html component and add className.
<Tab label={<span className={classes.tabLabel}>Label</span>}/>
1. You can set the style of the tab, and use an own wrapper component, e.g. like TabBigger:
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Tabs from '#material-ui/core/Tabs';
import Tab from '#material-ui/core/Tab';
import Typography from '#material-ui/core/Typography';
const styles = theme => ({
root: { backgroundColor: '#0af' },
tabRoot: { backgroundColor: '#0a6' },
label: {
backgroundColor: '#aa0',
fontSize: '22px'
},
});
function TabContainer(props) {
return (
<Typography component="div" style={{ padding: 8 * 3 }}>
{props.children}
</Typography>
);
}
const TabBigger = withStyles(styles)(( props )=>{
return (
<Tab className={props.classes.label} {...props}/>
);
});
class SimpleTabs extends React.Component {
state = {
value: 0,
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
const { value } = this.state;
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs className={classes.tabRoot} value={value} onChange={this.handleChange}>
<TabBigger label="Item One" />
<TabBigger label="Item Two" />
</Tabs>
</AppBar>
{value === 0 && <TabContainer>Item One</TabContainer>}
{value === 1 && <TabContainer>Item Two</TabContainer>}
{value === 2 && <TabContainer>Item Three</TabContainer>}
</div>
);
}
}
export default withStyles(styles)(SimpleTabs);
2. Alternatively, you might want to set the style of the tab-label (instead of the whole Tab component) with the MUI-rule labelContainer:
<Tab classes={{ root: { props.classes.tab }, labelContainer: props.classes.label }} />
With new versions of MUI you can specify the label component directly in the component
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Tabs from '#material-ui/core/Tabs';
import Tab from '#material-ui/core/Tab';
import Typography from '#material-ui/core/Typography';
const styles = theme => ({
root: { backgroundColor: '#0af' },
tabRoot: { backgroundColor: '#0a6' },
});
function TabContainer(props) {
return (
<Typography component="div" style={{ padding: 8 * 3 }}>
{props.children}
</Typography>
);
}
class SimpleTabs extends React.Component {
state = {
value: 0,
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
const { value } = this.state;
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs className={classes.tabRoot} value={value} onChange={this.handleChange}>
<Tab label={(<Typography variant="h6">Item One</Typography>)} />
<Tab label={(<Typography variant="h6">Item Two</Typography>)} />
</Tabs>
</AppBar>
{value === 0 && <TabContainer>Item One</TabContainer>}
{value === 1 && <TabContainer>Item Two</TabContainer>}
{value === 2 && <TabContainer>Item Three</TabContainer>}
</div>
);
}
}
export default withStyles(styles)(SimpleTabs);