0

I created a SharePoint Framework Webpart.

I call a webservice that returns some data from sharepoint (terms from termstore), and for each term i generate an html that display the term. On the onclick of each term i want to call a typescript function, passing the term as parameters, to get its children terms.

This code below create the following wrong behaviour: when the webpart is displayed, it automatically calls the function this.readIterm when I didnt even click on it !

Am I missing something or by design doing it the wrong way ? I tried to replace onclick="${this.readIterm(term)}" by onclick="readIterm($(term))" but it does nothing.

Code below

terms.forEach(term => {
              htmlContent +=
                `<div class="w3-card w3-third w3-margin-bottom" style="" onclick="${this.readIterm(term)}">
                      <header class="w3-container w3-blue">
                        <h1>Header</h1>
                      </header>
                    <div class="w3-container">
                      <span>${term.name}</p>
                    </div>
                    <footer class="w3-container w3-blue">
                      <h5>Footer</h5>
                    </footer>
                    </div>`

This html is then added to this.domElement.innerHTML, displaying it in the webpart.

public readIterm(myTerm: ITerm) { alert("readIterm is clicked"); }

Thank you in advance for your help and guidance if I do not follow best practice !

Jeff

Jeff
  • 83
  • 1
  • 7

2 Answers2

2

There is one more way to attach event listener.

Refer below code sample. This works perfectly for me: (Note: This is a basic idea. You can refer this code and make changes to yours accordingly.)

public render(): void{ 

this.domElement.innerHTML = ` <div class="form-group">
   <button class="btn btn-success" id="btnReadAllItems">
      <span class="ms-Button-label">Read All Items</span>
   </button>
   <button class="btn btn-success" id="btnReadItemById">
      <span class="ms-Button-label">Read Item By Id</span>
   </button>
</div>`; 
this._setButtonEventHandlers(); 

}



private _setButtonEventHandlers(): void {
   const webPart: SpfxCrudWebPart = this;
   this.domElement.querySelector('#btnReadAllItems').addEventListener('click', () => {
      this._GetListItemsNF();
   });
}


private _GetListItemsNF(): void {
   // 
   //
   //
}

Another way is as below. (But you will have to make some changes according to your code)

public render(): void{ 
      htmlContent +=
        `<div class="w3-card w3-third w3-margin-bottom" id="test">
              <header class="w3-container w3-blue">
                <h1>Header</h1>
              </header>
            <div class="w3-container">
              <span>${term.name}</p>
            </div>
            <footer class="w3-container w3-blue">
              <h5>Footer</h5>
            </footer>
        </div>`
    }

    this._setButtonEventHandlers(); 

    this.myTerm = term;  // Here we are assigning value to the `myTerm` variable. And `myTerm` is a public property, So value of `myTerm` will be accessible using `this.myTerm`
}


public myTerm: ITerm; // here we are declaring `myTerm` variable

public readIterm():void{

    // here you can access the cariable `myTerm` using `this.myTerm`.

    // alert(this.myTerm);

    // alert("readIterm is clicked"); 

}

private _setButtonEventHandlers(): void {
   this.domElement.querySelector('#test').addEventListener('click', () => { this.readIterm(); });
}
Rohit Waghela
  • 844
  • 3
  • 11
  • 21
  • I cant get it work with your solutions because Im getting terms from term store, for each term i generate an HTML To display it. On clicking on the term i need to pass the selected term, that is why i wanted to do smth like that : onclick="${this.readIterm(term)}"> maybe this is not the good practice. Thanks for your time :) – Jeff Sep 05 '17 at 15:43
  • please refer the above answer. I have updated and added one more approach. You can try this way. – Rohit Waghela Sep 06 '17 at 15:35
  • Hi thanks for your help I think I can fill an array of term object, then iterate those objects (my terms), and call the onclick and pass the object as parameter. I dont know if this is the good design. Maybe react helps for that ? – Jeff Sep 07 '17 at 14:20
0

Rather onClick instead of onclick. Then check to make sure that you get into your "readIterm" method by calling the console (console.log).

  • it gets into readIterms as the code defined. But without even clicking. It gets inside each time a term is displayed; – Jeff Aug 29 '17 at 07:38
  • But where does your method come from? Is it included in your module? Or else imported? If your method is imported, then call it there directly (eg {maMethode ()}, no need for this). Otherwise if it is passed in parameter of your module then declares there in local before calling it. Hoping to have helped. – Thedaril Aug 29 '17 at 07:44
  • the method is in the same TS file – Jeff Aug 29 '17 at 07:46
  • public readIterm(myTerm: ITerm) { alert("readIterm is clicked"); } – Jeff Aug 29 '17 at 07:46
  • If you want to perform the action by clicking, then you will have to declare in your module the method to attach it to the event (ex: const readIterm_ = event => () {readIterm ()}). Unless you explicitly pass the method to the module, I do not see how you could call a server method from your module (knowing that the context of your module is partitioned in {}). – Thedaril Aug 29 '17 at 08:03
  • Maybe this link will help you: https://stackoverflow.com/questions/41264672/call-typescript-function-from-c-sharp-webbrowser-control. Dont have code to share :( – Thedaril Aug 29 '17 at 08:11