I want to clear dropdown inside a form, when a user clicks reset button.
But can't figure out how to programatically set value.
SUIR uses declarative API. You need to use HOC for controlling Dropdown's value.
I've made a basic example that shows how to deal with it.
const {
Button,
Container,
Divider,
Dropdown,
Label,
} = semanticUIReact
const options = [
{ value: 'all', text: 'All' },
{ value: 'articles', text: 'Articles' },
{ value: 'products', text: 'Products' },
]
class App extends React.Component {
constructor(props) {
super(props);
this.state = { value: 'all' }
}
reset() {
this.setState({ value: undefined })
}
setProducts() {
this.setState({ value: 'products' })
}
setValue(e, data) {
this.setState({ value: data.value })
}
render() {
const { value } = this.state
return (
<Container>
<Label content={`Current: ${value}`} />
<Divider />
<Dropdown
onChange={this.setValue.bind(this)}
options={options}
selection
value={value}
/>
<Divider />
<Button
content='Reset'
onClick={this.reset.bind(this)}
/>
<Button
content='Set products'
onClick={this.setProducts.bind(this)}
/>
</Container>
)
}
}
// ----------------------------------------
// Render to DOM
// ----------------------------------------
const mountNode = document.createElement('div')
document.body.appendChild(mountNode)
ReactDOM.render(<App />, mountNode)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
<script src="https://unpkg.com/semantic-ui-react/dist/umd/semantic-ui-react.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.4/semantic.min.css">
Difficult without seeing your code, try setting 'value': []
Related
I have two buttons that show two different components when toggling them. For UX reasons (to know which component is showing) I would like to style the buttons according to if the value of the state is true or false (give them an underline and a darker color if the state is true). Is this possible in any way?
This is my GitHub repo: https://github.com/uohman/Portfolio2022
And this is the component where I handle the buttons:
`
import React, { useState } from 'react'
import ReactDOM from 'react-dom';
import { Subheading } from 'GlobalStyles';
import { FrontendProjects } from './FrontendProjects'
import { GraphicDesignProjects } from './GraphicDesignProjects';
import 'index.css'
export const FeaturedProjects = () => {
const [buttons, setButtons] = useState([
{ label: 'Development', value: true },
{ label: 'Graphic design', value: false }
]);
const handleButtonsChange = () => (label) => {
const newButtonsState = buttons.map((button) => {
if (button.label === label) {
return (button = { label: button.label, value: true });
}
return {
label: button.label,
value: false
};
});
setButtons(newButtonsState);
};
return (
<>
<Subheading><span>Featured projects</span></Subheading>
<SpecialButton {...{ buttons, setButtons, handleButtonsChange }} />
{buttons[0].value && <FrontendProjects />}
{buttons[1].value && <GraphicDesignProjects />}
</>
);
};
const SpecialButton = ({ buttons, setButtons, handleButtonsChange }) => {
return (
<div className="button-container">
{buttons.map((button, index) => (
<button
key={`${button.label}-${index}`}
onClick={() => handleButtonsChange({ buttons, setButtons })(button.label)}>
{button.label.toUpperCase()}
</button>
))}
</div>
);
};
const rootElement = document.getElementById('root');
ReactDOM.render(<FeaturedProjects />, rootElement);
`
I've given the buttons the pseudo element :focus and that nearly solves my problem, but still as a default the buttons are the same color although it is one of the components that is showing. Thankful for suggestions on how to solve this!
You can provide a style props to any html component.
You should pass an object where attributes are camelcased.
<button
style={{ // double bracket to pass an object
backgroundColor: yourVariable ? 'red' : undefined // notice css background-color became backgroundColor
}}
>
{button.label.toUpperCase()}
</button>
You can do the same with classes
<button
className={yourVariable && "yourClass"}
>
{button.label.toUpperCase()}
</button>
You can set styles for button based on a condition.
In this use case, you already have the state button.value which can be used as a condition to set inline styles (or classes) for the mapped button.
Example:
const SpecialButton = ({ buttons, setButtons, handleButtonsChange }) => {
return (
<div className="button-container">
{buttons.map((button, index) => (
<button
key={`${button.label}-${index}`}
// 👇 This property is added
style={{
backgroundColor: button.value ? "#aaa" : "#eee",
textDecoration: button.value ? "underline" : "none",
}}
onClick={() =>
handleButtonsChange({ buttons, setButtons })(button.label)
}
>
{button.label.toUpperCase()}
</button>
))}
</div>
);
};
The buttons are set to become darker when selected in the above example, but you can further customize the styles for the desired result.
More about inline styles
On a side note, it is not necessary to pass state values to the the event by onClick={() => handleButtonsChange({ buttons, setButtons })(button.label)}.
The parent component always have these values, so you do not need to pass it down to SpecialButton and pass it back.
Hope this will help!
Full example:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Subheading } from "GlobalStyles";
import { FrontendProjects } from "./FrontendProjects";
import { GraphicDesignProjects } from "./GraphicDesignProjects";
import "index.css";
export const FeaturedProjects = () => {
const [buttons, setButtons] = useState([
{ label: "Development", value: true },
{ label: "Graphic design", value: false },
]);
const handleButtonsChange = (label) => {
const newButtonsState = buttons.map((button) => {
if (button.label === label) {
return (button = { label: button.label, value: true });
}
return {
label: button.label,
value: false,
};
});
setButtons(newButtonsState);
};
return (
<>
<Subheading>
<span>Featured projects</span>
</Subheading>
<SpecialButton {...{ buttons, handleButtonsChange }} />
{buttons[0].value && <FrontendProjects />}
{buttons[1].value && <GraphicDesignProjects />}
</>
);
};
const SpecialButton = ({ buttons, handleButtonsChange }) => {
return (
<div className="button-container">
{buttons.map((button, index) => (
<button
key={`${button.label}-${index}`}
// 👇 This property is added
style={{
backgroundColor: button.value ? "#aaa" : "#eee",
textDecoration: button.value ? "underline" : "none",
}}
onClick={() =>
handleButtonsChange(button.label)
}
>
{button.label.toUpperCase()}
</button>
))}
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<FeaturedProjects />, rootElement);
I have a React Component ValidationEditor that calls another custom React Component Property, which holds the property value a array of strings.
interface props extends ValidationDataProperty {
tree: Tree;
}
const ValidationEditor = ({ tree, id, ifData, thenData, elseData }: props) => {
const { classes } = useStyles();
const { state, dispatch } = useContext(PropertyContext);
const updateValidation = modifyConditionalProperty(id, dispatch);
return (
<Group className={classes.validator}>
<Box></Box>
<Text>If</Text>
<Property
value={[""]}
mode="edit"
tree={tree}
onClick={(e: { target: { value: SetStateAction<string[]> } }) =>
updateValidation({ ifData: { ...ifData, value: e.target.value } })
}
/>
<NativeSelect
data={_.keys(ComparisonType)}
required
value={ifData.comparison}
onChange={(e: { target: { value: SetStateAction<string> } }) =>
updateValidation({
ifData: { ...ifData, comparison: e.target.value },
})
}
/>{" "}
<TextInput
placeholder="Provide conditional value"
required
value={ifData.value}
sx={{ flex: 1 }}
onChange={(e: { target: { value: SetStateAction<string> } }) =>
updateValidation({ ifData: { ...ifData, value: e.target.value } })
}
/>
</Group>
);
};
export default ValidationEditor;
Now I want to add a onClick event to the Property React Component . Basically onClick I want to call an action -> modifyConditionalProperty(id, dispatch) , that will update the store via a reducer. I am only struggling to make it work only for my custom React component Property rest its working fine.
This is how the Property component looks like
interface PropertyProps {
value?: string[];
mode: "edit" | "display";
tree: Tree;
onClick?: (e: { target: { value: SetStateAction<string[]> } }) => void;
}
const Property = ({ value, mode, tree }: PropertyProps) => {
const [currentValue, setCurrentValue] = useState<string[]>(value || []);
const [displayMode, toggle] = useToggle(mode, ["edit", "display"]);
console.log(value) // ["a", "b", "c"]
return (
<Box>
.....
</Box>
);
};
export default Property;
Goal
I need to modify the CSS for the reactjs-dropdown-component.
Background/Overview
I've downloaded the dropdown, imported it, and have it fully operational in react. However, I'm fairly new to coding and haven't yet been in a situation where I need to do significant styling to a downloaded component. Do I just recreate the stylesheet for it and import it?
The css for this component is in this Github repo: https://github.com/dbilgili/Custom-ReactJS-Dropdown-Components/blob/master/src/styles/stylus/dropdown.styl
The instructions I followed for downloading/using this dropdown are here: https://github.com/dbilgili/Custom-ReactJS-Dropdown-Components
I'm not sure that it's necessary but here is code where I'm using the dropdown
import React from 'react';
import './EventContainer.css';
import { Dropdown } from 'reactjs-dropdown-component';
import { dining } from './EventContainerIcons.js';
class EventContainer extends React.Component {
constructor(props){
super(props);
this.state = {
...props.event,
activityIcon: [
{
id: 0,
title: <img src={dining} width="64" height="64" alt="dining icon" />,
selected: false,
key: 'activityIcon'
},
{
id: 1,
title: 'Orange',
selected: false,
key: 'activityIcon'
},
{
id: 2,
title: 'Strawberry',
selected: false,
key: 'activityIcon'
}
],
};
}
handleTypeChange = (e) => {
this.setState({
type: e.target.value
})
}
handleTimeChange = (e) => {
this.setState({
time: e.target.value
})
}
handleSummaryChange = (e) => {
this.setState({
summary: e.target.value
})
}
handleNotesChange = (e) => {
this.setState({
notes: e.target.value
})
}
resetThenSet = (id, key) => {
let temp = this.state[key];
temp.forEach(item => (item.selected = false));
temp[id].selected = true;
this.setState({
[key]: temp
});
};
render(){
return (
<div className="eventContainer-flex">
<Dropdown
title="Event Type"
list={this.state.activityIcon}
resetThenSet={this.resetThenSet}
/>
<div>
<input
className="time-input-styling"
type="time"
value={this.state.time}
onChange={this.handleTimeChange}/>
</div>
<div>
<textarea
className="textarea-styling"
/*placeholder="Write summary here"*/
value={this.state.summary}
onChange={this.handleSummaryChange}
cols={60}
rows={3} />
</div>
<div>
<textarea
className="textarea-styling"
/*placeholder="Write notes here"*/
value={this.state.notes}
onChange={this.handleNotesChange}
cols={30}
rows={3} />
</div>
</div>
)
}
}
export default EventContainer;
In the documentation, they alreayd said it:
Refer to the following styling file for overriding the default styles.
You can create your own styling file with the same class names in
order to do your custom styling.
So, you have to create your css file, with the classes and override the classes you want.
I made a variable that has the style which I would want the input box to change to when it is clicked on.
How can I implement it so that when the input box is clicked, the border color of the input box changes to blue, considering that CSS, styles and everything else are imported?
const inputStyle = css
border-color: blue;
;
const InputBox = styled.input
myClick: function () {
inputstyle
}
;
render() {
return (
<InputBox
placeholder='Click Me'
type='text'
onClick={this.myClick}
/>
styled.foo doesn't return a class component, so writing methods as if they're on a class in the template string won't work.
Since you're handling something stateful (was this thing clicked?) you need to have some place to put that state. Then you can pass that state to the InputBox component:
const InputBox = styled.input`
border-color: ${({ clicked }) => clicked ? 'blue' : 'transparent'};
`
class Parent extends React.Component {
constructor (props) {
this.state = { clicked: false }
}
handleClick () {
this.setState({ clicked: true })
}
render () {
return (
<InputBox
placeholder="Click Me"
type="text"
clicked={this.state.clicked}
onClick={this.handleClick}
/>
)
}
}
I'd suggest checking out the "Passed Props" section of the styled-components docs.
you can do this :
const Styles = {
inputNormal:{color:'blue'},
inputClicked:{color:'red'}
}
class Parent extends React.Component {
constructor (props) {
this.state = { clicked: false }
}
handleClick () {
this.setState({ clicked: true })
}
render () {
return (
<InputBox
placeholder="Click Me"
type="text"
style={this.state.clicked?styles.inputNormal:styles.inputClicked}
onClick={this.handleClick}
/>
)}}
You should add styles with variables like this:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
clicked: false
};
}
myClick = () => {
this.setState({
clicked: true
});
};
render() {
const inputStyle = {
borderColor: "blue"
};
return (
<input
placeholder="Click Me"
type="text"
onClick={this.myClick}
style={this.state.clicked ? inputStyle : null}
/>
);
}
}
Here is a working demo:
DEMO
I've got a form with multiple different types of inputs, including text inputs, checkboxes, and radio buttons. Due to the nature of data surrounding a particular radio button set, I've had to extract it into its own component. What's weird is that any time any of the other radio buttons are selected, it causes the radio button group to become unselected.
I have a "Yes" and "No" option that map to true/false. When it's true, an element appears on the screen with checkboxes. When false, nothing special happens. When it's true and I select another radio button from another radio button group, it works fine, however when I select "No"/false, and then select a radio button, it resets. I've been completely confused at this problem for days and since I inherited this project, I'm not exactly sure what is wrong or what I need to do.
Here is my code, if anyone could provide some insight
Here is the code relevant to the radio button group from within the redux form:
<div className="page-form__block">
<p> Is there any PPE associated with this work? </p>
<Field
name="ppe"
component={props =>
<PPE
{...props}
/>
}
/>
</div>
And here is the actual component for the RadioButtonGroup:
import React from 'react';
import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton';
// import CheckboxList from '../../components/CheckboxList';
import Checkbox from 'material-ui/Checkbox';
import { find, findIndex } from 'lodash';
const safetyList = [
{ _id: '1',
details: 'Hard Hats' },
{ _id: '2',
details: 'Boots' },
{ _id: '3',
details: 'Long Sleeves' },
{ _id: '4',
details: 'Safety Googles' },
{ _id: '5',
details: 'Steel Toe Shoes' },
{ _id: '6',
details: 'Gloves' },
{ _id: '7',
details: 'Dust Masks' },
{ _id: '8',
details: 'High Vis Reflective Vests' },
{ _id: '9',
details: 'Harness' },
{ _id: '10',
details: 'Face Shield' },
{ _id: '11',
details: 'Hearing Protection' },
{ _id: '12',
details: 'Jeans/Long Pants' },
];
class Ppeinput extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
open: false,
list: [],
};
}
componentWillMount() {
if (this.props.input.value.list) {
this.setState({ list: this.props.input.value.list });
}
}
toggle(event) {
let open = event.target.value;
if (open === 'true') {
this.props.input.onChange({
open: true,
list: this.state.list,
});
} else {
this.props.input.onChange({
open: false,
list: [],
});
}
}
onCheck(event, isInputChecked) {
let initialArray = this.state.list;
if (isInputChecked) {
initialArray = [...initialArray, find(safetyList, { _id: event.target.value })];
} else {
initialArray.splice(findIndex(initialArray, { _id: event.target.value }), 1);
}
this.setState({ list: initialArray });
// console.log(initialArray);
this.props.input.onChange({
open: true,
list: initialArray,
});
}
render() {
const isOpen = this.props.input.value.open; // Get state of selected input
const { meta } = this.props;
return (
<div className="page-form__block">
<RadioButtonGroup name="ppe_input" defaultSelected={isOpen} onChange={::this.toggle}>
<RadioButton value={true} label="Yes" />
<RadioButton value={false} label="No" />
</RadioButtonGroup>
{meta.touched && meta.error && <div className="form-error">{meta.error}</div>}
{ isOpen ? (<div className="ppe_field">
<u> Select the PPE </u>
<ul>
{safetyList.map((item) => {
return find(this.props.input.value.list, { _id: item._id}) ? (
<li key={item._id}>
<Checkbox
label={item.details}
value={item._id}
onCheck={this.onCheck.bind(this)}
defaultChecked={true}
/>
</li>
) : (
<li key={item._id}>
<Checkbox
label={item.details}
value={item._id}
onCheck={this.onCheck.bind(this)}
/>
</li>
)
})}
</ul>
</div>) : (<div></div>) }
</div>
);
}
}
export default Ppeinput;
Redux is still a weird concept to grasp for me, so if anyone could provide insight, that'd be greatly appreciated!
So for whatever reason, my version of React/Redux in this particular instance does not like the raw false value. It likes "false". So basically, for my component, I changed out any instance of true/false with "true"/"false" and now everything works fine. I've actually run into this issue before inside of React, and I still have no idea why this happens. But either way, this is the solution I've found. Cheers!