Skip to content

Commit eb68fb6

Browse files
authored
Merge pull request pnp#54 from SharePoint/dev
Dev
2 parents 90d982c + d8dc76a commit eb68fb6

File tree

15 files changed

+215
-56
lines changed

15 files changed

+215
-56
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Releases
22

3+
## 1.2.4
4+
5+
**Enhancements**
6+
- Hiding placeholder web part on small zones
7+
8+
**Fixes**
9+
- iFrame dialog reference fix [#52 - Need some more implementation documentation on IFrameDialog](https://github.com/SharePoint/sp-dev-fx-controls-react/issues/52)
10+
311
## 1.2.3
412

513
**Enhancements**

docs/documentation/docs/about/release-notes.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Releases
22

3+
## 1.2.4
4+
5+
**Enhancements**
6+
- Hiding placeholder web part on small zones
7+
8+
**Fixes**
9+
- iFrame dialog reference fix [#52 - Need some more implementation documentation on IFrameDialog](https://github.com/SharePoint/sp-dev-fx-controls-react/issues/52)
10+
311
## 1.2.3
412

513
**Enhancements**

docs/documentation/docs/controls/IFrameDialog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Here is an example of the control in action:
1515
import { IFrameDialog } from "@pnp/spfx-controls-react/lib/IFrameDialog";
1616
```
1717

18-
- Use the `IFrameDialog` control in your code as follows:
18+
- Use the `IFrameDialog` control in your code as follows (`this._onIframeLoaded` and `this._onDialogDismiss` are methods that should be implemented if you want to execute some actions when the iframe content is loaded and dialog should be closed respectively):
1919

2020
```TypeScript
2121
<IFrameDialog

docs/documentation/docs/controls/fields/FieldLookupRenderer.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { FieldLookupRenderer } from "@pnp/spfx-controls-react/lib/FieldLookupRen
2222
- Use the `FieldLookupRenderer` control in your code as follows:
2323

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

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

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

docs/documentation/docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ npm install @pnp/spfx-controls-react --save --save-exact
1919
Once the package is installed, you will have to configure the resource file of the property controls to be used in your project. You can do this by opening the `config/config.json` and adding the following line to the `localizedResources` property:
2020

2121
```json
22-
"ControlStrings": "./node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
22+
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
2323
```
2424

2525
## Available controls

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@pnp/spfx-controls-react",
33
"description": "Reusable React controls for SharePoint Framework solutions",
4-
"version": "1.2.3",
4+
"version": "1.2.4",
55
"engines": {
66
"node": ">=0.10.0"
77
},

src/common/utilities/FieldRendererHelper.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { SPField } from '@microsoft/sp-page-context';
99
import { IContext } from '../Interfaces';
1010
import { GeneralHelper } from './GeneralHelper';
1111
import { FieldLookupRenderer, IFieldLookupClickEventArgs } from '../../controls/fields/fieldLookupRenderer/FieldLookupRenderer';
12-
import IFrameDialog from '../../controls/iFrameDialog/IFrameDialog';
1312
import { FieldUrlRenderer } from '../../controls/fields/fieldUrlRenderer/FieldUrlRenderer';
1413
import { FieldTaxonomyRenderer } from '../../controls/fields/fieldTaxonomyRenderer/FieldTaxonomyRenderer';
1514
import { IFieldRendererProps } from '../../controls/fields/fieldCommon/IFieldRendererProps';
@@ -132,16 +131,18 @@ export class FieldRendererHelper {
132131
break;
133132
case "Lookup":
134133
case "LookupMulti":
135-
SPHelper.getLookupFieldListDispFormUrl(field.id.toString(), context).then(dispFormUrlValue => {
136-
const lookupValues = fieldValue as ISPFieldLookupValue[];
137-
const dispFormUrl: string = dispFormUrlValue.toString();
138-
resolve(React.createElement(FieldLookupRenderer, {
139-
lookups: lookupValues,
140-
dispFormUrl: dispFormUrl,
141-
...props
142-
}));
143-
});
144-
134+
//
135+
// we're providing fieldId and context. In that case Lookup values will be rendered right away
136+
// without additional lag of waiting of response to get dispUrl.
137+
// The request for DispUrl will be sent only if user click on the value
138+
//
139+
const lookupValues = fieldValue as ISPFieldLookupValue[];
140+
resolve(React.createElement(FieldLookupRenderer, {
141+
lookups: lookupValues,
142+
fieldId: field.id.toString(),
143+
context: context,
144+
...props
145+
}));
145146
break;
146147
case 'URL':
147148
SPHelper.getFieldProperty(field.id.toString(), 'Format', context, true).then(format => {

src/controls/fields/fieldLookupRenderer/FieldLookupRenderer.tsx

Lines changed: 78 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
import { override } from '@microsoft/decorators';
22
import * as React from 'react';
3-
import { css, DialogType, Link } from 'office-ui-fabric-react';
3+
import { css, Dialog, DialogType, Link, Spinner, SpinnerSize } from 'office-ui-fabric-react';
44

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

99
import styles from './FieldLookupRenderer.module.scss';
10-
import IFrameDialog from '../../iFrameDialog/IFrameDialog';
10+
import { IFrameDialog } from '../../iFrameDialog/IFrameDialog';
11+
import { SPHelper } from '../../../Utilities';
12+
import { IContext } from '../../../Common';
1113

14+
/**
15+
* Field Lookup Renderer Props
16+
* There are 3 options to provide the props:
17+
* - [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
18+
* - Provide dispFormUrl: if you know this URL a priori you can provide it into the renderer
19+
* - Provide onClick handler to handle value's click event outside the renderer
20+
*/
1221
export interface IFieldLookupRendererProps extends IFieldRendererProps {
1322
/**
1423
* lookup values
@@ -22,14 +31,23 @@ export interface IFieldLookupRendererProps extends IFieldRendererProps {
2231
* custom event handler of lookup item click. If not set the dialog with Display Form will be shown
2332
*/
2433
onClick?: (args: IFieldLookupClickEventArgs) => {};
34+
/**
35+
* Field's id.
36+
*/
37+
fieldId?: string;
38+
/**
39+
* Customizer context. Must be providede if fieldId is set
40+
*/
41+
context?: IContext;
2542
}
2643

2744
/**
28-
* For future
45+
* Field Lookup Renderer State
2946
*/
3047
export interface IFieldLookupRendererState {
3148
hideDialog?: boolean;
3249
lookupDispFormUrl?: string;
50+
dispFormUrl?: string;
3351
}
3452

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

5371
this.state = {
54-
hideDialog: true
72+
hideDialog: true,
73+
dispFormUrl: props.dispFormUrl
5574
};
5675
}
5776

@@ -61,23 +80,35 @@ export class FieldLookupRenderer extends React.Component<IFieldLookupRendererPro
6180
return <Link onClick={this._onClick.bind(this, lookup)} className={styles.lookup} style={this.props.cssProps}>{lookup.lookupValue}</Link>;
6281
});
6382
return (
64-
<div style={this.props.cssProps} className={css(this.props.className)}>{lookupLinks}
65-
{!this.state.hideDialog && <IFrameDialog
66-
url={this.state.lookupDispFormUrl}
67-
iframeOnLoad={this._onIframeLoaded.bind(this)}
68-
hidden={this.state.hideDialog}
69-
onDismiss={this._onDialogDismiss.bind(this)}
70-
modalProps={{
71-
isBlocking: true,
72-
containerClassName: styles.dialogContainer
73-
}}
74-
dialogContentProps={{
75-
type: DialogType.close,
76-
showCloseButton: true
77-
}}
78-
width={'570px'}
79-
height={'315px'}/>}
80-
</div>);
83+
<div style={this.props.cssProps} className={css(this.props.className)}>{lookupLinks}
84+
{!this.state.hideDialog && this.state.dispFormUrl && <IFrameDialog
85+
url={this.state.lookupDispFormUrl}
86+
iframeOnLoad={this._onIframeLoaded.bind(this)}
87+
hidden={this.state.hideDialog}
88+
onDismiss={this._onDialogDismiss.bind(this)}
89+
modalProps={{
90+
isBlocking: true,
91+
containerClassName: styles.dialogContainer
92+
}}
93+
dialogContentProps={{
94+
type: DialogType.close,
95+
showCloseButton: true
96+
}}
97+
width={'570px'}
98+
height={'315px'} />}
99+
{!this.state.hideDialog && !this.state.dispFormUrl && <Dialog
100+
onDismiss={this._onDialogDismiss.bind(this)}
101+
modalProps={{
102+
isBlocking: true,
103+
containerClassName: styles.dialogContainer
104+
}}
105+
dialogContentProps={{
106+
type: DialogType.close,
107+
showCloseButton: true
108+
}}>
109+
<Spinner size={SpinnerSize.large} />
110+
</Dialog>}
111+
</div>);
81112
}
82113

83114
private _onClick(lookup: ISPFieldLookupValue): void {
@@ -92,10 +123,32 @@ export class FieldLookupRenderer extends React.Component<IFieldLookupRendererPro
92123
//
93124
// showing Display Form in the dialog
94125
//
95-
this.setState({
96-
lookupDispFormUrl: `${this.props.dispFormUrl}&ID=${lookup.lookupId}&RootFolder=*&IsDlg=1`,
97-
hideDialog: false
98-
});
126+
if (this.state.dispFormUrl) {
127+
this.setState({
128+
lookupDispFormUrl: `${this.state.dispFormUrl}&ID=${lookup.lookupId}&RootFolder=*&IsDlg=1`,
129+
hideDialog: false
130+
});
131+
}
132+
else if (this.props.fieldId) {
133+
134+
this.setState({
135+
hideDialog: false
136+
});
137+
138+
SPHelper.getLookupFieldListDispFormUrl(this.props.fieldId, this.props.context).then(dispFormUrlValue => {
139+
const dispFormUrl: string = dispFormUrlValue.toString();
140+
this.setState((prevState, props) => {
141+
if (prevState.hideDialog) {
142+
return;
143+
}
144+
145+
return {
146+
dispFormUrl: dispFormUrl,
147+
lookupDispFormUrl: `${dispFormUrl}&ID=${lookup.lookupId}&RootFolder=*&IsDlg=1`
148+
};
149+
});
150+
});
151+
}
99152
}
100153

101154
private _onIframeLoaded(iframe: any): void {

src/controls/iFrameDialog/IFrameDialog.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from "react";
22
import * as ReactDOM from "react-dom";
33
import { Dialog, IDialogProps } from 'office-ui-fabric-react';
4-
import IFrameDialogContent from './IFrameDialogContent';
4+
import { IFrameDialogContent } from './IFrameDialogContent';
55
import * as appInsights from '../../common/appInsights';
66

77
export interface IFrameDialogProps extends IDialogProps {
@@ -12,7 +12,7 @@ export interface IFrameDialogProps extends IDialogProps {
1212
/**
1313
* iframe's onload event handler
1414
*/
15-
iframeOnLoad?: (iframe: any) => {};
15+
iframeOnLoad?: (iframe: any) => void;
1616
/**
1717
* iframe width
1818
*/
@@ -29,7 +29,7 @@ export interface IFrameDialogState {
2929
/**
3030
* Dialog component to display content in iframe
3131
*/
32-
export default class IFrameDialog extends React.Component<IFrameDialogProps, IFrameDialogState> {
32+
export class IFrameDialog extends React.Component<IFrameDialogProps, IFrameDialogState> {
3333

3434
public constructor(props: IFrameDialogProps, state: IFrameDialogState) {
3535
super(props, state);

src/controls/iFrameDialog/IFrameDialogContent.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import styles from './IFrameDialogContent.module.scss';
66
export interface IIFrameDialogContentProps {
77
url: string;
88
close: () => void;
9-
iframeOnLoad?: (iframe: any) => {};
9+
iframeOnLoad?: (iframe: any) => void;
1010
width: string;
1111
height: string;
1212
}
1313

1414
/**
1515
* IFrame Dialog content
1616
*/
17-
export default class IFrameDialogContent extends React.Component<IIFrameDialogContentProps, {}> {
17+
export class IFrameDialogContent extends React.Component<IIFrameDialogContentProps, {}> {
1818
private _iframe: any;
1919

2020
constructor(props: IIFrameDialogContentProps) {

0 commit comments

Comments
 (0)