Consume Lookup Multi Select Fields SPFx with Models and Hooks
April 4, 2024First when you set up lookup columns in a list or library, Microsoft restricts you to 12 columns of that type in a single view. The reason behind this limitation is that lookup columns retrieve data from another list or source. If you surpass this limit and try to add a 13th column, you’ll encounter an error message. It seems that 13 isn’t a lucky number in this case!
But if for your use case makes sense, here it is a solutions using the SharePoint Framework SPFx, not to bypass but use.
See my previous posts about Models and Hooks
Use Models
/* Model to MAP */
export interface IMyModelToMap {
MyId: number;
MyText: string;
MyMultiSelectLookup: IMylMultiSelectResponse[];
}
/* IMyMainResponse Response */
export interface IMyMainResponse {
Id: number;
Title: string;
MyMultiSelectLookup: IMylMultiSelectResponse[];
}
/* IMylMultiSelectResponse Response */
export interface IMylMultiSelectResponse {
Id: number;
Title: string;
}
Your Custom Hook
import { Logger, LogLevel } from "@pnp/logging";
import { spfi, SPFI } from "@pnp/sp";
import { useEffect, useState } from "react";
// Interfaces
import { IMyMainResponse, IMyModelToMap } from "../interfaces/MyModel"
//pnpjs
import { getSP } from "../pnpjsConfig";
import { Caching } from "@pnp/queryable";
const useTranings = () => {
const LOG_SOURCE = "PnPLog";
const LIBRARY_NAME = "Your List Name"
const [myItems, setMyItems] = useState<IMyModelToMap[]>([]);
const [isError, setError] = useState<boolean>(false);
const _sp: SPFI = getSP();
//Side Effect
useEffect(() => {
(async () => {
try {
const spCache = spfi(_sp).using(Caching({ store: "session" }))
const response: IMyMainResponse[] = await spCache.web.lists
.getByTitle(LIBRARY_NAME)
.items.select("Id",
"Title",
"MyMultiSelectLookup/Id",
"MyMultiSelectLookup/Title")
.expand("MyMultiSelectLookup")();
const items: IMyModelToMap[] = response.map((item: IMyMainResponse) => {
return {
MyId: item.Id || 0,
MyText: item.Title || "undefined",
MyMultiSelectLookup: item.MyMultiSelectLookup || []
};
});
setMyItems(items);
} catch (err) {
console.log(err);
setError(true);
Logger.write(
`${LOG_SOURCE} (getting files useEffect setMyItems) - ${JSON.stringify(err)} - `, LogLevel.Error
);
}
})();
}, []);
return [myItems, isError] as const
}
export default useYourCustomHook
Our React Control
//* Omitted for abbreviation */
//Custom Hook
import useYourCustomHook from '../../../hooks/useYourCustomHook';
const YourControl: React.FC<IYourControlProps> = (props) => {
const {
hasTeamsContext
} = props;
const [myItems, isError] = useYourCustomHook();
<section className={`${styles.mainProgress} ${hasTeamsContext ? styles.teams : ''}`}>
if (!isError) {
return (
{myItems.map((tr, idx) => {
return (
console.log(tr)
console.log(tr.MyText)
<>
{tr.MyMultiSelectLookup.map((it) => {
return (
console.log(it)
console.log(it.Title)
)
})}
</>
);
})}
</section>
</>
);
} else {
return <p>Error</p>;
}
}
export default YourControl
Hope that helps you