0

I am working on React.
I have a method called on_render_cell, where I have created a div and I am inserting image in that div based on some conditions.
This is the approach I am following to insert image in the div.I get the desired images. Now my goal is:
To open a modal when the image is clicked. When I try to assign onClick={this.openModal()}, the modal doesn't pops up. I noticed that this is because this points to the <img>. Can anyone help me how can I call openModal() on click handler of image tag written in result variable of on_render_cell()?

export class ScheduleManager extends SampleBase {
constructor() {
        super(...arguments);
        this.state = {
            visible : false
        }
    }    
openModal() {
            this.setState({
                visible : true
            });


   }


    closeModal() {
        this.setState({
            visible : false
        });
    }
on_render_cell(args) {
let ele = document.createElement('div');
            var sum=0;
            var cursor=Event.find({Teacher:teacherName});
            cursor.forEach(function(event){
              if(convert(event.StartTime)===convert(args.date))
               sum = sum + parseFloat(event.Duration);
             });
              let hoursPerDay = sum/60;
              let percentHours=(hoursPerDay/maxHoursPerDay)*100;
              let result ='';
              if(percentHours===0)
              {
                result='<img id="aaa" ref="abc" className="weather-image" height="25px" width="25px" src="http://www.clker.com/cliparts/h/e/s/t/j/U/grey-circle.svg.thumb.png"  onClick={console.log(this)} />';
              }
              else if(percentHours<=25)
              {
                result = '<img className="weather-image"  src= "http://www.clker.com/cliparts/0/w/P/n/G/3/blue-circle-th.png" />';
              }
              else if(percentHours>25 && percentHours<=50)
              {
                result='<img className="weather-image"  src= "http://www.clker.com/cliparts/o/b/y/x/Z/c/yellow-dot-th.png" />';
              }
              else if(percentHours>50 && percentHours<=75)
              {
                result = '<img className="weather-image"  src= "http://www.clker.com/cliparts/1/A/W/q/h/h/orange-circle-th.png" />';
              }
              else
              {
                result='<img className="weather-image"  src= "http://www.clker.com/cliparts/3/m/Q/u/P/J/red-circle-small-new.svg.thumb.png" />';
              }
              ele.innerHTML = result; 
             (args.element).appendChild(ele.firstChild);
}
render(){
 return (
          <div>
          <input type="button" value="Open" onClick={() => this.openModal()} />
          <Modal 
                    visible={this.state.visible}
                    width="400"
                    height="300"
                    effect="fadeInUp"
                    onClickAway={() => this.closeModal()}
                >
                    <div>
                        <h1>Title</h1>
                        <p>Some Contents</p>
                        <a href="javascript:void(0);" onClick={() => this.closeModal()}>Close</a>
                    </div>
                </Modal>
          <p>Grey circle denotes no classes for the day</p>
          <p>Blue circle denotes less than 25% occupancy for the day</p>
)
}
}

Goal : Open Modal on image click. i.e, access openModal() of component

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
  • What does the method `on_render_cell` is supposed to do ? – nubinub Dec 21 '18 at 14:44
  • I guess the problem is that `on_render_cell` is not using React elements but just native javascript elements. – nubinub Dec 21 '18 at 14:50
  • @nubinub I am using the scheduler(calendar) and on_render_cell is responsible for rendering the cells of scheduler. Like the images of cloud, sun, etc are displayed on each date of month here [https://ej2.syncfusion.com/react/demos/#/material/schedule/date-header-template], I am displaying circles instead of those images and want to open modal when user clicks it. – Pooja Chawla Dec 21 '18 at 15:14
  • And have you tried to wrap it in a react component and put the click handler on [that component](https://ej2.syncfusion.com/react/demos/#/material/schedule/cell-template) ? – nubinub Dec 21 '18 at 15:22
  • No. @nubinub did u see the demo in the link? – Pooja Chawla Dec 21 '18 at 15:36
  • Looking at the source code of the demo, it looks like the cellTemplate is wrapped within a React Element, which should allow you to handle the click properly. – nubinub Dec 21 '18 at 15:38
  • yes exactly. The problem is that when `{this.openModal()` is used in tag, `this` is referring to the image tag, not the React Component. – Pooja Chawla Dec 21 '18 at 15:57

2 Answers2

0

sorry but you are not doing it right. when you write:

onClick={() => this.openModal()}

you are creating a new function each time the element renders. instead, I suggest you to bind the method inside the constructor:

this.openModal = this.openModal.bind(this);

and inside the input write:

onClick={this.openModal}

this way you won't create a new function each time the elements renders, and the openModal this will point to the element itself.

If I understand correctly the problem is in this line:

result='<img id="aaa"... onClick={console.log(this)} />';

have you tried pass JSX instead of a string? bind the function openModal in the constructor, and pass to the img the function this.openModal. I think that if you will pass JSX instead of a string it will work

UPDATE

ok so I took the code from Here and edited it a bit:

export class CellTemplate extends SampleBase {
  getCellContent(date) {
      if (date.getMonth() === 10 && date.getDate() === 23) {
        return ( < div > < img src = "src/schedule/images/thanksgiving-day.svg" / > < div className = "caption" > Thanksgiving day < /div></div > );
      }

      cellTemplate(props) {
          if (props.type === "monthCells") {
            return ( < div className = "templatewrap" > {
                this.getCellContent(props.date)
              } > < /div>);
            }
            return;
          }
          render() {
            return ( < div className = 'schedule-control-section' >
              <
              div className = 'col-lg-12 control-section' >
              <
              div className = 'control-wrapper' >
              <
              ScheduleComponent cssClass = 'cell-template'
              width = '100%'
              height = '650px'
              selectedDate = {
                new Date(2017, 11, 15)
              }
              cellTemplate = {
                this.cellTemplate.bind(this)
              } >
              <
              ViewsDirective >
              <
              ViewDirective option = 'Month' / >
              <
              /ViewsDirective> <
              Inject services = {
                [Month, Resize, DragAndDrop]
              }
              /> <
              /ScheduleComponent> <
              /div> <
              /div> <
              /div>);
            }
          }

in cellTemplate you can see how to call getCellContent correct, and in getCellContent you can see how I would have return JSX.

Gilli Carmon
  • 86
  • 1
  • 7
  • My modal pops up properly(as desired) everywhere except when it is used in the tag written in on_render_cell(). the problem is *this* refers to image, not the component – Pooja Chawla Dec 21 '18 at 14:36
  • Ok I'm not sure I understand. the onClick you are talking about is when clicking the image, or when clicking the input inside the div? anyway I didn't say that `onClick={() => this.openModal()} ` won't work, I am saying it creates a new function each render. you can read about it [here](https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56). – Gilli Carmon Dec 21 '18 at 15:04
  • onClick when clicking the image. @Gilli Carmon – Pooja Chawla Dec 21 '18 at 15:16
  • Ok so you need to pass the image the function. I would put the modal and the render cells in the same component, and pass to the render cells the modal functions. so the onClick method will point to this.props.modalOpen. I hope I was clear. – Gilli Carmon Dec 21 '18 at 15:38
  • on_render_cell can access the openModal(), but the tag cannot. Because it is stored in the variable result. Please see the code. Thanks – Pooja Chawla Dec 21 '18 at 16:01
  • Thanks dear. I tried running your code snippet, but by doing so, the image itself is not appearing, meaning that it works only when result stores string not JSX. – Pooja Chawla Dec 21 '18 at 18:48
  • Can you show me the code that calls on_render_cells? I think that it doesn't show the image because of the new way of return of the method the image won't show. – Gilli Carmon Dec 21 '18 at 19:04
  • It’s the same code that you wrote for me by modifying string to JSX and using return() at end. – Pooja Chawla Dec 21 '18 at 21:14
  • No but where do you call the function. where is the code that you write one_render_cells()? Because I ran the code and it worked for me. – Gilli Carmon Dec 22 '18 at 01:12
  • I am using the scheduler(calendar) and on_render_cell is responsible for rendering the cells of scheduler. Like the images of cloud, sun, etc are displayed on each date of month here [ej2.syncfusion.com/react/demos/#/material/schedule/…, I am displaying circles instead of those images and want to open modal when user clicks it. See this demo link[https://ej2.syncfusion.com/react/demos/#/material/schedule/date-header-template]. Go to the month view here and try to implement onClick handler on images like sun, cloud etc – Pooja Chawla Dec 22 '18 at 13:42
  • hey thanks a lot. JSX way is not working. I honestly appreciate your efforts and heartily thank u. Your approach wasn't working, so I ended up adding event listener to the element and now it works. Thanks :) – Pooja Chawla Dec 22 '18 at 21:25
0

You can give some var like myRef to your componen as a prop, then in onComponentDidMount of your component assign to prop myRef current instance (this). this.props.myRef = this, then in your parent component you can use methods of myRef. For more you can check this post React.js - access to component methods