0

I'm working on a SharePoint Webpart and my DefaultButton has brocken. I load items to an office-ui-fabric Dropdown from a SharePoint List. It's working fine, I get the value of the selected options, but... I want to push the selected value in an other SharePoint List.

I use onClick to implement my addListItem Method and getting the following error:

No overload matches this call. Overload 1 of 2, '(props: IButtonProps | Readonly): DefaultButton', gave the following error. Type '(event: FormEvent, option: IDropdownOption) => void' is not assignable to type 'MouseEventHandler<HTMLDivElement | HTMLAnchorElement | HTMLButtonElement | BaseButton | Button | HTMLSpanElement>'. Overload 2 of 2, '(props: IButtonProps, context: any): DefaultButton', gave the following error. Type '(event: FormEvent, option: IDropdownOption) => void' is not assignable to type 'MouseEventHandler<HTMLDivElement | HTMLAnchorElement | HTMLButtonElement | BaseButton | Button | HTMLSpanElement>'.

And below my Code:

import pnp,{} from 'sp-pnp-js';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';   
import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { FormEvent } from 'react';

export default class Form extends React.Component<
IFormProps, 
IListFormState,

{}
> {

constructor(props: IFormProps){
    super(props);
    this.addListItem = this.addListItem.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.state = { options:[], selectedValue:"", selectedOption: "" };
    
 }
 
  public render(): React.ReactElement<IFormProps> {
    return (
          <div className={styles.choice}><br></br><br></br>
            <Dropdown options={this.state.options}
                      onChange={ this.handleChange}
                     />
          </div>
          <label id="infoLabel" className={styles.infoText}> {this.state.selectedValue} </label>
          
          <DefaultButton className={styles.btn1} onClick= {()=> this.addListItem }> Rückruf eintragen </DefaultButton>
); 
  } 

private getListItems = async () => {
    const listItems = await   pnp.sp.web.lists.getByTitle('DropdownList').items.select('Beschreibung','Beschreibung0').get();
    return listItems;
  };

  private createOptions = (listItems: any) => {
    const options = listItems.map((item: { Beschreibung: any; Beschreibung0: any; }) => {
      return { key: item.Beschreibung0, text: item.Beschreibung };
    });
    return options;
  };

  componentDidMount() {
    this.getListItems().then(listItems => {
      const options = this.createOptions(listItems);
      this.setState({options});

    });
  }
  
 public handleChange = (event: FormEvent<HTMLDivElement>, option: IDropdownOption): void => {
    this.setState({
      selectedOption: option.text,
      selectedValue: option.key.toString()
    });
    this.setState({ selectedOption: option.text });
    console.log("Selected Option: " + option.text); // "Selected Option for example: Ferrari"
    
  }
 
 public addListItem (event: FormEvent<HTMLDivElement>, option: IDropdownOption) {
    let dropdown = option.text;
    // item push in the SharePoint List
    pnp.sp.web.lists.getByTitle("TestList")
    .items.add({
      'Rubrik': dropdown
    })
    .then(()=> alert("Die Datei wurde erfolgreich gespeichert!"));
       }
    }    
  }

I tried this way too:

<DefaultButton className={styles.btn1} onClick= {()=> this.addListItem }> Rückruf eintragen </DefaultButton>

This way looks like a solution, I have no more error(s), but my button action doesn't work. I have no issue, no error message in VSCode, no error message on Chrome, EDGE or Firefox Console, no alert, nothing.

Anyone some idea? Thank you!

2 Answers 2

0

I see a couple things here...

If you do

OnClick={ () => this.addListItem }

it's actually creating a mini context/closure inside the brackets there, by using () => , and you are referencing your handler function there but you are not actually calling it. What you would need to do if you wanted to construct your handler that way would be to do:

OnClick={ () => this.addListItem() }

Adding the parentheses to the function name will call the function. But, you don't need to do that. You can hook up that handler the same way you hook up your dropdown handler, simply by referencing the function that should be the callback without creating a special context for it:

OnClick={this.addListItem}

Now, regarding the error, you're getting that because you are passing the same parameters to your button click handler that you are passing to your dropdown change handler.

// it makes sense that a dropdown event handler would expect
// something from a dropdown control, like a dropdown option
public handleChange = (event: FormEvent<HTMLDivElement>, option: IDropdownOption): void => { }

// you hooked up your addListItem function as an event handler to a _button_
// why would a button expect to know anything about something that's part of a dropdown control, like a dropdown option?
// it wouldn't know anything about dropdown options, because it's a button
public addListItem (event: FormEvent<HTMLDivElement>, option: IDropdownOption) { }

You need the value of the dropdown in the addListItem function, but you already set that value into state when you handle the onChange event from the dropdown, so you can just pull that value from state in the addListItem function.

(You also are unnecessarily setting the value of the selected option twice in your handleChange function, which you don't need to do.)

I would set up those two functions like this:

public handleChange = (event: FormEvent<HTMLDivElement>, option: IDropdownOption): void => {
    console.log("Selected Option: " + option.text); // "Selected Option for example: Ferrari"
    // you only need to call setState once
    this.setState({
        selectedOption: option.text,
        selectedValue: option.key.toString()
    });
}

// set this up as an arrow function, with _no_ parameters
public addListItem = (): void => { 
    // pull the value of the dropdown from where you stored it in state
    const { selectedOption } = this.state;
    // item push in the SharePoint List
    pnp.sp.web.lists.getByTitle("TestList")
    .items.add({
      'Rubrik': selectedOption
    })
    .then(() => alert("Die Datei wurde erfolgreich gespeichert!"));
}
1
0

Your button has no way of passing dropdown information. That signature isn't for an onClick of a button.

If you're trying to pull the selected value of the dropdown and then save it to a list on click, I recommend switching from an uncontrolled dropdown to a controlled one by setting the selectedKey of the dropdown to a member of your state and then updating it using the onChange event. Then in your onClick handler for the button you can access that value.

See the Controlled single-select Dropdown example for details on doing this: https://developer.microsoft.com/en-us/fluentui#/controls/web/dropdown

You can also see an example of how the onClick handler for a DefaultButton is being used here: https://developer.microsoft.com/en-us/fluentui#/controls/web/button

You should also change your onClick signature to use an arrow function like you're doing elsewhere. Something like this:

public addListItem = (): void => {

Then set the onClick of the Button like this:

<DefaultButton className={styles.btn1} onClick={this.addListItem}> Rückruf eintragen </DefaultButton>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.