Skip to content

Commit ba78422

Browse files
Merge pull request pnp#1371 from ekapic/feature/listitempicker-support-listname
Feature/listitempicker support listname
2 parents b69aec0 + 9b8bf88 commit ba78422

File tree

7 files changed

+79
-14
lines changed

7 files changed

+79
-14
lines changed

docs/documentation/docs/controls/ComboBoxListItemPicker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ The `ComboBoxListItemPicker` control can be configured with the following proper
112112
| keyColumnInternalName | string | no | InternalName of column to use as the key for the selection. Must be a column with unique values. Default: Id |
113113
| webUrl | string | yes | Url to web hosting list |
114114
| spHttpClient | RequestClient | yes | Any implementation of PnPJS RequestClient |
115-
| listId | string | yes | Guid of the list. |
115+
| listId | string | yes | Guid or title of the list. |
116116
| onSelectItem | (items: any[]) => void | yes | Callback function which returns the selected items. |
117117
| className | string | no | ClassName for the picker. |
118118
| defaultSelectedItems | any[] | no | Initial items that have already been selected and should appear in the people picker. Support objects and Ids only |

docs/documentation/docs/controls/ListItemPicker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ The `ListItemPicker` control can be configured with the following properties:
5151
| columnInternalName | string | yes | InternalName of column to search and get values. |
5252
| keyColumnInternalName | string | no | InternalName of column to use as the key for the selection. Must be a column with unique values. Default: Id |
5353
| context | BaseComponentContext | yes | SPFx web part or extention context |
54-
| listId | string | yes | Guid of the list. |
54+
| listId | string | yes | Guid or title of the list. |
5555
| itemLimit | number | yes | Number of items which can be selected |
5656
| onSelectItem | (items: any[]) => void | yes | Callback function which returns the selected items. |
5757
| className | string | no | ClassName for the picker. |

src/common/dal/ListItemRepository.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,22 @@ export class ListItemRepository {
4242
return Promise.reject(error);
4343
}
4444
}
45+
46+
public async getListId(
47+
listName: string,
48+
webUrl?: string,
49+
): Promise<string> {
50+
51+
const webAbsoluteUrl = !webUrl ? this.SiteUrl : webUrl;
52+
const apiUrl = `${webAbsoluteUrl}/_api/web/lists/getByTitle(@listName)/Id?@listName='${encodeURIComponent(listName)}'`;
53+
const data = await this.SPClient.get(apiUrl, SPHttpClient.configurations.v1);
54+
if (data.ok) {
55+
const results = await data.json();
56+
if (results) {
57+
return results.value;
58+
}
59+
}
60+
61+
return;
62+
}
4563
}

src/controls/listItemPicker/ComboBoxListItemPicker.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ListItemRepository } from '../../common/dal/ListItemRepository';
88
import styles from './ComboBoxListItemPicker.module.scss';
99
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
1010
import { cloneDeep, isEqual } from 'lodash';
11+
import { Guid } from '@microsoft/sp-core-library';
1112

1213

1314
export class ComboBoxListItemPicker extends React.Component<IComboBoxListItemPickerProps, IComboBoxListItemPickerState> {
@@ -26,6 +27,7 @@ export class ComboBoxListItemPicker extends React.Component<IComboBoxListItemPic
2627
errorMessage: "",
2728
suggestionsHeaderText: !this.props.suggestionsHeaderText ? strings.ListItemPickerSelectValue : this.props.suggestionsHeaderText,
2829
selectedItems: this.props.defaultSelectedItems || [],
30+
safeListId: this.props.listId,
2931
};
3032

3133
// Get SPService Factory
@@ -34,26 +36,37 @@ export class ComboBoxListItemPicker extends React.Component<IComboBoxListItemPic
3436
}
3537

3638
public componentDidMount(): void {
37-
this.loadOptions(this.props).then(() => { /* no-op; */}).catch(() => { /* no-op; */});
39+
if(!Guid.tryParse(this.props.listId)) {
40+
this._listItemRepo.getListId(this.props.listId)
41+
.then((value) => {
42+
this.setState({...this.state,
43+
safeListId: value });
44+
this.loadOptions(this.props).then(() => { /* no-op; */}).catch(() => { /* no-op; */});
45+
})
46+
.catch(() => { /* no-op; */ });
47+
} else {
48+
this.loadOptions(this.props).then(() => { /* no-op; */}).catch(() => { /* no-op; */});
49+
}
3850
}
3951

4052
protected async loadOptions(props: IComboBoxListItemPickerProps, isInitialLoad?: boolean): Promise<void> {
4153
const {
4254
filter,
43-
keyColumnInternalName,
4455
listId,
56+
keyColumnInternalName,
4557
columnInternalName,
4658
webUrl,
4759
itemLimit,
4860
onInitialized,
4961
orderBy
5062
} = props;
63+
const { safeListId } = this.state;
5164
const query = filter || "";
5265
const keyColumnName = keyColumnInternalName || "Id";
5366

5467
if (!this._options || listId !== this.props.listId|| filter !== this.props.filter) {
5568
const listItems = await this._listItemRepo.getListItemsByFilterClause(query,
56-
listId,
69+
safeListId,
5770
columnInternalName,
5871
keyColumnInternalName,
5972
webUrl,

src/controls/listItemPicker/IListItemPickerState.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export interface IListItemPickerState {
77
suggestionsHeaderText:string;
88
selectedItems?: any[]; // eslint-disable-line @typescript-eslint/no-explicit-any
99
field?: ISPField;
10+
safeListId: string;
1011
}

src/controls/listItemPicker/ListItemPicker.tsx

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as telemetry from '../../common/telemetry';
1010
import isEqual from 'lodash/isEqual';
1111
import { ITag } from 'office-ui-fabric-react/lib/components/pickers/TagPicker/TagPicker.types';
1212
import { SPHelper } from '../../common/utilities/SPHelper';
13-
13+
import { Guid } from "@microsoft/sp-core-library"
1414

1515
export class ListItemPicker extends React.Component<IListItemPickerProps, IListItemPickerState> {
1616
private _spservice: SPservice;
@@ -27,17 +27,33 @@ export class ListItemPicker extends React.Component<IListItemPickerProps, IListI
2727
showError: false,
2828
errorMessage: "",
2929
suggestionsHeaderText: !this.props.suggestionsHeaderText ? strings.ListItemPickerSelectValue : this.props.suggestionsHeaderText,
30-
selectedItems: props.defaultSelectedItems || []
30+
selectedItems: props.defaultSelectedItems || [],
31+
safeListId: props.listId,
3132
};
3233

3334
// Get SPService Factory
3435
this._spservice = new SPservice(this.props.context);
3536
}
3637

37-
public componentDidMount(): void {
38+
private ensureLoadField(): void {
3839
this.loadField(this.props).then(() => { /* no-op; */ }).catch(() => { /* no-op; */ });
3940
}
4041

42+
public componentDidMount(): void {
43+
// Ensure list ID if a list name is passed in listId parameter
44+
if(!Guid.tryParse(this.props.listId)) {
45+
this._spservice.getListId(this.props.listId)
46+
.then((value) => {
47+
this.setState({...this.state,
48+
safeListId: value });
49+
this.ensureLoadField();
50+
})
51+
.catch(() => { /* no-op; */ });
52+
} else {
53+
this.ensureLoadField();
54+
}
55+
}
56+
4157
public UNSAFE_componentWillReceiveProps(nextProps: IListItemPickerProps): void {
4258
let newSelectedItems: any[] | undefined; // eslint-disable-line @typescript-eslint/no-explicit-any
4359
if (this.props.listId !== nextProps.listId) {
@@ -54,8 +70,8 @@ export class ListItemPicker extends React.Component<IListItemPickerProps, IListI
5470
if (this.props.listId !== nextProps.listId
5571
|| this.props.columnInternalName !== nextProps.columnInternalName
5672
|| this.props.webUrl !== nextProps.webUrl) {
57-
this.loadField(nextProps).then(() => { /* no-op; */ }).catch(() => { /* no-op; */ });
58-
}
73+
this.ensureLoadField();
74+
}
5975
}
6076

6177
/**
@@ -158,15 +174,15 @@ export class ListItemPicker extends React.Component<IListItemPickerProps, IListI
158174
* Function to load List Items
159175
*/
160176
private loadListItems = async (filterText: string): Promise<{ key: string; name: string }[]> => {
161-
const { listId, columnInternalName, keyColumnInternalName, webUrl, filter, orderBy, substringSearch } = this.props;
177+
const { columnInternalName, keyColumnInternalName, webUrl, filter, orderBy, substringSearch } = this.props;
162178
const {
163-
field
179+
field, safeListId
164180
} = this.state;
165181
const arrayItems: { key: string; name: string }[] = [];
166182
const keyColumn: string = keyColumnInternalName || 'Id';
167183

168184
try {
169-
const listItems = await this._spservice.getListItems(filterText, listId, columnInternalName, field, keyColumn, webUrl, filter, substringSearch, orderBy ? orderBy : ''); // JJ - 20200613 - find by substring as an option
185+
const listItems = await this._spservice.getListItems(filterText, safeListId, columnInternalName, field, keyColumn, webUrl, filter, substringSearch, orderBy ? orderBy : ''); // JJ - 20200613 - find by substring as an option
170186
// Check if the list had items
171187
if (listItems.length > 0) {
172188
for (const item of listItems) {
@@ -190,7 +206,7 @@ export class ListItemPicker extends React.Component<IListItemPickerProps, IListI
190206
field: undefined
191207
});
192208

193-
const field = await this._spservice.getField(props.listId, props.columnInternalName, props.webUrl);
209+
const field = await this._spservice.getField(this.state.safeListId, props.columnInternalName, props.webUrl);
194210

195211
this.setState({
196212
field

src/services/SPService.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,23 @@ export default class SPService implements ISPService {
190190
}
191191
}
192192

193+
public async getListId(
194+
listName: string,
195+
): Promise<string> {
196+
197+
const webAbsoluteUrl = this._webAbsoluteUrl
198+
const apiUrl = `${webAbsoluteUrl}/_api/web/lists/getByTitle(@listName)/Id?@listName='${encodeURIComponent(listName)}'`;
199+
const data = await this._context.spHttpClient.get(apiUrl, SPHttpClient.configurations.v1);
200+
if (data.ok) {
201+
const results = await data.json();
202+
if (results) {
203+
return results.value;
204+
}
205+
}
206+
207+
return;
208+
}
209+
193210
/**
194211
* Get List Items
195212
*/

0 commit comments

Comments
 (0)