Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PeoplePicker component with SPBrowser #1349

Closed
divewoot opened this issue Nov 2, 2022 · 5 comments
Closed

PeoplePicker component with SPBrowser #1349

divewoot opened this issue Nov 2, 2022 · 5 comments

Comments

@divewoot
Copy link

divewoot commented Nov 2, 2022

Category

[ x] Question

Version

Please specify what version of the library you are using: [ 3.10.0 ]

Question

While not able to deploy a solution as Spfx. . . have a react app loaded to sharepoint page via content editor webpart. Using SPBrowser from @pnp/sp to handle authentication, the react app is able to read people fields from a list and display these in a desired table format.
Is it possible to use the PeoplePicker component from @pnp/spfx-controls-react also in the same react app? When attempting, see error "PeoplePicker' cannot be used as a JSX component.
Its instance type 'PeoplePicker' is not a valid JSX element.
The types returned by 'render()' are incompatible between these types.
Type 'ReactElement<IPeoplePickerProps, string | JSXElementConstructor>' is not assignable to type 'ReactNode'.
Property 'children' is missing in type 'ReactElement<IPeoplePickerProps, string | JSXElementConstructor>' but required in type 'ReactPortal'.ts(2786)
index.d.ts(181, 9): 'children' is declared here.

here is the full PeoplePicker component and how it is currently setup.

import * as React from 'react';
import styles from './SpfxPnpPeoplepicker.module.scss';
import { ISpfxPnpPeoplepickerProps } from './ISpfxPnpPeoplepickerProps';
import { ISpfxPnpPeoplepickerState, IUserDetail } from './ISpfxPnpPeoplepickerState';
import { PeoplePicker, PrincipalType } from "@pnp/spfx-controls-react/lib/PeoplePicker";
import { autobind } from 'office-ui-fabric-react/lib/Utilities';
import { spfi, SPBrowser } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";

const myTenant: string = 'xxx'
const mySite: string = "xxx"


 // you should use the baseUrl value when working in a SPA to ensure it is always properly set for all requests
 const sp: any = spfi().using(SPBrowser({ baseUrl: "https://"+myTenant+".sharepoint.com/sites/"+mySite }));


export default class SpfxPnpPeoplepicker extends React.Component<ISpfxPnpPeoplepickerProps, ISpfxPnpPeoplepickerState> {
  constructor(props: ISpfxPnpPeoplepickerProps, state: ISpfxPnpPeoplepickerState) {
    super(props);
    sp.setup({
      spfxContext: this.props.context
    });
    this.state = { SuccessMessage: '', UserDetails: [], selectedusers: [] };
    this._getListItem();
  }

  @autobind
  private async _getListItem() {
    const item: any = await sp.web.lists.getByTitle("Teams").items.getById(1).select("Title", "Team/Name").expand("Team").get();
    let usernamearr: string[] = [];
    item.Team.forEach((user: { Name: string; }) => {
      usernamearr.push(user.Name.split('|membership|')[1].toString());
    })
    this.setState({
      selectedusers: usernamearr
    });
  }

  public render(): React.ReactElement<ISpfxPnpPeoplepickerProps> {
    return (
      <div className={styles.spfxPnpPeoplepicker}>
        <PeoplePicker
          context={this.props.context}
          titleText="People Picker"
          personSelectionLimit={3}
          showtooltip={true}
          isRequired={true}
          selectedItems={this._getPeoplePickerItems}
          showHiddenInUI={false}
          principalTypes={[PrincipalType.User]}
          defaultSelectedUsers={this.state.selectedusers}
          resolveDelay={1000} />
        <br></br>
        <button className={styles.button} onClick={this._updateListItem}>Save</button>
        <br></br>
        <br></br>
        <label className={styles.label}>{this.state.SuccessMessage}</label>
      </div>
    );
  }

  @autobind
  private _getPeoplePickerItems(items: any[]) {
    let userarr: IUserDetail[] = [];
    items.forEach(user => {
      userarr.push({ ID: user.id, LoginName: user.loginName });
    })
    this.setState({ UserDetails: userarr })
  }

  @autobind
  private async _updateListItem() {
    let userids: object[] = [];
    this.state.UserDetails.forEach(user => {
      userids.push({ key: user.LoginName });
    })
    const updatedItem = await sp.web.lists.getByTitle("Teams").items.getById(1).validateUpdateListItem(
      [{
        FieldName: "Team",
        FieldValue: JSON.stringify(userids),
      }]);
    this.setState({ SuccessMessage: 'Successfully saved' });
  }
}
@ghost
Copy link

ghost commented Nov 2, 2022

Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.

@ghost ghost added the Needs: Triage 🔍 label Nov 2, 2022
@github-actions
Copy link

github-actions bot commented Nov 2, 2022

Thank you for submitting your first issue to this project.

@bcobra
Copy link

bcobra commented Apr 3, 2023

using 3.13.0
'PeoplePicker' cannot be used as a JSX component.
Its instance type 'PeoplePicker' is not a valid JSX element.
The types returned by 'render()' are incompatible between these types.
Type 'ReactElement<IPeoplePickerProps, string | JSXElementConstructor>' is not assignable to type 'ReactNode'.
Property 'children' is missing in type 'ReactElement<IPeoplePickerProps, string | JSXElementConstructor>' but required in type 'ReactPortal'.ts(2786)
index.d.ts(192, 9): 'children' is declared here.

@michaelmaillot
Copy link
Collaborator

michaelmaillot commented Aug 10, 2023

Hi @divewoot & @bcobra,

If I understand your request correctly, you want to use SPFx Controls / React through a JS Script Editor webpart right?

Or does the code provided above is compiled and stored somewhere, to be imported in the Script Editor?

I'm confused about the fact that you can't deploy a SPFx solution but you're referring to this.props.context to init PnPjs sp.

Edit: or is it a issue when using PeoplePicker control outside of SPFx? If so, it's not possible I think, since it needed a SPFx context object (which is BaseComponentContext). But I know there's a feature request to replace this whole context thing by only properties needed for querying users.

@divewoot
Copy link
Author

Thanks for responding on this. Will mark this closed since using the PeoplePicker outside of SPFx is not possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants