0

I need to call cancelMethod with params from Button onClick inside popover. However I could not access this method. Can you explain is it possible to access. If yes how can I do it?

const popover = (
  <Popover id="popover-basic">
    <Popover.Title as="h3">Cancel reservation</Popover.Title>
    <Popover.Content>
     for <strong>canceling</strong> course. Click here:
     <Button onClick={cancelMethod()} variant='danger'>Cancel</Button>
    </Popover.Content>
  </Popover>
);

const Event = ({event}) => (
  <OverlayTrigger trigger="click" placement="top" overlay={popover}>
    <Button 
     style={{background:"transparent", border:"none"}}
    >{event.title} <br/> Lecture Room:{event.room}<br/> Teacher: {event.instructor}</Button>
  </OverlayTrigger>
);


export default class NewCalendarView extends Component {

  cancelMethod(id){
    alert("Hello"+id);
  }

  componentDidMount() {
    API.getLectures().then((res)=>{
      console.log(res)
       const cal=res.map((lec)=>{
         let lecture= {
           instructor: lec.teacherName,
          room: lec.room,
          title: lec.subject,
          startDate : moment(lec.date+"T"+lec.hour).toDate(),
          endDate:  moment(lec.date+"T"+lec.hour+"-02:00").toDate()
          }   
          return lecture;
      })
          this.setState({events:cal,loading:null,serverErr:null})
    }).catch((err)=>{
        this.setState({serverErr:true,loading:null})
    })
}
  constructor(props) {
    super(props);

    this.state = {
       events: []
    }
  }

  render() {
    return (
      <div style={{
        flex: 1
      }}>
        {console.log(this.state.events)}

        <Calendar
          localizer={localizer}
          events={this.state.events}
          startAccessor='startDate'
          endAccessor='endDate'
          defaultView='week'
          views={['month', 'week', 'day']}
          culture='en'
          components={{
            event: Event
          }}

          />
      </div>
    );
  }
}
Neo
  • 119
  • 2
  • 11

2 Answers2

5

You can define the functions Popover and Event within the class and the call the function with this keyword.

export default class NewCalendarView extends Component {
  cancelMethod(id){
    alert("Hello"+id);
  }

  componentDidMount() {
    API.getLectures().then((res)=>{
      console.log(res)
       const cal=res.map((lec)=>{
         let lecture= {
           instructor: lec.teacherName,
          room: lec.room,
          title: lec.subject,
          startDate : moment(lec.date+"T"+lec.hour).toDate(),
          endDate:  moment(lec.date+"T"+lec.hour+"-02:00").toDate()
          }   
          return lecture;
      })
          this.setState({events:cal,loading:null,serverErr:null})
    }).catch((err)=>{
        this.setState({serverErr:true,loading:null})
    })
}
  constructor(props) {
    super(props);

    this.state = {
       events: []
    }
  }

Popover = (
  <Popover id="popover-basic">
    <Popover.Title as="h3">Cancel reservation</Popover.Title>
    <Popover.Content>
     for <strong>canceling</strong> course. Click here:
     <Button onClick={cancelMethod()} variant='danger'>Cancel</Button>
    </Popover.Content>
  </Popover>
);

Event = ({event}) => (
  <OverlayTrigger trigger="click" placement="top" overlay={this.popover}>           // added the this keyword
    <Button 
     style={{background:"transparent", border:"none"}}
    >{event.title} <br/> Lecture Room:{event.room}<br/> Teacher: {event.instructor}</Button>
  </OverlayTrigger>
);

  render() {
    return (
      <div style={{
        flex: 1
      }}>
        {console.log(this.state.events)}

        <Calendar
          localizer={localizer}
          events={this.state.events}
          startAccessor='startDate'
          endAccessor='endDate'
          defaultView='week'
          views={['month', 'week', 'day']}
          min={new Date(2020, 1, 0, 7, 0, 0)} 
          max={new Date(2022, 1, 0, 21, 0, 0)}
          culture='en'
          components={{
            event: this.Event           // added the this keyword
          }}

          />
      </div>
    );
  }
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
kaceva5618
  • 86
  • 5
1

One way would be to pass it as prop to popover (which I renamed to PopoverInstance as Popover was already taken). This unfortunately has a side effect of having to drill the prop two levels down (instead of direct one level down). An alternative approach would be to introduce outside state (like Context or Redux) that manages state and methods. It would certainly help with prop drilling.

If cancelMethod is only used in this popover, you can consider moving it there as well.

Also I am unsure how Calendar works, so take that into consideration when you look at the example I've set below.

const PropoverInstance = ({cancelMethod}) => (
  <Popover id="popover-basic">
    <Popover.Title as="h3">Cancel reservation</Popover.Title>
    <Popover.Content>
     for <strong>canceling</strong> course. Click here:
     <Button onClick={cancelMethod()} variant='danger'>Cancel</Button>
    </Popover.Content>
  </Popover>
);

const Event = ({event, cancelMethod}) => (
  <OverlayTrigger trigger="click" placement="top" overlay={<PopoverInstance cancelMethod={cancelMethod} />}>
    <Button 
     style={{background:"transparent", border:"none"}}
    >{event.title} <br/> Lecture Room:{event.room}<br/> Teacher: {event.instructor}</Button>
  </OverlayTrigger>
);


export default class NewCalendarView extends Component {

  cancelMethod(id){
    alert("Hello"+id);
  }

  componentDidMount() {
    API.getLectures().then((res)=>{
      console.log(res)
       const cal=res.map((lec)=>{
         let lecture= {
           instructor: lec.teacherName,
          room: lec.room,
          title: lec.subject,
          startDate : moment(lec.date+"T"+lec.hour).toDate(),
          endDate:  moment(lec.date+"T"+lec.hour+"-02:00").toDate()
          }   
          return lecture;
      })
          this.setState({events:cal,loading:null,serverErr:null})
    }).catch((err)=>{
        this.setState({serverErr:true,loading:null})
    })
}
  constructor(props) {
    super(props);

    this.state = {
       events: []
    }
  }

  render() {
    return (
      <div style={{
        flex: 1
      }}>
        {console.log(this.state.events)}

        <Calendar
          localizer={localizer}
          events={this.state.events}
          startAccessor='startDate'
          endAccessor='endDate'
          defaultView='week'
          views={['month', 'week', 'day']}
          culture='en'
          components={{
            event: <Event event={???} cancelMethod={cancelMethod} />
          }}

          />
      </div>
    );
  }
}
Sylvester
  • 116
  • 2
  • 4