Skip to content

Commit

Permalink
Merge pull request #50 from AJIXuMuK/field-lookup-optimization
Browse files Browse the repository at this point in the history
Lookup Field Renderer Optimization
  • Loading branch information
estruyf authored Mar 12, 2018
2 parents 3cfa7ae + 55e88b6 commit f004a95
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { FieldLookupRenderer } from "@pnp/spfx-controls-react/lib/FieldLookupRen
- Use the `FieldLookupRenderer` control in your code as follows:

```TypeScript
<FieldLookupRenderer lookups={event.fieldValue} dispFormUrl={'https://contoso.sharepoint.com/_layouts/15/listform.aspx?PageType=4&ListId={list_id}'} className={'some-class'} cssProps={{ background: '#f00' }} />
<FieldLookupRenderer lookups={event.fieldValue} fieldId={'<field-guid>'} context={this.context} className={'some-class'} cssProps={{ background: '#f00' }} />
```

## Implementation
Expand All @@ -36,6 +36,8 @@ The FieldLookupRenderer component can be configured with the following propertie
| lookups | ISPFieldLookupValue[] | yes | Lookup field values. |
| dispFormUrl | boolean | no | Url of Display form for the list that is referenced by the lookup. |
| onClick | (args: ILookupClickEventArgs) => {} | no | Custom event handler of lookup item click. If not set the dialog with Display Form will be shown. |
| fieldId | string | Field's id |
| context | IContext | Customizer context. Must be providede if fieldId is set |

![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/fields/FieldLookupRenderer)

22 changes: 12 additions & 10 deletions src/common/utilities/FieldRendererHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,18 @@ export class FieldRendererHelper {
break;
case "Lookup":
case "LookupMulti":
SPHelper.getLookupFieldListDispFormUrl(field.id.toString(), context).then(dispFormUrlValue => {
const lookupValues = fieldValue as ISPFieldLookupValue[];
const dispFormUrl: string = dispFormUrlValue.toString();
resolve(React.createElement(FieldLookupRenderer, {
lookups: lookupValues,
dispFormUrl: dispFormUrl,
...props
}));
});

//
// we're providing fieldId and context. In that case Lookup values will be rendered right away
// without additional lag of waiting of response to get dispUrl.
// The request for DispUrl will be sent only if user click on the value
//
const lookupValues = fieldValue as ISPFieldLookupValue[];
resolve(React.createElement(FieldLookupRenderer, {
lookups: lookupValues,
fieldId: field.id.toString(),
context: context,
...props
}));
break;
case 'URL':
SPHelper.getFieldProperty(field.id.toString(), 'Format', context, true).then(format => {
Expand Down
101 changes: 77 additions & 24 deletions src/controls/fields/fieldLookupRenderer/FieldLookupRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import { override } from '@microsoft/decorators';
import * as React from 'react';
import { css, DialogType, Link } from 'office-ui-fabric-react';
import { css, Dialog, DialogType, Link, Spinner, SpinnerSize } from 'office-ui-fabric-react';

import { ISPFieldLookupValue } from "../../../common/SPEntities";
import { IFieldRendererProps } from '../fieldCommon/IFieldRendererProps';
import * as appInsights from '../../../common/appInsights';

import styles from './FieldLookupRenderer.module.scss';
import IFrameDialog from '../../iFrameDialog/IFrameDialog';
import { SPHelper } from '../../../Utilities';
import { IContext } from '../../../Common';

/**
* Field Lookup Renderer Props
* There are 3 options to provide the props:
* - [recommended, used in FieldRendererHelper] Provide fieldId and context. In that case request for DispUrl will be sent only if a user clicks on the value
* - Provide dispFormUrl: if you know this URL a priori you can provide it into the renderer
* - Provide onClick handler to handle value's click event outside the renderer
*/
export interface IFieldLookupRendererProps extends IFieldRendererProps {
/**
* lookup values
Expand All @@ -22,14 +31,23 @@ export interface IFieldLookupRendererProps extends IFieldRendererProps {
* custom event handler of lookup item click. If not set the dialog with Display Form will be shown
*/
onClick?: (args: IFieldLookupClickEventArgs) => {};
/**
* Field's id.
*/
fieldId?: string;
/**
* Customizer context. Must be providede if fieldId is set
*/
context?: IContext;
}

/**
* For future
* Field Lookup Renderer State
*/
export interface IFieldLookupRendererState {
hideDialog?: boolean;
lookupDispFormUrl?: string;
dispFormUrl?: string;
}

/**
Expand All @@ -51,7 +69,8 @@ export class FieldLookupRenderer extends React.Component<IFieldLookupRendererPro
appInsights.track('FieldLookupRenderer', {});

this.state = {
hideDialog: true
hideDialog: true,
dispFormUrl: props.dispFormUrl
};
}

Expand All @@ -61,23 +80,35 @@ export class FieldLookupRenderer extends React.Component<IFieldLookupRendererPro
return <Link onClick={this._onClick.bind(this, lookup)} className={styles.lookup} style={this.props.cssProps}>{lookup.lookupValue}</Link>;
});
return (
<div style={this.props.cssProps} className={css(this.props.className)}>{lookupLinks}
{!this.state.hideDialog && <IFrameDialog
url={this.state.lookupDispFormUrl}
iframeOnLoad={this._onIframeLoaded.bind(this)}
hidden={this.state.hideDialog}
onDismiss={this._onDialogDismiss.bind(this)}
modalProps={{
isBlocking: true,
containerClassName: styles.dialogContainer
}}
dialogContentProps={{
type: DialogType.close,
showCloseButton: true
}}
width={'570px'}
height={'315px'}/>}
</div>);
<div style={this.props.cssProps} className={css(this.props.className)}>{lookupLinks}
{!this.state.hideDialog && this.state.dispFormUrl && <IFrameDialog
url={this.state.lookupDispFormUrl}
iframeOnLoad={this._onIframeLoaded.bind(this)}
hidden={this.state.hideDialog}
onDismiss={this._onDialogDismiss.bind(this)}
modalProps={{
isBlocking: true,
containerClassName: styles.dialogContainer
}}
dialogContentProps={{
type: DialogType.close,
showCloseButton: true
}}
width={'570px'}
height={'315px'} />}
{!this.state.hideDialog && !this.state.dispFormUrl && <Dialog
onDismiss={this._onDialogDismiss.bind(this)}
modalProps={{
isBlocking: true,
containerClassName: styles.dialogContainer
}}
dialogContentProps={{
type: DialogType.close,
showCloseButton: true
}}>
<Spinner size={SpinnerSize.large} />
</Dialog>}
</div>);
}

private _onClick(lookup: ISPFieldLookupValue): void {
Expand All @@ -92,10 +123,32 @@ export class FieldLookupRenderer extends React.Component<IFieldLookupRendererPro
//
// showing Display Form in the dialog
//
this.setState({
lookupDispFormUrl: `${this.props.dispFormUrl}&ID=${lookup.lookupId}&RootFolder=*&IsDlg=1`,
hideDialog: false
});
if (this.state.dispFormUrl) {
this.setState({
lookupDispFormUrl: `${this.state.dispFormUrl}&ID=${lookup.lookupId}&RootFolder=*&IsDlg=1`,
hideDialog: false
});
}
else if (this.props.fieldId) {

this.setState({
hideDialog: false
});

SPHelper.getLookupFieldListDispFormUrl(this.props.fieldId, this.props.context).then(dispFormUrlValue => {
const dispFormUrl: string = dispFormUrlValue.toString();
this.setState((prevState, props) => {
if (prevState.hideDialog) {
return;
}

return {
dispFormUrl: dispFormUrl,
lookupDispFormUrl: `${dispFormUrl}&ID=${lookup.lookupId}&RootFolder=*&IsDlg=1`
};
});
});
}
}

private _onIframeLoaded(iframe: any): void {
Expand Down

0 comments on commit f004a95

Please sign in to comment.