How to get an alert message when changing the options in react? - javascript

I am having an ADD button which allows me to add some objects to the option that I selected in the dropdown. And I also have a function attached to that Add Button.
onAddClicked = () =>{
this.setState({
showOptions: true
});
}
<button type="button" onClick={this.onAddClick}
style={{ float: "right", marginLeft: "10px", marginRight: "10px" }}
id="AddSelectedTag"
className={((this.state.selectedOptions ?this.state.selectedOptions.length === 0 : true) ?
"re-btn-primary-inactive" : "re-btn-primary-blue")}disabled={(this.state.selectedOptions ?
this.state.selectedOptions.length === 0 : true) ? true : false}>Add
</button>
I can select and option and few objects under it. Now I need to display an error message when I want to change my option after selecting few objects under that. I am having state for my selected options as "this.state.selectedOptions".
I am trying
if(this.state.selectedOptions ? this.state.selectedOptions.value : null)
{
alert("selectedOptions value has changed");
}
But this is returning an alert message everytime I click on the Add button, not when I try to change the state.
onViewAllTagClick = (event) => {
this.setState({
showTagsSysController: true,
selectedOptions: event,
});
}
<li id="viewAllTags" className="re-exp-pak-edit-system-li">
<div className="re-lbl-normal-12">
<Select id="selectTags"
styles={ddlUtils.getSnapDdlStyle(200)}
placeholder="Select Tag, Network or Hardware "
options={[{label:"Tag",value:2,isChild:0},
{label:"Network",value:5,isChild:0},
label:"Hardware",value:3,isChild:0},
]}
value = { this.state.selectedOptions}
isSearchable={false}
isDisabled={this.state.isEdit === true}
noOptionsMessage={() => null}
onChange = {this.state.selectedSystems !== null ? this.onViewAllTagClick : null}>
</Select>

Add an event listener like componentDidUpdate and compare props
componentDidUpdate(prevProps) {
if(this.props.selectedOptions !== prevProps.selectedOptions)
alert("selectedOptions value has changed");
}

Related

React-Table, disable all checkboxes after checking first 5 checkboxes?

Using Indeterminate Checkboxes.I need to disable all the checkboxes dynamically when the threshold of selected checkboxes reaches to 5(any of the five in table).
function IndeterminateCheckbox({
indeterminate,
className = "",
setActionsVisible,
...rest
}: { indeterminate?: boolean } & HTMLProps<HTMLInputElement>) {
const ref = React.useRef<HTMLInputElement>(null!);
React.useEffect(() => {
if (typeof indeterminate === "boolean") {
setActionsVisible(indeterminate)
ref.current.indeterminate = !rest.checked && indeterminate;
}
}, [ref, indeterminate]);
return (
<input
type="checkbox"
ref={ref}
className={className + " cursor-pointer"}
{...rest}
/>
);
}
And the code/logic for column cell is,
cell: ({ row, getValue }) => {
return (
<div className="custom-checkbox">
<IndeterminateCheckbox
disabled={
row.getAllCells()[5].getValue() === "Cancelled"
}
{...{
checked:
row.getIsSelected() &&
row.getAllCells()[5].getValue() !== "Cancelled" &&
row.getAllCells()[5].getValue() !== "Completed" &&
row.getAllCells()[5].getValue() !== "Failed",
indeterminate: row.getIsSomeSelected(),
setActionsVisible: setActionsVisible,
onChange: row.getToggleSelectedHandler(),
className: "custom-control-input",
}}
/>
</div>
);
},
footer: (props) => props.column.id,
Can anybody suggest me where i am going wrong.? Thanks in Advance.
I am able to disable checkboxes on initial condition(eg. disabling all the checkboxes whose status is "Completed"). ButI need to disable all the checkboxes dynamically when the threshold of selected checkboxes reaches to 5.

button onClick firing twice

#State() open: boolean = false;
...
...
private toggleSelect(source: string) {
console.log('fired ' + source);
this.open = !this.open;
console.log('toggleSelect: Open is now ' + this.open);
this.toggle.emit({ visible: this.open });
}
private handleSelect(value: string | undefined) {
this.value = value;
console.log('EMITTING ' + this.value);
this.changeValue.emit(this.value);
}
render() {
return (
<Host>
<button
class={`select ${this.open ? 'icon-open' : 'icon-closed'} ${
this.open ? 'select-open' : 'select-closed'
}`}
onClick={() => this.toggleSelect('button')}
>
<a> {this.getClosedDisplayValue(this.value)} </a>
<div class={`select-panel ${this.open ? 'open' : 'close'}`}>
{[{ value: 'undefined', name: '' }, ...this.data].map((item) => {
{
return (
<label class="checkmark" htmlFor={item.value}>
{this.getDisplayValue(item.value)}
<input
id={item.value}
title={this.getDisplayValue(item.value)}
name="select"
type="radio"
value={item.value}
onInput={(event) =>
this.handleSelect((event.target as HTMLInputElement).value)
}
/>
</label>
);
}
})}
</div>
</button>
<div
class={`overlay ${this.open ? 'open' : 'close'}`}
role="button"
onClick={() => this.toggleSelect('overlay')}
></div>
</Host>
);
}
}
I have the following code and what happens is when I open the drop down and select an item - I get this in the logs
*/opening the drop down
select.entry.js:39 fired button
select.entry.js:39 toggleSelect: Open is now true
*/selecting an option notice the double click event
select.entry.js:37 fired button
select.entry.js:39 toggleSelect: Open is now false
select.entry.js:37 fired button
select.entry.js:39 toggleSelect: Open is now true
select.entry.js:44 handling select was: true now is **FALSE**
is there a way to prevent this from being called twice or is because I have a input radio tag inside the button tag
I would ideally not want to have to hard code a this.open =false on the handle select method
This is a feature of React strict mode. React helps you detect side effects by running some functions twice. take a look: Why is console.log logging twice in react js?

How to call validation of Textbox on value change of other component in React.js?

Want to call validation of Textbox from value change of other custom component which sets value in state.
Handlers:
handleValueChange = (val, elementName) => {
this.setState({
...this.state,
[elementName]: val
});
};
handleSelectOptionTab = tab => {
console.log("tab : ", tab)//tab : {discountType: "Amount"}
this.setState({ ...this.state, ...tab });
};
Input components:
<Textbox
tabIndex="1"
name="discount"
id={"discount"}
type="number"
value={_.toString(this.state.discount)}
placeholder="Enter discount"
onChange={val => this.handleValueChange(val, "discount")}
onBlur={() => {}}
validate={this.state.validate}
validationCallback={res => {
this.setState({
...this.state,
hasDiscountError: res
});
}}
validationOption={
this.state.discountType === "Percent"
? {
name: "discount",
required: true,
reg: /regext-for-percent/,
regMsg:"validation msg 1"
}
: {
name: "discount",
required: true,
reg: /regex-for-amount/,
regMsg: "Validation msg 2"
}
}
/>
//Options: "Amount", "Percent"
//This is selectable optional buttons where user can choose anyone among multiple options (discountType: "Amount" or discountType: "Percent")
<OptionalButton
selection={this.state}
identifier={"discountType"}
tabIndex="2"
onSelect={tab => this.handleSelectOptionTab(tab)}
options={DISCOUNT_TYPES}
/>
Validation of Textbox is working fine on value change and focused out from Textbox but if value is already present and this.state.discountType is change from OptionalButton in that case validation is not working.
Example: Textbox value is 10000 with Type selected as "Amount" which is valid but as Type is changed to "Percent" then Textbox should show validation error.
You should also update this.state.validate after changing the tab. The issue is that the textbox is unaware that the tab change needs a revalidation, so you need to tell it using the this.state.validate value.
Change you handleSelectOptionTab method like this:
handleSelectOptionTab = tab => {
console.log("tab : ", tab)//tab : {discountType: "Amount"}
// try and use a function inside setState, instead of an object
this.setState(oldState => ({ ...oldState, ...tab, validate: true }));
};
and then inside your validationCallback
validationCallback={res => {
this.setState(oldState => ({
...oldState,
hasDiscountError: res,
validate: false // to not trigger another validation again
}));
}}
Maybe option component is change then trigger this.handleValueChange(val, "discount").
You use ref for reach component.
Following code to use ref
For example div element
const refTest = React.createRef<HTMLDivElement>()
And use for component
<div className="App" ref={refTest}>
I don't know which use to component so example is div element.
Then you should trigger "handleValueChange" event for "refTest" component

Using onClick to call the same function works for one thing and not another?

I'm creating an application where a user can search for a device with a search bar, or look through a nested menu. When the user finds the device they want, they click on the green plus to add it to their "bag". For some reason the addDevice function I've written only works for the search function, and not when it's called in the menu. It seems to partially work, but not correctly. Does anyone know what in my code could be causing this? Please see the images below for more details.
I'm also making two different API calls, one for the search bar (called in its own function) and one for the menu (called in componentDidMount). Could this possibly be what's causing the error?
I won't include every line of code because it's a lot, but please let me know if you'd like to see anything else.
class App extends React.Component {
state = {
devices: [],
bag: [],
objectKeys: null,
tempKeys: []
};
this is the function that gets called by the onClick's
addDevice = (e, deviceTitle) => {
const array = Array.from(this.state.bag || []);
if (array.indexOf(deviceTitle) === -1) {
array.push(deviceTitle);
} else {
return;
}
localStorage.setItem("list", JSON.stringify(array));
this.setState({
bag: array
});
};
This is the function that doesn't seem to work when addDevice is called
makeMenuLayer = layer => {
const { objectKeys } = this.state;
if (layer == null) {
return null;
}
const layerKeys = Object.entries(layer).map(([key, value]) => {
{/*If value has children, display an arrow, if not, do nothing*/}
var arrow = Object.keys(value).length ? (
<i
className="fas fa-angle-right"
style={{ cursor: "pointer", color: "gray" }}
/>
) : (
""
);
{/*If value has no children, display an plus sign, if not, do nothing*/}
var plus =
Object.keys(value).length === 0 ? (
<i
className="fas fa-plus"
style={{ cursor: "pointer", color: "green" }}
onClick={e => this.addDevice(e, this.value)}
/>
) : (
""
);
return (
<ul key={key}>
<div onClick={() => this.handleShowMore(key)}>
{key} {arrow} {plus}
</div>
{objectKeys[key] && this.makeMenuLayer(value)}
</ul>
);
});
return <div>{layerKeys}</div>;
};
this is where the addDevice that does work gets called
render () {
return(
<div className="search-results">
{(this.state.devices || []).map(device => (
<a key={device.title}>
<li>
{device.title}{" "}
<i
className="fas fa-plus plus input"
style={{ cursor: "pointer", color: "green" }}
onClick={e => this.addDevice(e, device.title)}
/>
</li>
</a>
))}
</div>
)}
This is what it looks like when devices are added from the search (works fine)
This is what happens when I try to add "Necktie" from the menu. It doesn't let me add anything else after that
In this line onClick={e => this.addDevice(e, this.value)}
The value of this points to the class itself. Thus, this.value is undefined, It's not not allowing you to add anything more because undefined is already in the array and undefined === undefined is actually true.
To fix this, you need to pass the correct value of the device title.

Switching between buttons

How can i make dynamic switching between buttons? For example if one button is active, then the rest is not active. For example:
constructor(props) {
super(props)
this.state = {
active: false,
notactive: false
}
}
checkActive = () => {
this.setState({
active: true,
notactive: false
})
};
checkNotactive = () => {
this.setState({
active: false,
notactive: true
})
};
But i want make it dynamic.
I mean that when I have, for example, 10 buttons, I will not set each state apart. If I add another button, it will work. Just like the radio button.
Instead of a boolean you could use an index to mark the active button.
Eg:
this.state = {
activeButtonIndex: null
}
then when creating your buttons using a loop you can check
if (index === this.state.activeButtonIndex) { do something }
You would need to have a type property based on your buttons. If for example you need to make 3 buttons daily, weekly, monthly then you can have something like this.
return (
<div style={style.buttonContainer}>
<div className={this.props.active === "daily" ? "activeButton" : ""}>
<Button color="primary" onClick={this.handleClick("daily")}>
Daily
</Button>
</div>
<div className={this.props.active === "weekly" ? "activeButton" : ""}>
<Button color="primary" onClick={this.handleClick("weekly")}>
Weekly
</Button>
</div>
<div className={this.props.active === "monthly" ? "activeButton" : ""}>
<Button color="primary" onClick={this.handleClick("monthly")}>
Monthly
</Button>
</div>
</div>
);
I have a property on parent's state active and based on that I will switch dynamically.

Categories

Resources