-
Notifications
You must be signed in to change notification settings - Fork 399
Folder picker does not works if outside of current site collection #1379
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
Comments
Ok, actually it works as expected if <FolderPicker context={context}
label={''}
siteAbsoluteUrl={defaultLibrary.siteAbsoluteUrl}
rootFolder={{
Name: defaultLibrary.name,
ServerRelativeUrl: decodeURIComponent(new URL(defaultLibrary.webUrl).pathname), // Get the server relative url, with spaces decoded
}}
onSelect={folder => {
setSelectedFolder({ ...folder });
}}
canCreateFolders
/> However, I think there's a hole in the documentation of the component which doesn't mention this prop. An earlier check could also be beneficial (by checkinf if rootFolder.ServerRelativeUrl starts with siteAbsoluteUrl for example). |
Hi @stevebeauge, I agree about the missing prop in the control's doc. Regarding the earlier check mentioned above, the thing is that the FolderPicker control is using the FolderExplorer one under the hood, which works with "current web" context by default and only outside when using the From my perspective, the |
Dealing with different kinds of url is sometimes painful. I wrote a utility package to use in my projects, that allows me to rationalize URL forms. Here are the relevant parts, if it can help: export const toServerRelativeUrl = (url: string): string => {
const fullUrl = new URL(url, document.location.href);
return decodeURIComponent(fullUrl.pathname); // decodeURIComponent is needed to decoded urls like %20 for spaces
};
export const toAbsoluteUrl = (url: string): string => {
const fullUrl = new URL(url, document.location.href);
return fullUrl.toString();
};
export const toWebRelativeUrl = (webUrl: string, objectUrl: string): string => {
const webUrlObj = new URL(webUrl, document.location.href);
const objectUrlObj = new URL(objectUrl, webUrlObj);
if (
!objectUrlObj
.toString()
.toLocaleLowerCase()
.startsWith(webUrlObj.toString().toLocaleLowerCase())
) {
throw new Error("Object url is not located inside the specified web");
}
const objServerRelativeUrl = decodeURIComponent(objectUrlObj.pathname);
const webServerRelativeUrl = decodeURIComponent(webUrlObj.pathname);
return trimStart(objServerRelativeUrl.replace(webServerRelativeUrl, ""), "/");
};
/**
* Trims a string from the beginning.
* @param input The input string.
* @param c The characters to trim (default is whitespace).
* @param ignoreCase Whether to ignore case when trimming (default is true).
* @returns The input string with leading characters removed.
*/
export const trimStart = (input: string, c = '\\s', ignoreCase = true): string => {
// Use a regular expression to match the specified characters at the beginning of the string,
// and remove them. The `ignoreCase` option controls whether the match is case-insensitive.
return input.replace(new RegExp(`^[${c}]+`, ignoreCase ? 'gi' : 'g'), '');
}; The trick is to let the standard URL type handle the different forms of URL as input and produce the desired form. This way, whenever I need to add sharepoint URL as props of my component, I don't have to force the user to think about which kind of URL is required. ex: describe("urlUtils", () => {
test("toWebRelativeUrl absolute + absolute", () => {
assert.equal(
urlUtils.toWebRelativeUrl(
"https://contoso.sharepoint.com/sites/site1",
"https://contoso.sharepoint.com/sites/site1/Shared documents",
),
"Shared documents",
);
});
test("toWebRelativeUrl absolute + absolute / leading slash", () => {
assert.equal(
urlUtils.toWebRelativeUrl(
"https://contoso.sharepoint.com/sites/site1/",
"https://contoso.sharepoint.com/sites/site1/Shared documents",
),
"Shared documents",
);
});
test("toWebRelativeUrl relative + absolute", () => {
assert.equal(
urlUtils.toWebRelativeUrl(
"/sites/site1",
"https://contoso.sharepoint.com/sites/site1/Shared documents",
),
"Shared documents",
);
});
test("toWebRelativeUrl relative + absolute / leading slash", () => {
assert.equal(
urlUtils.toWebRelativeUrl(
"/sites/site1/",
"https://contoso.sharepoint.com/sites/site1/Shared documents",
),
"Shared documents",
);
});
test("toWebRelativeUrl absolute + relative", () => {
assert.equal(
urlUtils.toWebRelativeUrl(
"https://contoso.sharepoint.com/sites/site1",
"/sites/site1/Shared documents",
),
"Shared documents",
);
});
test("toWebRelativeUrl absolute + relative / leading slash", () => {
assert.equal(
urlUtils.toWebRelativeUrl(
"https://contoso.sharepoint.com/sites/site1/",
"/sites/site1/Shared documents",
),
"Shared documents",
);
});
test("toWebRelativeUrl relative + relative", () => {
assert.equal(
urlUtils.toWebRelativeUrl(
"/sites/site1",
"/sites/site1/Shared documents",
),
"Shared documents",
);
});
test("toWebRelativeUrl relative + relative / leading slash", () => {
assert.equal(
urlUtils.toWebRelativeUrl(
"/sites/site1/",
"/sites/site1/Shared documents",
),
"Shared documents",
);
});
test("toWebRelativeUrl absolute + absolute / different site", () => {
expect(() =>
urlUtils.toWebRelativeUrl(
"https://contoso.sharepoint.com/sites/site1",
"https://contoso.sharepoint.com/sites/site2/Shared documents",
),
).toThrowError();
});
}); Feel free to reuse it. |
Definitely missing in documentation, thanks @stevebeauge for spotting it. Would you be interested in submitting a PR? |
You mean a PR for improving the docs or a PR to add the url utility ? Or both ? |
@stevebeauge I was referring to the docs for |
Done: #1658. |
Category
[ ] Enhancement
[X] Bug
[ ] Question
Version
Please specify what version of the library you are using: [ 3.12.0 ]
Expected / Desired Behavior / Question
The folder picker should allow setting the
rootFolder
to any location the current has permission to access.Observed Behavior
If the

rootFolder
is set to a folder in another site collection, the picker is empty and the new folder action fails :When the "Select folder" icon is click the dev console emits :
The failing network request is:
And its result is:
My Analysis
Looking at the failing request, we can see the
getFolderByServerRelativePath
method is called onto the current page's web. Not the web targeted by the root folder, which is required.Steps to Reproduce
Create a webpart which use FolderPicker and point to a folder outside the current site collection.
My repro code (I can push the full project if needed):
The text was updated successfully, but these errors were encountered: