I have a checkbox input:
import { Checkbox } from 'semantic-ui-react';
<Checkbox
checked={false}
ref={id}
/>
Now I would like to write a function that set this checkbox's checked to true (the onClick function goes on another React element, not the checkbox itself):
onClick: (id) => {
//Find the correct checkbox, set the prop
this.refs[id].checked = true;
}
But I have no idea how to do it (the above code does nothing). How do I find react components based on a certain prop?
Maintain a state object that has mapping of id to checkbox state and then onClick based on the id change the state
this.state = {
checked: {'12': true. '23':false}
}
<Checkbox
checked={this.state.checked[id]}
/>
If you want to toggle
onClick = (id) => {
var checked = {...this.state.checked}
checked[id] = !this.state.checked[id];
this.setState({checked})
}
If you only want to set
onClick = (id) => {
var checked = {...this.state.checked}
checked[id] = true;
this.setState({checked})
}
You have to add an onClick attribute in the Checkbox and the funciton name.
Inside the on click function you should get as parameter the event
and check the evet.target.checked
which is the checkbox's attribute to show clicked status.
You don't need to use refs if its all in the same component.
Let me know if you have trouble
You could do something like:
<Checkbox
checked={false}
ref={id}
onClick={() => { this.onClick(id); }}
/>
Not sure if this Checkbox is rendered in the same component tho, so the reference to this might be wrong.
onClick: (id) => {
this.refs[id].checked = true;
}
Related
In the checkbox the default value is null and I am setting it as true when required
but also I thought of one more condition that needs to be set when the checkbox is already selected I want to unselect it and set the value as false instead of null.
Assume alwaysSelected -if this is selected it is true(onload) based on this condition i should update the state
this.state = {
checkbox: null,
}
this.props.alwaysSelected=true
<Checkbox
onChange={this.ChangeValue}
/>
ChangeValue= (event) => {
this.setState(checboxState=> ({
checkbox: checboxState.checkbox ? null : true
});
})
Just say prevState.checkbox -true on a load of the page then it just gives null but need to set it as false
Option tried is setState callback and componentDidUpdate but failed to acheive.
can we do this in another approach??
You can pass the checkbox state to the Checkbox component as value and change the event:
ChangeValue = () => this.setState({checkbox:!checkbox});
or if event returns true/false
ChangeValue = event => this.setState({checkbox:!event});
In my application, there is a parent Product page component consists of two child components. The basic structure is like
Parent(ProductPage)
<template>
....
<div><ProductListTable /></div>
<div><EditActionComponent /></div>
....
</template>
In EditActionComponent, one edit button is there. ProductListTable is having products list where on each row click one edit modal will open.
So i want when i click edit button in edit action component then only row click will be enabled in product list table component.
EditActionComponent
methods:{
onEditAction(){
this.editable = true;
this.actionButtonsToShow = false;
this.editTextToshow = true;
this.$emit('editable',this.editable)
}
}
ProductListTable
methods: {
onRowClick() {
if(this.editable) { // i need this boolean value here
// modal open logic
}
}
}
So how to pass boolean value one child component to other child component?
since you're already emitting an event from your EditActionComponent you can get the boolean value by adding event listener for editable
eg: <EditActionComponent v-on:editable="callbackFunction">
in your ProductPage component, you create the callbackFunction(val) method to get the boolean value and store it in your data.
// ProductPage Component
data: () => ({
editable: false
}),
methods: {
callbackFunction(val) {
this.editable = val;
}
}
then you bind the variable to your ProductListTable component (assuming you have the editable props declared).
<ProductListTable :editable="editable" />
I created a drop down menu that returns a selected option through an event handler when the option is clicked.
When I click on the option, I target the innerText of that option via event. It looks like this: event.target.innerText. The selected targets value is then used to fill in an 'input' to show the users selected value. Exactly how you expect a <select> input to work. The targets value is also used for filtering listed components, but that is not what I am worried about here.
When the drop down menu component loads, inside of a componentDidMount() method, the state is updated with a default value so that the drop down menus load with the first option pre-populated (this is so that they are not empty before a user selects an option).
When I click on an option to make a selection, the returned event.target.innerText is of the previous selection. So if option 1 was the default value when the component mounts, and then I select option 2 and console.log the result, the value would be option 1. If I then select another option, option 3, the returned console.log() would be option 2. It's one behind.
In this .gif, you can see that when componentDidMount() fires, it console.log()s the default values of the drop down menu. But when I make a selection, you'll notice the console.log() is only returning the event.target.innerText of the previously selected option.
Here is the component:
class DropDownSelect extends Component {
constructor(props) {
const { inputOptions } = props;
const { option1 } = inputOptions;
super(props);
this.state = {
showOptions: false,
selectionMade: option1
};
}
setShowOptions = () => {
const { showOptions } = this.state;
this.setState(prevState => ({ showOptions: !prevState.showOptions }));
};
setSelectionMade = event => {
const { target } = event;
event.stopPropagation();
this.setShowOptions();
this.setState({ selectionMade: target.innerText });
console.log(this.state.selectionMade);
};
setDefaultSelectionOnLoad = () => {
const { inputOptions } = this.props;
this.setState({ selectionMade: inputOptions.option1 });
};
componentDidMount() {
this.setDefaultSelectionOnLoad();
console.log(this.state.selectionMade);
}
render() {
const { showOptions, selectionMade } = this.state;
const { inputOptions } = this.props;
const inputOptionsArray = Object.keys(inputOptions);
return (
<DropDownSelectMenu>
<DropDownSelectPlaceholder onClick={this.setShowOptions}>
<p>{selectionMade}</p>
<i>
<FontAwesomeIcon icon={faCaretDown} />
</i>
</DropDownSelectPlaceholder>
{showOptions ? (
<DropDownSelectOptions>
{inputOptionsArray.map((key, index) => {
return (
<DropDownOption
onClick={event => {
this.setSelectionMade(event);
}}
key={index}
>
{inputOptions[key]}
</DropDownOption>
);
})}
</DropDownSelectOptions>
) : null}
</DropDownSelectMenu>
);
}
}
The DropDownOption styled component is where the function that updates the selection in the state is added as an onClick handler. Since this component is a child, and you need to click the parent component to open the DropDownOption component, I thought that maybe the event handler was bubbling up and grabbing the event.target value from the parent, so I added event.stopPropagation() to the event handler function setSelectionMade(). This didn't do anything for me.
Your code works fine, only this debugging method fails ;)
This is of the most common errors in react - expecting state update immediatelly just after setState call.
Read docs, please. Value can be read in setState callback.
You can simply console.log(selectionMade) in render (before return () to get current value.
I'm new to react, I'm curious how to do this properly.
suppose I have this form, by clicking button, I want to get textbox value,
var form = React.createClass({
submit : function(e){
//how to get textbox value?
},
render : function(){
return (
<form>
<input type="text" id="textbox" value="hey, get me"/>
<button onClick={this.submit}>Get it</button>
</form>
);
}
});
Any answer will be appreciated! thank you!
React enforces parent-to-child unidirectional data flow.
So, there's no simple way to access data from siblings.
But, if a child changes the state across the component, you probably want a state for keeping a track of that.
Sample code:
var FormBox = React.createClass({
getInitialState: function () {
return {
textBox: 'hey, get me!'
}
},
pressButton: function () {
alert(this.state.textBox)
},
textChange: function (e) {
this.setState({
textBox: e.target.value
})
},
render: function () {
return (
<form action='.'>
<input type='text' placeholder={this.state.textBox} onChange={this.textChange}/>
<button onClick={this.pressButton}> Get it </button>
</form>
)
}
})
ReactDOM.render(<FormBox />, document.getElementById('root'))
JSBin demo: https://jsbin.com/koxujuwope/edit?js,output
Also, just a suggestion... You should move to ES2015
One way to accomplish this is using refs.
After building your component, you may find yourself wanting to "reach
out" and invoke methods on component instances returned from render(). link to refs docs
Refs are basically the html elements / react instances you want to access. In this case, we want to get Input html element. We get input element by this.inputValue. Then read its value by usual js rule.
var form = React.createClass({
submit : function(e){
e.preventDefault();
console.log(this.inputValue.value);
},
render : function(){
return (
<form onSubmit={this.submit}>
<input type="text" id="textbox" defaultValue="hey, get me"
ref={ function(node){ this.inputValue = node }.bind(this) }
/>
<button onClick={this.submit}>Get it</button>
</form>
);
}
});
here is a jsfiddle for your example, you can check the console for the input value.
Another way to accomplish the same thing is to make your input a controlled element. That means you assign input's value attribute to this.state.inputValue and you pass a onChange event handler as onChange={yourInputHandlerFunction}.
See the answer which explains this way of accomplishing the same thing.
The following code helps me to setup communication between two siblings. The setup is done in their parent during render() and componentDidMount() calls.
It is based on https://reactjs.org/docs/refs-and-the-dom.html
class App extends React.Component<IAppProps, IAppState> {
private _navigationPanel: NavigationPanel;
private _mapPanel: MapPanel;
constructor() {
super();
this.state = {};
}
// `componentDidMount()` is called by ReactJS after `render()`
componentDidMount() {
// Pass _mapPanel to _navigationPanel
// It will allow _navigationPanel to call _mapPanel directly
this._navigationPanel.setMapPanel(this._mapPanel);
}
render() {
return (
<div id="appDiv" style={divStyle}>
// `ref=` helps to get reference to a child during rendering
<NavigationPanel ref={(child) => { this._navigationPanel = child; }} />
<MapPanel ref={(child) => { this._mapPanel = child; }} />
</div>
);
}
}
I have a button with an onClick event that sends a value to my state and should remove it from the state on a second click:
<button
type="button"
value={posts.index}
onClick={this.props.data ? this.props.remove : this.props.add}
key={cont._id}
data={-1}
>
My problem is that I dunno how to set the data attribute to 1 after the first click, so the second click would fire the remove function. How do I achieve that?
action creator
export function add(e) {
return{
type: ADD,
payload: e.target.value
}
}
Set the value before the return.
render() {
const buttonAction = this.props.data ? this.props.remove : this.props.add
return (
<button
type="button"
value={posts.index}
onClick={buttonAction}
key={cont._id}
data={this.props.data}>
)
}
I'm assuming the data attribute in prop contains the value you want the data attribute to contain.
First, ensure that in the parent component, data is defined as a state property, so that it can be manipulated to affect both the parent and the button.
Next, define the add() and remove() functions to look like:
add() {
this.setState({data: this.state.data + 1});
}
remove() {
this.setState({data: this.state.data - 1});
}
And of course, the constructor bind to this scope (still on the parent)
constructor(props, context) {
this.add = this.add.bind(this)
this.remove = this.remove.bind(this)
}
With these done, you can then define your button as:
<button
type="button"
value={posts.index}
onClick={this.props.data ? this.props.remove : this.props.add}
key={cont._id}
data={this.props.data} >
React strongest belief is that changes in the DOM be triggered by data. With this setup, anytime you make any change to the parent data attribute by calling the add() or remove() callback, the button is re-rendered to reflect the new value of data.