I would like to set display property of a child element to inline, when there is a mouseOver or mouseEnter event in this React component.
I can see that the state is being set, but it does not change for the display property.
export class EditablePageTitle extends React.Component {
state = {
showEditIcon: 'none'
};
showEditIcon() {
console.log('showEditIcon 1 ', this.state.showEditIcon);
this.setState({ showEditIcon: 'inline' });
console.log('showEditIcon 2 ', this.state.showEditIcon);
}
render() {
return (
<FlexColumn
style={{
alignItems: 'baseline',
paddingBottom: s[3]
}}
>
<div id="page-title" onMouseEnter={() => this.showEditIcon()}>
<Input
{...this.props}
type={this.props.type || 'text'}
defaultValue={this.props.defaultValue}
disabled="disabled"
onChange={this.props.onChange}
/>
<i
className="fa fa-pencil-alt"
style={{
paddingRight: s[3],
color: '#FFFFFF',
fontSize: s[3],
display: this.state.showEditIcon
}}
/>
{console.log('this.state.showEditIcon ', this.state.showEditIcon)}
</div>
<Label>{this.props.label}</Label>
</FlexColumn>
);
}
}
Call the showEditIcon method like the following and also you should bind this:
export class EditablePageTitle extends React.Component {
constructor(props) {
super(props);
this.state = {
showEditIcon: 'none'
};
this.showEditIcon = this.showEditIcon.bind(this);
}
showEditIcon() {
console.log('showEditIcon 1 ', this.state.showEditIcon);
this.setState({ showEditIcon: 'inline' });
console.log('showEditIcon 2 ', this.state.showEditIcon);
}
render() {
return (
<FlexColumn
style={{
alignItems: 'baseline',
paddingBottom: s[3]
}}
>
<div id="page-title" onMouseEnter={this.showEditIcon}>
<Input
{...this.props}
type={this.props.type || 'text'}
defaultValue={this.props.defaultValue}
disabled="disabled"
onChange={this.props.onChange}
/>
<i
className="fa fa-pencil-alt"
style={{
paddingRight: s[3],
color: '#FFFFFF',
fontSize: s[3],
display: this.state.showEditIcon
}}
/>
{console.log('this.state.showEditIcon ', this.state.showEditIcon)}
</div>
<Label>{this.props.label}</Label>
</FlexColumn>
);
}
}
This is possibly a conflict with how Font Awesome and React handle rendering.
If you are using React we recommend the react-fontawesome package or Web Fonts with CSS.
https://fontawesome.com/how-to-use/on-the-web/using-with/react
However, you may just want to try wrapping your icon with a span and apply the display property there.
<span style={{ display: this.state.showEditIcon }}>
<i className="fa fa-pencil-alt"
style={{
paddingRight: s[3],
color: '#FFFFFF',
fontSize: s[3]
}}
/>
</span>
Related
Now i have used state hook to hide the Form when the page loads. And upon the click or toggle of the radio I'm able to show the Form, But if i toggle the radio again, the form is not hiding.
This is what i have implemented:
const WelcomeTab = () => {
const [toggle, settoggle] = useState(false);
return (
<React.Fragment>
<Tab.Pane
style={{
borderRadius: '7px',
padding: '30px',
}}
attached={false}
>
<Grid>
<Grid.Row>
<Grid.Column floated="left" width={8}>
<Header
style={{
fontSize: '18px',
fontFamily: 'Nunito-Regular',
color: '#4F4F4F',
}}
>
Welcome Screen
</Header>
</Grid.Column>
<Grid.Column floated="right" width={4}>
<Header
as="h4"
style={{
display: 'flex',
justifyContent: 'space-around',
marginLeft: '30px',
}}
>
Customize
<Radio toggle onChange={() => settoggle({ toggle: !toggle })} />
</Header>
</Grid.Column>
</Grid.Row>
</Grid>
{toggle ? (
<Form style={{ paddingTop: '20px' }}>
<Form.Field>
<label style={lableStyle}>Title</label>
<input style={{ marginBottom: '20px' }} />
<label style={lableStyle}>Message</label>
<TextArea />
</Form.Field>
</Form>
) : null}
</Tab.Pane>
</React.Fragment>
);
};
const lableStyle = {
fontFamily: 'Nunito-Regular',
fontWeight: 400,
color: '#4F4F4F',
fontSize: '15px',
display: 'inline-block',
marginBottom: '10px',
};
export default WelcomeTab;
try to add useEffect hook along with change like below,
you no longer need to {} this is old syntax of setState, using hooks we directly make the changes, hope this helps
useEffect(()=>{},[toggle])
replace this wrong syntax code, i can see its not json its boolean value
<Radio toggle onChange={()=>settoggle({toggle: !toggle})}/>
as this is old syntax not work with hooks, try to implment this instead,
<Radio toggle onChange={()=>settoggle(!toggle)}/>
I am new to react-admin, and how to customize react admin buttons?
In my scenario I have a list also in create, edit, and export button there and I don't know which is the best way to change button css in react-admin. Can anyone solve this?
By default I have button like above mentioned, so I need to add css for this two buttons.
Here is my sample code
// style list
const useStyles = makeStyles((theme) => ({
userCard: {
padding: "20px",
borderRadius: "12px",
},
btn_edit: {
background: "#5E35B1",
color: "#fff",
fontSize: "10px",
},
mainList: {
boxShadow: "none !important",
borderRadius: "0px",
},
listCreateIcon: {
padding: "0px !important",
},
}));
//main
export const UserList = (props) => {
const classes = useStyles();
return (
<Card className={classes.userCard}>
<List
{...props}
pagination={null}
perPage={9999}
className={classes.mainList}
>
<Datagrid className={classes.listCard}>
<TextField source="username" />
<BooleanField source="enabled" />
<ReferenceArrayField reference="_roles" source="roles">
<SingleFieldList>
<ChipField source="name" />
</SingleFieldList>
</ReferenceArrayField>
<EditButton className={classes.btn_edit} />
</Datagrid>
</List>
</Card>
);
};
export const UserCreate = (props) => {
const classes = useStyles();
return (
<Create {...props} className={classes.listCreateIcon}>
<SimpleForm style={{ padding: "0px !important" }}>
<TextInput source="username" />
<TextInput type="password" source="password" />
<ReferenceArrayInput source="roles" reference="_roles" allowEmpty>
<SelectArrayInput optionText="name" />
</ReferenceArrayInput>
<BooleanInput source="enabled" defaultValue={true} />
</SimpleForm>
</Create>
);
};
export const UserEdit = (props) => (
<Edit {...props}>
<SimpleForm>
<TextField source="username" />
<ReferenceArrayInput source="roles" reference="_roles">
<SelectArrayInput optionText="name" />
</ReferenceArrayInput>
<BooleanInput source="enabled" />
</SimpleForm>
</Edit>
);
This will work for you.
btn_create: {
display: "inline-flex",
alignItems: "center",
gridGap: 4,
backgroundColor: "transparent",
borderColor: "transparent",
fontSize: 16,
color: "blue" // the text color you want
// if you are using the svg icon
svg : {
width: 16,
height: 16,
path: {
fill : "blue" //color code of icon
}
}
},
btn_group: {
display:"flex",
gridGap: "16px",
alignItems: "Center",
}
on Component
<div className={classes.btn_group}>
<EditButton className={classes.btn_create} />
<EditButton className={classes.btn_create} />
</div>
PS. If the icon is font icon, you may not use the svg styling.
I'm new to reactjs and I want an e-trade project. The problem is pressing the first "+" button, but increasing the number in the box next to it. How can I do this?
When I press the first, the other shouldn't increase because I will add more vegetable.
How can I solve this? Thank you so much
class App extends Component {
constructor(props) {
super(props);
this.state = {
counter: 0
};
}
increment() {
this.setState(prevState => ({
counter: this.state.counter + 1
}));
}
decrement() {
if (this.state.counter === 0) {
this.setState({
counter: 0
});
} else {
this.setState(prevState => ({
counter: this.state.counter - 1
}));
}
}
render() {
return (
<div class="container">
<div class="row" style={{ marginTop: '50px' }}>
<Card className="col-md-3" style={{ }}>
<Card.Img variant="top" src="https://res.cloudinary.com/sivadass/image/upload/v1493620046/dummy-products/broccoli.jpg" style={{ width: '200px',marginLeft:'30px' }}/>
<Card.Body>
<Card.Title style={{ textAlign: 'center' }}> Brocoli - 1
</Card.Title>
<Card.Text style={{ textAlign: 'center' }}>
1 $
</Card.Text>
<div style={{ textAlign: 'center' }}>
<Button onClick={this.decrement.bind(this)}>-</Button>
<h2 value="1">{this.state.counter}</h2>
<Button onClick={this.increment.bind(this)}>+</Button>
</div>
</Card.Body>
</Card>
<Card className="col-md-3" style={{ marginLeft:'10px' }}>
<Card.Img variant="top" src="https://res.cloudinary.com/sivadass/image/upload/v1493620046/dummy-products/broccoli.jpg" style={{ width: '200px',marginLeft:'30px' }}/>
<Card.Body>
<Card.Title style={{ textAlign: 'center' }}> Brocoli - 1
</Card.Title>
<Card.Text style={{ textAlign: 'center' }}>
1 $
</Card.Text>
<div style={{ textAlign: 'center' }}>
<Button onClick={this.decrement.bind(this)}>-</Button>
<h2 value="1">{this.state.counter}</h2>
<Button onClick={this.increment.bind(this)}>+</Button>
</div>
</Card.Body>
</Card>
</div>
</div>
)
}
}
export default App;
Can you please check whether you are looking for the following type of solution or not? Please ignore the styling I have just implemented the functionality.
constructor(props) {
super(props);
this.state = {
items:[{
name:"Veg 1",
counter:0
},{
name:"Veg 2",
counter:0
}]
};
}
increment = (index) =>{
let localItems = [...this.state.items];
localItems[index].counter += 1;
this.setState({
...this.state,
items:[...localItems]
})
}
decrement = (index) =>{
let localItems = [...this.state.items];
localItems[index].counter -= 1;
this.setState({
...this.state,
items:[...localItems]
})
}
render() {
const { classes } = this.props;
return (
this.state.items.length ? this.state.items.map((item,index)=>{
return (
<div>
<button onClick={()=>this.increment(index)}>+</button>
<span>{item.name} - {item.counter}</span>
<button onClick={()=>item.counter && this.decrement(index)}>-</button>
</div>
)
}):null
)
}
I am trying to pass my API value to the Flippy card to dynamically render image and the word displayed on flip.
I am struggling with something I thought would be easy: I have an API where I call back an image link and a word to populate the flip cards. I want to dynamically render my flip cards to the page using that data, but right now my image link and the word are hard coded and I don't know to pass my API call values to the component. API works and correctly returns links and words; hard coded flip card also works with no issues and functions as intended. I believe I have to implement props and pass it somehow to the const DefaultCardContents- thanks so much for taking a stab at it.
I tried implemeneting props but I am unsure how to pass them to the constant
THIS IS MY FLASHCARD COMPONENT
import React, { Component } from 'react';
import Flippy, { FrontSide, BackSide } from './../lib';
import Button from 'react-bootstrap/Button';
import './style.css';
const FlippyStyle = {
width: '200px',
height: '200px',
textAlign: 'center',
color: '#FFF',
fontFamily: 'sans-serif',
fontSize: '30px',
justifyContent: 'center'
}
const DefaultCardContents = ({ children }) => (
<React.Fragment>
<FrontSide
style={{
backgroundColor: 'white',
display: 'flex',
alignItems: 'center',
flexDirection: 'column'
}}
>
<img
src="https://parent.guide/wp-content/uploads/2014/08/Banana-baby-food-recipes.jpg"
style={{ maxWidth: '100%', maxHeight: '100%' }}
/>
<span
style={{
fontSize: '12px',
position: 'absolute',
bottom: '10px',
width: '100%'
}}>
{children}<br />
Hover over to show key word
</span>
</FrontSide>
<BackSide
style={{
backgroundColor: '#EB6864',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column'
}}>
<h1>Banana</h1>
<span
style={{
fontSize: '12px',
position: 'absolute',
bottom: '10px',
width: '100%'
}}>
{children}<br />
<Button variant="success">Success</Button>
<Button variant="outline-warning">Warning</Button>
</span>
</BackSide>
</React.Fragment>);
const FlippyOnHover = ({ flipDirection = 'vertical' }) => (
<Flippy
flipOnHover={true}
flipDirection={flipDirection}
style={FlippyStyle}
>
<DefaultCardContents>
</DefaultCardContents>
</Flippy>
);
class Flashcard extends Component {
constructor(props) {
super(props);
this.state = {
isFlipped: false
}
}
render() {
return (
<div className="App">
<div style={{ display: 'flex', flex: '1 0 200px', justifyContent: 'space-around', 'flex-wrap': 'wrap' }}>
<FlippyOnHover flipDirection="horizontal" />
</div>
</div>
);
}
}
export default Flashcard;
THIS IS MY API CALL AND PAGE RENDER
import React, { Component } from "react";
import Flashcard from "../components/Flashcard";
import API from "../utils/API";
class Flashcards extends Component {
state = {
flashcards: [],
flashcardName: "",
flashcardImage: "",
flipped: false
};
componentDidMount() {
this.loadFlashcards();
};
loadFlashcards = () => {
API.getFlashcards()
.then(res => {
// console.log(res.data);
this.setState({ flashcards: res.data, flashcardName: "", flashcardImage: "" })
// console.log("flashhhhhhhhhh" + JSON.stringify(this.state.flashcards));
})
.catch(err => console.log(err));
};
flipped = () => {
console.log(this.state)
if (this.state.flipped === false) {
this.setState({ flipped: true })
}
}
render() {
return (
<div>
{this.state.flashcards.length ? (
<div>
{this.state.flashcards.map(flashcards => (
<div key={flashcards._id} >
<Flashcard/>
</div>
))}
</div>
) : (
<h3>No Results to Display</h3>
)}
</div>
)
}
}
export default Flashcards;
Expected result is a dynamically generated array of cards base don API
You need to modify your Flashcard component to accept props for the title and the URL for the image, assuming that is in the data returned from the API.
In your map, pass the values to the Flashcard, something like:
{this.state.flashcards.map(flashcard => (
<div key={flashcard._id}>
<Flashcard
title={flashcard.title}
imageUrl={flashcard.image}
/>
</div>
))}
Edit:
Looks like your are using the react-flippy library, so you don't need to manage what state the flash card is in.
Crudly, your FlashCard component could look something like:
import React, { Component } from "react";
import Flippy, { FrontSide, BackSide } from "./../lib";
import Button from "react-bootstrap/Button";
import "./style.css";
const FlippyStyle = {
width: "200px",
height: "200px",
textAlign: "center",
color: "#FFF",
fontFamily: "sans-serif",
fontSize: "30px",
justifyContent: "center"
};
const CardContents = ({ title, imageUrl }) => (
<React.Fragment>
<FrontSide
style={{
backgroundColor: "white",
display: "flex",
alignItems: "center",
flexDirection: "column"
}}
>
<img
src={imageUrl}
style={{ maxWidth: "100%", maxHeight: "100%" }}
/>
<span
style={{
fontSize: "12px",
position: "absolute",
bottom: "10px",
width: "100%"
}}
>
<br />
Hover over to show key word
</span>
</FrontSide>
<BackSide
style={{
backgroundColor: "#EB6864",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexDirection: "column"
}}
>
<h1>{title}</h1>
<span
style={{
fontSize: "12px",
position: "absolute",
bottom: "10px",
width: "100%"
}}
>
<br />
<Button variant="success">Success</Button>
<Button variant="outline-warning">Warning</Button>
</span>
</BackSide>
</React.Fragment>
);
class Flashcard extends Component {
render() {
return (
<div>
<div
style={{
display: "flex",
flex: "1 0 200px",
justifyContent: "space-around",
"flex-wrap": "wrap"
}}
>
<Flippy flipOnHover={true} flipDirection='horizontal' style={FlippyStyle}>
<CardContents imageUrl={this.props.imageUrl} title={this.props.title}/>
</Flippy>
</div>
</div>
);
}
}
export default Flashcard;
I'm struggling to find a solution to my problem, but no success yet.
My idea is: when the user receives the 6 digits code from the API and hits confirm the page will reload and send him to the main app. I have looked around if there is any function that can help me resolve my problem, but the only idea that seems to be working for now is to link the button from the ValidationPage to the rooting stack and give the function onPress to send the user to the MainPage.js.
But my opinion is that this is not the right way to do this. So does anyone have an idea how to tackle this problem? I'll be glad if someone can help me. Thank you! The outlook of the page looks like this :
LoginPage.js
import React, { Component } from 'react';
import { Linking, Image, View, AsyncStorage, Dimensions } from "react-native";
import { Container, Icon, Text, Content, Button, Input, Item } from "native-base";
export default class LoginScreen extends Component {
constructor(props) {
super(props);
this.state = {}
}
state = {
fontLoaded: false,
}
async componentWillMount() {
await Expo.Font.loadAsync({
Roboto: require("native-base/Fonts/Roboto.ttf"),
Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),
Ionicons: require("#expo/vector-icons/fonts/Ionicons.ttf"),
});
this.setState({ fontLoaded: true });
}
render() {
return (
this.state.fontLoaded ? (
<Container>
<Content>
<View style={{ alignContent: 'center', alignItems: 'center' }}>
<Image
style={{
width: '60%',
height: 200,
}}
source={require('../../assets/images/Shootlog.png')} />
</View>
<Text style={{ textAlign: 'center', lineHeight: 30, fontWeight: 'bold', fontSize: 20, color: 'grey' }}> Welcome to myShootLog</Text>
<Text style={{ textAlign: 'center', color: '#be0202' }}>Smart Shooting Solution for shooting ranges.</Text>
<Text style={{ padding: 20, textAlign: 'center', color: 'grey' }}> To continue , please fill in your email adress :</Text>
<View style={{ alignContent: 'center', alignItems: 'center', margin: 20 }}>
<Item style={{ marginBottom: 10 }}>
<Input
placeholder='example#mail.com'
onChangeText={(text) => this.validate(text)}
value={this.state.email}
keyboardType='email-address'
/>
<Icon name={this.state.emailCheck} />
</Item>
<Button full onPress={() => this.props.navigation.navigate('Validation')} style={{ backgroundColor: '#e72a2e'}}>
<Text style={{ textTransform: 'uppercase', }}>{'send'.toUpperCase()}</Text>
<Icon name='arrow-forward' />
</Button>
</View>
</Content>
<View style={{ width: '100%', alignContent: 'center', position: 'absolute', top: footerTopPosition }}>
<Text style={{ color: 'grey', fontSize: 11, textAlign: 'center' }} >All Rights Reserved.® 2018 by CanDoIt </Text>
<Text style={{ color: 'grey', fontSize: 10, textAlign: 'center' }} onPress={() => Linking.openURL('http://candoit.be')}>www.candoit.be</Text>
</View>
</Container>
) : null
);
}
validate = (text) => {
let reg = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (reg.test(text) === false) {
console.log('email is incorrect')
this.setState({ emailCheck: 'close-circle' });
return false;
}
else {
this.setState({ emailCheck: 'checkmark-circle' })
console.log('email is correct')
}
}
}
ValidationPage.js
import React, { Component } from 'react';
import { Linking, Image, View, AsyncStorage, Dimensions } from "react-native";
import { Container, Icon, Text, Content, Button, Input, Item } from "native-base";
export default class ValidationScreen extends Component {
constructor(props) {
super(props);
this.state = {}
}
state = {
fontLoaded: false,
}
async componentWillMount() {
await Expo.Font.loadAsync({
Roboto: require("native-base/Fonts/Roboto.ttf"),
Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),
Ionicons: require("#expo/vector-icons/fonts/Ionicons.ttf"),
});
this.setState({ fontLoaded: true });
}
render() {
const { navigate } = this.props.navigation;
return (
this.state.fontLoaded ? (
<Container>
<Content>
<View style={{ alignContent: 'center', alignItems: 'center' }}>
<Image
style={{
width: '60%',
height: 200,
}}
source={require('../../assets/images/Shootlog.png')} />
</View>
<Text style={{ textAlign: 'center', lineHeight: 30, fontWeight: 'bold', fontSize: 20, color: 'grey' }}> Welcome to NicoLog</Text>
<Text style={{ textAlign: 'center', color: '#be0202' }}>Smart Shooting Solution for shooting ranges.</Text>
<Text style={{ padding: 20, textAlign: 'center', color: 'grey' }}> Please fill in the 6 digits code from the email that you have recieved :</Text>
<View style={{ alignContent: 'center', alignItems: 'center', margin: 20 }}>
<Item style={{ marginBottom: 10 }}>
<Input
placeholder='Ex. 910-519'
onChangeText={(text) => this.validate(text)}
value={this.state.email}
keyboardType='number-pad'
/>
<Icon name={this.state.emailCheck} />
</Item>
<Button full onPress={() => this.props.navigation.navigate('Main')} style={{ backgroundColor: '#e72a2e' }}>
<Icon name='checkmark-circle' />
<Text style={{ textTransform: 'uppercase' }}>{'confirm'.toUpperCase()}</Text>
</Button>
<Text style={{ padding: 20, textAlign: 'center', color: 'grey' }}>If you didn't recieved anything please click the button bellow.</Text>
<Button full style={{ backgroundColor: '#e72a2e' }}>
<Icon name='refresh' />
<Text style={{ textTransform: 'uppercase' }}>{'re-send'.toUpperCase()}</Text>
</Button>
</View>
</Content>
<View style={{ width: '100%', alignContent: 'center', position: 'absolute', top: footerTopPosition }}>
<Text style={{ color: 'grey', fontSize: 11, textAlign: 'center' }} >All Rights Reserved.® 2018 by CanDoIt </Text>
<Text style={{ color: 'grey', fontSize: 10, textAlign: 'center' }} onPress={() => Linking.openURL('http://candoit.be')}>www.candoit.be</Text>
</View>
</Container>
) : null
);
}
validate = (text) => {
let reg = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (reg.test(text) === false) {
console.log('email is incorrect')
this.setState({ emailCheck: 'close-circle' });
return false;
}
else {
this.setState({ emailCheck: 'checkmark-circle' })
console.log('email is correct')
}
}
callMain = () => {
this.props.callParent(); // accsessing the function from the parent App.js
}
}
Navigation.js
import React from 'react';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import LoginScreen from './screens/LoginScreen';
import ValidationScreen from './screens/ValidationScreen';
export default createAppContainer( createStackNavigator (
{
Login: { screen: LoginScreen},
Validation: { screen: ValidationScreen},
},
{
headerMode: 'none'
}
));