i m learning react and i trying to change my button text after sweetAlert2-react popup.
The original text on the button is 'ACTIVE' and
If i choose OK on the popup the text on the button must be 'activated' and if y choose CANCEL 'disabled'..
I do not know how or where to do the IF iteration
any help?
here is my code:
<button onClick={() => this.setState({ show: true })}>ACTIVE</button> <SweetAlert show={this.state.show} showCancelButton={this.state.show} title="Are you shore?" onConfirm={() => this.setState({ show: false })} />
Thanks!
Conditionally set the string internal to the button.
<button>
{this.state.active === 'active' && <div>ok</div>}
{this.state.active === 'disabled' && <div>idk</div>}
<button>
If there are only two states consider a ternary operator.
<button>
{this.state.active === 'active' ? <div>ok</div> : <div>idk</div>}
<button>
You could save the button's text in the state, (ex: this.state.buttonText), then you'll be able to set the buttonText when user click on OK/Cancel button.
You can use a common method (in the below example hideAlert) for manage both events (ok and cancel) and inside it, set the button's text.
See the following example please (click here to run):
import React, { Component } from "react";
import SweetAlert from "react-bootstrap-sweetalert";
import ReactDOM from "react-dom";
export default class HelloWorld extends Component {
constructor(props) {
super(props);
this.state = {
alert: null,
button: "active"
};
}
showAlert() {
const getAlert = () => (
<SweetAlert
show={this.state.show}
showCancel
onConfirm={() => this.hideAlert("disabled")}
onCancel={() => this.hideAlert("active")}
>
Are you sure?
</SweetAlert>
);
this.setState({
alert: getAlert()
});
}
hideAlert(text) {
this.setState({
alert: null,
button: text
});
}
render() {
return (
<div style={{ padding: "20px" }}>
<button onClick={() => this.showAlert()}>
{this.state.button}
</button>
{this.state.alert}
</div>
);
}
}
ReactDOM.render(<HelloWorld />, document.getElementById("app"));
I hope it helps you, bye.
Related
I have two component: 1:StudentList 2: Major in react and antd.
StudentList Component rendered a list of students.
Major Component made a list of majors that you can pick them. After selecting major, the selected major title display on the top of the students list. and the list will be filtered according to the selected major.
This is StudentList component contain Major component:
class StudentList extends Component {
render(){
return(
<>
<Major/>
<h5>20 student found in <a>selected major</a></h5>
<List>
//this is the list of students and is not related to this question
</List>
</>);
}
}
This is Major Component with a filter button to open the popover:
class Major extends Component {
render() {
return (
<Popover
trigger="click"
content={content} //list of majors
>
<Button>
<FilterOutlined /> Select major to filter
</Button>
</Popover>
);
}
}
When I click on the Select major to filter button, the popover open to select majors. I want to change the code in order to open this popover from two place:
1- click on Select major to filter button in the Major component
2- click on selected major in the title in StudentList component.
Notice: I want to open the same popover in the same place (similar to when I click on Select major to filter button)
Maybe it could handle with state and handleVisibleChange function. but I don't know how to handle it from 2 components. I glad to hearing your solutions.
You can use the visible and onVisibleChange property from Antd's tooltip because they are used by the PopOver as well. You can find an easy example from Andt how to control a PopOver by visible in the docs.
To get the button click you can use onClick from antd's Button Api.
The desired example using React Components:
class Major extends Component {
componentDidUpdate(prevProps) {
// Typical usage (don't forget to compare props):
if (this.props.value !== prevProps.value) {
this.setState({ visible: this.props.value });
}
}
state = {
visible: false
};
hide = () => {
this.setState({
visible: false
});
};
handleVisibleChange = visible => {
this.setState({ visible });
// this.props.onChange(visible); // add me to open popover on every click on studenlist
};
render() {
return (
<Popover
trigger="click"
content={<a onClick={this.hide}>Close</a>}
visible={this.state.visible}
onVisibleChange={this.handleVisibleChange}
>
<Button>Select major to filter</Button>
</Popover>
);
}
}
class StudentList extends Component {
state = {
visible: false
};
onClick = () => {
this.setState({ visible: !this.state.visible });
};
render() {
return (
<>
{/* <Major value={this.state.visible} onChange={setVisible} /> */}
<Major value={this.state.visible} />
<h5>
20 student found in <a>selected major</a>
</h5>
<Button onClick={this.onClick}>Select major from Studenlist</Button>
</>
);
}
}
Component example as a CodeSandBox.
Here is a simple example for your request using react hooks and simple buttons to open the PopOver:
function Major({ value, onChange }) {
const [visible, setVisible] = useState(value);
useEffect(() => {
value && setVisible(value);
}, [value]);
const hide = () => setVisible(false);
const handleVisibleChange = visible => {
setVisible(visible);
onChange(visible);
};
return (
<Popover
trigger="click"
content={<a onClick={hide}>Close</a>}
visible={visible}
onVisibleChange={handleVisibleChange}
>
<Button>Select major to filter</Button>
</Popover>
);
}
function StudentList() {
const [visible, setVisible] = useState(false);
const onClick = () => {
setVisible(true);
};
return (
<>
<Major value={visible} onChange={setVisible} />
<h5>
20 student found in <a>selected major</a>
</h5>
<Button onClick={onClick}>Select major from Studenlist</Button>
</>
);
}
The depended working CodeSandBox.
Edit1: Added React Component example.
In my react.js project I have parent and child components (Page like parent and Modal with input like child). I receive data in parent by ajax request and pass it for input from parent to child and fill the child state with it. Also in child component I have 2 buttons: Submit and Cancel. Conside the following code:
**Parent**
render() {
const { projectAux } = this.props;
return (
<ProjectNameFormModal
projectAux={projectAux}
onVisibleChange={e => this.onVisibleProjectNameFormModalChange(e)}
visible={this.state.editProjectNameModalVisible}
/>
)
}
**Child**
import React from 'react';
import {Button, Checkbox, Form, Input, List, Modal, Select} from "antd";
class ProjectNameFormModal extends React.Component{
constructor(props){
super(props);
this.state = {
projectAux: props.projectAux,
visible: props.visible
}
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
if(this.state.projectAux != nextProps.projectAux){
this.setState({
projectAux: nextProps.projectAux,
visible: nextProps.visible
});
}
return true;
}
handleProjectNameInputChange = e => {
let current_state = this.state;
current_state.projectAux[e.target.name] = e.target.value;
this.setState(current_state);
}
handleCancelSubmitProjectNameUpdate = e => {
this.props.onVisibleChange(false);
}
handleSubmitProjectNameUpdate = e => {
console.log(' in handleSubmitProjectNameUpdate');
this.setState({...this.state, visible: false});
this.props.onVisibleChange(false);
}
render() {
return (
<Modal
title='Edit project Name'
visible={this.props.visible}
bodyStyle={{}}//height:"800px"
onSave={{}}
maskClosable={false}
onCancel={this.handleCancelSubmitProjectNameUpdate}
footer={[
<Button key="back" onClick={this.handleCancelSubmitProjectNameUpdate}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.handleSubmitProjectNameUpdate}>
Save
</Button>,
]}
>
<div>
<Input placeholder="ProjectName"
name="name"
onChange={this.handleProjectNameInputChange}
value={this.state.projectAux && (this.state.projectAux.name)}
/>
</div>
</Modal>
);
}
}
export default ProjectNameFormModal;
So the problem is when I enter some new data to input and then press Cancel button, I have also my Parent state updated to the new data which I definetely dont want to happen. When Cancel is pressed, no updates to the parent state should occur but it happens. Btw, parent state does not update when I enter new symbols into input. I tried to use spread operator as it is said here but it did not work.
Any ideas how to fix it would be welcome, thank you.
I have a button that changes the active state onClick:
render() {
return(
<SomeButton
onClick={e => this.handleClick(e)}
id={someId}
activeStatus={someId === this.state.active ? "active" : "not active"}
/>
)
}
The function that changes the state:
handleClick(e) {
e.preventDefault();
this.setState({ active: e.currentTarget.id });
}
The state:
this.state = {
active: null
};
The button that receives the activeStatus props:
export default function SomeButton({ activeStatus }) {
console.log(activeStatus);
return (
// button jsx code
);
}
However, every time I click on the button (I have 3 instances of that button on the page), the activeStatus console.log shows:
I click on button 1:
active
not active
not active
I click on button 2:
active
active
not active
I click on button 3:
active
active
active
I was expecting that the status would toggle depending on the active button which is clicked.
What am I missing?
You can set the state in an array:
this.state = {
active: [false, false, false] // or just: []
};
handleClick(e) {
e.preventDefault();
const activeState = [false, false, false]; // or just: []
activeState[e.currentTarget.index] = true;
// button index ^^
this.setState({ active: activeState });
}
And just pass the activeStatus to the active state:
activeStatus={this.state.active}
Inside your component, bind the active state:
<button className={ activeStatus[0] ? 'active' : 'not-active' }>...</button>
<button className={ activeStatus[1] ? 'active' : 'not-active' }>...</button>
<button className={ activeStatus[2] ? 'active' : 'not-active' }>...</button>
I'd use e.target.id instead of e.currentTarget.id and if the button ids are static, then you could put them into your state and use the id to update a buttonState object (one of several ways to handle it).
Working example: https://codesandbox.io/s/olmn9k08m5
Some notes:
Keep your state consistent (if it's a string, keep it a string, if
it's an array, keep it any array...etc -- in the example below
buttonState is an object and stays an object).
Also, you don't need e.preventDefault() unless you're submitting a
form or trying to block functionality.
Always specify the button's type ("button" or "submit")
ShowButton.js
import React, { Component } from "react";
import SomeButton from "./SomeButton";
const buttons = ["button1", "button2", "button3"];
export default class App extends Component {
state = {
buttonState: {
button1: "inactive",
button2: "inactive",
button3: "inactive"
}
};
handleClick = e => {
const { id } = e.target; // id="button1","button2" or "button3"
this.setState(prevState => ({
buttonState: {
...prevState.buttonState, // spread out object
[id]: prevState.buttonState[id] === "active" ? "inactive" : "active" // use the [id] as an object property (ex: "button1") and set the property's value to "active" or "inactive"
}
}));
};
render = () => (
<div className="container">
<h1>Controlling Active Buttons</h1>
{buttons.map(id => (
<SomeButton
key={id}
id={id}
handleClick={this.handleClick}
activeStatus={this.state.buttonState[id]}
/>
))}
</div>
);
}
SomeButton.js
import React from "react";
export default ({ activeStatus, handleClick, id }) => (
<div style={{ marginBottom: 20 }}>
<button
type="button"
style={{ minWidth: 150 }}
className={`uk-button ${
activeStatus === "active" ? "uk-button-primary" : null
}`}
id={id}
onClick={handleClick}
>
{activeStatus}
</button>
</div>
);
Hi I am playing around with ReactJS, and found this awesome Modal Component to open Videoes in a Modal, but when I put the Modal inside a loop with multiple links and open the modal, it open like 5 times if I have 5 links. What do I do wrong?
Modal Component: https://github.com/appleple/react-modal-video
import React from 'react'
import ReactDOM from 'react-dom'enter code here
import ModalVideo from 'react-modal-video'
class App extends React.Component {
constructor () {
super()
this.state = {
isOpen: false
}
this.openModal = this.openModal.bind(this)
}
openModal () {
this.setState({isOpen: true})
}
render () {
return (
<div>
<ModalVideo channel='youtube' isOpen={this.state.isOpen} videoId='L61p2uyiMSo' />
<button onClick={this.openModal}>Open</button>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
My Loop with the Modal Component Inside:
render(){
return(
<div>
{(this.props.frag.all == null) ? null :
this.props.frag.all.map((frags, i) => {
return (
<li key={frags.id} className="group" id="" style={{width: 'calc(13% - 30px)'}}>
<ModalVideo channel='youtube' isOpen={this.state.isOpen} videoId='{frags.url}' />
<button onClick= {this.openModal.bind(this)}>Open</button>
</li>
)})
}
</div>
The problem is that each ModalComponent uses the same state property isOpen so when you click on any link it sets this property and each ModalComponent becomes open. You should use unique property for each modal (you can use poperty which you already uses as key).
<li key={frags.id} className="group" id="" style={{width: 'calc(13% - 30px)'}}>
<ModalVideo channel='youtube' isOpen={this.state.isOpen[frags.id]} videoId='{frags.url}' />
<button onClick= {this.openModal.bind(this, frags.id)}>Open</button>
</li>
And your method:
openModal (id) {
this.setState({
isOpen: {
[id]: true
}
});
}
Reason is, you are using single state variable to maintain open/close status of modal, it will work properly for one, but in case of multiple modals, you have to use multiple state values to maintain the statuses, Use this:
Define isOpen as an array in state:
this.state= {
isOpen=[],
}
Use this method to change the status of any particular modal:
openModal(index){
let isOpen = this.state.isOpen.slice();
isOpen[index] = true;
this.setState({isOpen});
}
Bind the index of each modal in onClick method:
render(){
return(
<div>
{(this.props.frag.all == null) ? null :
this.props.frag.all.map((frags, i) => {
return (
<li key={frags.id} className="group" id="" style={{width: 'calc(13% - 30px)'}}>
<ModalVideo channel='youtube' isOpen={this.state.isOpen[i] || false} videoId='{frags.url}' />
<button onClick= {this.openModal.bind(this,i)}>Open</button>
</li>
)})
}
</div>
)
}
Modals in a loop are a bit complicated because they need a unique key for each row. Making the modal work without duplicating it is another challenge. The first mistake many of us make is including the modal within the loop. To prevent the duplication of the modal we need to make it fully dynamically. I have included a full example without having to duplicate the modal inside of the loop. I hope that helps
here is a full example
import React, { Component } from 'react';
import { Button, Alert, Input, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
class History extends Component
{
constructor(props)
{
super(props);
this.state = {
userHistory: [{'id': 1, 'test': 'this is a test'}, {'id': 2, 'test': 'this is a test2'}, {'id': 3, 'test': 'this is a test3'}],
showLog: false,
logID: null
}
}
render()
{
const history = this.state.userHistory.map( (ticket, key) =>
{
return (
<tr key={key}>
<td>{ticket.test}</td>
<td>{ticket.id ? <Button color="info" onClick={() => this.setState({logID: ticket.id, showLog: true})}>View</Button> : ''}</td>
</tr>
)
});
return (
<div className="card-body">
<table class="table table-striped">
<thead>
<tr>
<th>test</th>
<th>modal</th>
</tr>
</thead>
<tbody>
{history}
</tbody>
</table>
<Modal id={this.state.logID} isOpen={this.state.showLog} fade="false" toggle={() => this.setState({showLog: false})}>
<ModalHeader toggle={() => this.setState({showLog: false})}>#jerryurenaa is awesome :D</ModalHeader>
<ModalBody>
<p>Modal Number: {this.state.logID}</p>
</ModalBody>
<ModalFooter>
<Button onClick={() => this.setState({showLog: false})}>Cancel</Button>
</ModalFooter>
</Modal>
</div>
);
}
}
export default History;
I found this perfect Sweet Alert module for Bootstrap and React (which I'm using in my Meteor app):
http://djorg83.github.io/react-bootstrap-sweetalert/
But I don't understand how you include this code inside a React component.
When someone clicks the Delete button in my app, I'd like a Sweet Alert prompt to pop up asking for confirmation.
Here is my component for the Delete button:
import React, {Component} from 'react';
import Goals from '/imports/collections/goals/goals.js'
import SweetAlert from 'react-bootstrap-sweetalert';
export default class DeleteGoalButton extends Component {
deleteThisGoal(){
console.log('Goal deleted!');
// Meteor.call('goals.remove', this.props.goalId);
}
render(){
return(
<div className="inline">
<a onClick={this.deleteThisGoal()} href={`/students/${this.props.studentId}/}`}
className='btn btn-danger'><i className="fa fa-trash" aria-hidden="true"></i> Delete Goal</a>
</div>
)
}
}
And here is the code that I copied from the Sweet Alert example:
<SweetAlert
warning
showCancel
confirmBtnText="Yes, delete it!"
confirmBtnBsStyle="danger"
cancelBtnBsStyle="default"
title="Are you sure?"
onConfirm={this.deleteFile}
onCancel={this.cancelDelete}
>
You will not be able to recover this imaginary file!
</SweetAlert>
Anyone know how to do this?
Working example based on your code http://www.webpackbin.com/VJTK2XgQM
You should use this.setState() and create <SweetAlert ... /> on onClick. You can use fat arrows or .bind() or any other method to be sure that proper context is used.
import React, {Component} from 'react';
import SweetAlert from 'react-bootstrap-sweetalert';
export default class HelloWorld extends Component {
constructor(props) {
super(props);
this.state = {
alert: null
};
}
deleteThisGoal() {
const getAlert = () => (
<SweetAlert
success
title="Woot!"
onConfirm={() => this.hideAlert()}
>
Hello world!
</SweetAlert>
);
this.setState({
alert: getAlert()
});
}
hideAlert() {
console.log('Hiding alert...');
this.setState({
alert: null
});
}
render() {
return (
<div style={{ padding: '20px' }}>
<a
onClick={() => this.deleteThisGoal()}
className='btn btn-danger'
>
<i className="fa fa-trash" aria-hidden="true"></i> Delete Goal
</a>
{this.state.alert}
</div>
);
}
}
if it doesn't work for someone the way you exposed the #hinok solution then you can modify this function like this:
deleteThisGoal() {
this.setState({
alert: ( <
SweetAlert success title = "Woot!"
onConfirm = {
() => this.hideAlert()
} >
Hello world!
<
/SweetAlert>
)
});
};
This was the code that I wrote:
showAlert(title, message, callBack, style) {
this.setState({
alert: (
<SweetAlert
warning
showCancel
confirmBtnText = "Sí"
cancelBtnText = "No"
confirmBtnBsStyle= {style ? style : "warning"}
cancelBtnBsStyle = "default"
customIcon = "thumbs-up.jpg"
title = {title}
onConfirm = {callBack()}
onCancel = {this.hideAlert}
>
{message}
</SweetAlert>
)
});
}
hideAlert = () => {
this.setState({
alert: null
});
}
updateCustomer = () => {..."a few lines of code here"}
This was the called from button:
{<Button color="primary" disabled={this.state.notChange} onClick={() => this.showAlert('Save changes for client', '¿Are you sure?', () => this.updateCustomer, null) } >Save changes</Button>}
Saludos!!