0

Two questions: I'm studying spfx and for this particular example I provide I don't understand how the Send button associates with the setComment() function. I've created an Update button which I want to use to update the item I've just created. This does nothing even though I've passed the props to it (maybe incorrectly!)

For the Update button I've tried using React to pass the props using an onClick within the JSX, but that doesn't work. I've also tried doing this without the $. I've created a seperate set of functions _readListItem() and _getListItem() to help me but not sure how to use them in combination with _updateListItem(), or whether I need them at all.

import { Environment, EnvironmentType, Version } from '@microsoft/sp-core-library';
import { ISPHttpClientOptions, SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import { escape } from '@microsoft/sp-lodash-subset';
import { BaseClientSideWebPart, IPropertyPaneConfiguration, PropertyPaneTextField } from '@microsoft/sp-webpart-base';
import * as strings from 'FeedbackWebpartWebPartStrings';
import styles from './FeedbackWebpart.module.scss';
import { IFeedbackWebPartProps } from './IFeedbackWebPartProps';
import {ISPListItem} from './ISPListItem';

export default class FeedbackWebpartWebPart extends BaseClientSideWebPart<IFeedbackWebPartProps> {

  public render(): void {
    this._updateListItem = this._updateListItem.bind(this);
    this._readListItem = this._readListItem.bind(this);
    this.domElement.innerHTML = `
    <div>
    <p class='${styles.titleText}'>Job Evaluation Form</p>
    <i class='ms-Icon ms-Icon--NoteForward' aria-hidden='true'></i>
    <p class='${styles.labelText}'>Name</p>
    <input type='text' class='${styles.input}' maxlength='255' placeholder='${escape(this.properties.hintText)}' />
    <br>
    <br>
    <p class='${styles.labelText}'>Job Title</p>
    <input type='text' class='${styles.input}' maxlength='255' placeholder='${escape(this.properties.hintText)}' />
    <br>
    <p class='${styles.successIndicator}'></p>
    <br>
    <br>
    <br>
    <button type='button' class='ms-Button'><span class='ms-Button-label'>Send</span></button>
    <br>
    <br>
    <button type='button' class='ms-Button' onClick='${this._updateListItem}'><span class='ms-Button-label'>Update</span></button>
    </div>`;

 //The binding below allows setComment to be used in the render and outside of it.
    this.setComment = this.setComment.bind(this);
    this._updateListItem = this._updateListItem.bind(this);
    this._readListItem = this._readListItem.bind(this);
    //Grab ALL the <input> elements
    // [0] -  just want the first element
    // cast this generic element to specific type of element (which I know that it is) as the variable is expecting a specific type
    const textInput: HTMLInputElement = this.domElement.getElementsByTagName("INPUT") [0] as HTMLInputElement;

    // setComment is used in an event listener here to be called upon whenever a user types into this input field.
    textInput.addEventListener("keyup", this.setComment);
    this.sendFeedback = this.sendFeedback.bind(this);
    const submitbutton: HTMLButtonElement = this.domElement.getElementsByTagName("BUTTON") [0] as HTMLButtonElement;

    submitbutton.onclick = this.sendFeedback;
    submitbutton.disabled = true;

  }
private _updateListItem(): void {

  const url: string = this.context.pageContext.site.absoluteUrl+"/_api/web/lists/getbytitle('Feedback')/items(1)";
  const itemDefinition : any = {
    "Title" : "Modified title field value!"};
    const headers:any = {
      "X-HTTP-Method":"MERGE",
      "IF-MATCH": "*",
    };
    const spHttpClientOptions: ISPHttpClientOptions = {
      "headers": headers,
      "body": JSON.stringify(itemDefinition)
    };
    this.context.spHttpClient.post(url, SPHttpClient.configurations.v1,spHttpClientOptions)
    .then((response: SPHttpClientResponse) => {
      if (response.status === 204) {
        this._operationResults.innerHTML = "Update: List Item updated successfully.";

      } else {
        this._operationResults.innerHTML = "Update: List Item update failed. " +response.status+" - "+response.statusText;
      }
    });
    }

private sendFeedback(): void {
  this.context.statusRenderer.clearError(this.domElement);
  const paragraphElement: HTMLParagraphElement = this.domElement.getElementsByClassName(styles.successIndicator) [0] as HTMLParagraphElement;
  paragraphElement.innerHTML="";

  if(this._commentText === undefined || this._commentText.length === 0) {
    this.context.statusRenderer.renderError(this.domElement, "Please type in a comment or a suggestion.");
    return;

  }
  if(Environment.type === EnvironmentType.Local) {
    this.context.statusRenderer.renderError(this.domElement, "Feedback can't be saved when running in local workbench");
    return;
  }

  const url: string = this.context.pageContext.site.absoluteUrl+"/_api/web/lists/getbytitle('Feedback')/items";
  const item : any = {
    "Title": this._commentText,
    "URL": window.location.href,
    "JobTitle": this._jobTitle
  };

  const spHttpClientOptions: ISPHttpClientOptions = {
    "body": JSON.stringify(item)
  };

I'm sorry there is a lot of code but I don't know how you would understand what I need to know if I don't provide it.

I expect to understand how the Send button works and the Update button to update the item of any changes when clicked.

NightTom
  • 418
  • 15
  • 37

1 Answers1

1

Looks like the "Send" button onClick event is set with the following code:

const submitbutton: HTMLButtonElement = this.domElement.getElementsByTagName("BUTTON") [0] as HTMLButtonElement;

submitbutton.onclick = this.sendFeedback;

Here getElementsByTagName("BUTTON")[0] returns the first element created with in the above HTML.

I guess going with the same approach, the update button could be handled like so:

const updateButton: HTMLButtonElement = this.domElement.getElementsByTagName("BUTTON") [1] as HTMLButtonElement;

updateButton.onclick = this._updateListItem.bind(this);

Note the changed index from [0] to [1], to take the second button, as well as the usage of bind(). Without bind, "this" would be undefined when _updateListItem is called.

Niilo Keinänen
  • 2,187
  • 1
  • 7
  • 12
  • Thanks. The Update button still isn't doing anything though. Is it because it needs it's own event handler or can I just use the setComment(event: Event) one? – NightTom Jul 15 '19 at 15:01
  • I'm getting TypeError: Cannot set property 'innerHTML' of null when clicking on hte Update button. – NightTom Jul 15 '19 at 15:14