Version 4 Planning
Hello!
The PnPjs core team is discussing version 4 of PnPjs. No big changes planned for this go-round, just improvements and lots more coverage for Microsoft Graph.
We'd love to hear from all of you about your love/hate/wish was easier list in v3 to help guide our thinking for v4. The more detail you can share the better so we can understand your idea.
We setup a board so you can view our current thinking.
Please share your feedback as a comment below!
Thanks,
🐇🐇🐇 @bcameron1231, @juliemturner, @patrick-rodgers
Something that would be really cool! - a fluent way to write the filter query
So "title eq 'test'" becomes something like .filter(textField("title").equals("test")) - CamlJS does this awesomely for CAML!
Thanks for all the awesome work you all are doing! 🙌
Something that would be really cool! - a fluent way to write the filter query
So "title eq 'test'" becomes something like
.filter(textField("title").equals("test"))- CamlJS does this awesomely for CAML!Thanks for all the awesome work you all are doing! 🙌
I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...
I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...
Dates, booleans (do you write true/false or 1 and 0), lookups, maybe even things like "in date rage" - also to bring forward some of the lesser known options like startsWith
Loads of awesome potential, but maybe also a bigger undertaking 😊
I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...
Dates, booleans (do you write true/false or 1 and 0), lookups, maybe even things like "in date rage" - also to bring forward some of the lesser known options like startsWith
Loads of awesome potential, but maybe also a bigger undertaking 😊
I love this idea, and when it has come up in the past I've suggested it would be a great project for someone to undertake as a separate library. We can def take a look at it in our planning and see where it falls. Thanks for the suggestion!
Please allow getting and setting lists from any site collection the easy way you had it in version 2... The whole business of changing the context with:
export const getSP = (context?:WebPartContext ): SPFI => { if (_sp === null && context !== null) { _sp = spfi().using(SPFx({ pageContext: context.pageContext })); _context = context; } return _sp; };
Is cumbersome and in 3.18 causes bunch of TypeScript errors about not being null.
We like simple :-)
Please allow getting and setting lists from any site collection the easy way you had it in version 2... The whole business of changing the context with:
export const getSP = (context?:WebPartContext ): SPFI => { if (_sp === null && context !== null) { _sp = spfi().using(SPFx({ pageContext: context.pageContext })); _context = context; } return _sp; };Is cumbersome and in 3.18 causes bunch of TypeScript errors about not being null. We like simple :-)
@Ofer-Gal, I tend to just do
const sp = spfi().using(SPFx(this._Context));
const otherSite = spfi(<OtherSiteURL>).using(AssignFrom(sp.web));
Any reason that dosen't work for you? Gives me access to the current web, but also any other web the user has access to
That's a good one to share @Tanddant ... my preference is below which is the most similar to v2 method.
const web = Web([sp.web, {Other Web URL}]);
Here are all the options: https://pnp.github.io/pnpjs/getting-started/#connect-to-a-different-web
@Tanddant I use hooks so this._Context does not exist.
@juliemturner I tried:
const projWeb: IWeb = Web([sp.web, { window.location.origin + "/Teams/" + projectNumber}]);
but TypeScript says:
Argument of type '[any, { window: Window & typeof globalThis; "": string; }]' is not assignable to parameter of type 'SPInit'.
Type '[any, { window: Window & typeof globalThis; "": string; }]' is not assignable to type 'ISPQueryable
Where should sp come from?
@Ofer-Gal - The second paramater is a string, try:
const projWeb: IWeb = Web([sp.web, `${window.location.origin}/Teams/${projectNumber}`])
As for my solution, the context I'm referencing is the WebPartContext, I've just passed it to my provider class, that's available in the root of your Web Part as this.context, from the sample you have it would just be
const sp = spfi().using(SPFx(context));
const otherSite = spfi(<OtherSiteURL>).using(AssignFrom(sp.web));
Or with @juliemturner's admittedly more sleek approach
const sp = spfi().using(SPFx(context));
const OtherWeb = Web([sp.web, <OtherSiteURL>])
Works great thanks!
@juliemturner or @patrick-rodgers
Is anyone looking to the filter query builder? - I would love to collaborate on it, I have a starting point that work for the most basic things
- TextField
- equals
- not equals
- Number, Date
- equals
- not equals
- greater than
- greater than equals
- less than
- less that equals
But ideally I would love a second opinion, and maybe someone with more insights into PnPJS to be able to help out
@Tanddant - Yes, @bcameron1231 got quite a ways on it but as a team there are some things that weren't exactly the way we'd want them to be, I think Beau could go into more detail, but it was around nested filters I believe
Here's his PR WIP: https://github.com/pnp/pnpjs/pull/2781
Hey @Tanddant definitely take a look at the PR Julie linked.
It's a bit crude at the moment and needs work, but it's my first exploration at possibly using Lamba type expressions instead. While Camljs is great, I personally prefer the look of a lambda expressions rather than consecutive chaining -- from a readability perspective.
Inside that branch, you'll see what I've done to handle scenarios like Number/Date versus Text field, specifically in the fomatValue() method within spqueryable. The reason I opted for an internal check/conversion on types is to make it easier for the consumer of the library... so they don't have to think about field types.
I'm very open to improving this, and certainly open to alternatives all together.
Hi, I hope, its not completly off topic. I just come across limitation to query length. Query is limited to 160 characters.
- could be there an info about too long url? Happens usually with multiple filter conditions.
- automatically convert GET to POST with CAML format. I'm not sure it would be possible do that, but would be nice, right?
@m0jimo - I think there is some confusion. The URL length is certainly a thing but it's a different thing than the overall length. So, one of the common ways to work around the URL length is to use alias parameters and we support that (https://pnp.github.io/pnpjs/sp/alias-parameters/). The second option if you go over the ~2000 character length (different for different browsers) is to use CAML queries because that would be in the post body, but we would not do that conversion for you. We do however support you doing it with the renderListDataAsStream or the getItemsByCAMLQuery methods.
Thanks @juliemturner for provided links and ideas. I made a mistake in filter query which was not caused by its length. I'm aware of CAML support in PnpJs. I also found a parsers for OData filter, so I should be able to convert it to CAML myself in case it overcomes its length.
What about SharePoint alerts? We built our own custom document library UI web part using the files/folders PnP JS API but it doesn't have anything for alerts. We have a button on the page where they can manage alerts without having to use the backend SharePoint pages.
We had to create Azure functions which call the PnP PowerShell APIs to get/add/delete alerts. I wasn't sure if that's not possible to add to PnP JS or if it's just something that has never been added. It would be nice if we could get rid of all our Azure functions and be able to use PnP JS for that.
@kbeeveer46 - "Alerts" is a bit vague, I can think of 2 or 3 different things you might mean.
If you want to submit an enhancement request and give us details of what specific endpoints you're referencing we might be able to help but based on what you're describing it might be that the limitation is what you can do with delegated vs application level permissions. If the api endpoint was supported with delegated permissions then you wouldn't have to use an azure function... if you're using the azure function because that's how you're running PowerShell then if you can articulate what PowerShell commands you're referencing specifically I suspect you can do this already in the client side code, but maybe only with an extension method.
@juliemturner When you're in a document library in SharePoint there's a set of buttons at the top like upload, delete etc. There's also a button that lets you set up alerts if anything has been added/changed/deleted from the library. I put a screen shot below.
Is there a way to manage (add/edit/delete) these using PnP JS? In PnP PowerShell they have the following cmdlets. I created Azure Functions that are called via http requests that run these cmdlets and return a response since I am not aware of another way to add/edit/delete alerts. We are using SharePoint online as a client portal so we don't want to make our clients use the "backend" pages of SharePoint like in my screen shot below. We wrote a custom document library web part that has an alert manager inside of it that does the same thing as the backend pages but with a better UI.
https://pnp.github.io/powershell/cmdlets/Get-PnPAlert.html https://pnp.github.io/powershell/cmdlets/Add-PnPAlert.html https://pnp.github.io/powershell/cmdlets/Remove-PnPAlert.html
@juliemturner What's the opinion on "undocumented APIs"?
I've been reverse engineering the news API, now not quite sure what to do with that 😅 - if it doesn't fit here I'll do an SPFx sample on it instead, the API isn't officially documented, so it might change and break, but it seemingly hasn't changed for a few years
@Tanddant well that's a good question. We have in the past reverse engineered APIs (pages forex) and used them in the library, but that isn't the best path forward as things can change/break unexpectedly. Depending on the API we can weigh the pros/cons. In my job-job I have to say, don't do that. But wearing my PnPjs hat I understand that sometimes folks need to solve issues we haven't fully supported in the service yet and generally encourage finding ways to solve the customer need.
@patrick-rodgers
Here's my current work: https://github.com/Tanddant/pnpjs/tree/v4-ODataFilterQuery
export interface IDepartment {
Id: number;
Manager: IDepartment;
Alias: string;
HasSharedMailbox: boolean;
DepartmentNumber: number;
}
export interface IEmployee {
Id: number;
Age: number;
Firstname: string;
Lastname: string;
Employed: boolean;
Department: IDepartment;
DepartmentId: number
Manager: IEmployee;
Created: Date;
SecondaryDepartment: IDepartment[];
SecondaryDepartmentId: number[];
}
const r = await sp.web.lists.getByTitle("Employees").items.filter<IEmployee>(
Or(
And(
TextField("Firstname").Equals("Dan"),
TextField("Lastname").Contains("Tof"),
NumberField("Age").GreaterThan(25),
BooleanField("Employed").IsTrue(),
DateField("Created").IsBetween(new Date(2000, 1, 1), new Date(2024, 12, 31)),
TextField("Firstname").Equals("Dan"),
),
And(
TextField("Firstname").In(["Beau", "Bob", "Dan"]),
TextField("Lastname").Equals("Cameron"),
NumberField("Age").LessThan(35),
BooleanField("Employed").IsTrue(),
LookupField<IEmployee, IDepartment>("Department").TextField("Alias").Equals("Intern Management"),
),
)
)()
It works, but I can't start my code unless I comment out this stuff ^ - and then bring it back while running the code
There are some slightly coupled parts to nodejs that don't work in React Native due to mobile only view. While I can see it is possible with behaviours to do this maybe, I've yet to come across a sample of using things like React Native Fetch instead. I know work on the React Native Components is underway so I think this would be a nice round solution for React Native components, especially as you can now build React Native Apps via cli for Windows as well.
There are some slightly coupled parts to nodejs that don't work in React Native due to mobile only view. While I can see it is possible with behaviours to do this maybe, I've yet to come across a sample of using things like React Native Fetch instead. I know work on the React Native Components is underway so I think this would be a nice round solution for React Native components, especially as you can now build React Native Apps via cli for Windows as well.
We'd certainly welcome a community sample, but it's hard to support making samples for all the possible SDK/lang/framework variants in the world. If it has its own fetch API and it matches the browser's/node-fetch than the behavior should be trivial. You can use our node fetch behavior as an example.
Indeed, there needs to be some work first looking at v3 though, maybe to make custom behaviours easier or you remove shim dependencies as it's currently not compatible without changes to the core sadly
On Wed, 27 Mar 2024, 21:53 Patrick Rodgers, @.***> wrote:
There are some slightly coupled parts to nodejs that don't work in React Native due to mobile only view. While I can see it is possible with behaviours to do this maybe, I've yet to come across a sample of using things like React Native Fetch instead. I know work on the React Native Components is underway so I think this would be a nice round solution for React Native components, especially as you can now build React Native Apps via cli for Windows as well.
We'd certainly welcome a community sample, but it's hard to support making samples for all the possible SDK/lang/framework variants in the world. If it has its own fetch API and it matches the browser's/node-fetch than the behavior should be trivial. You can use our node fetch behavior as an example https://github.com/pnp/pnpjs/blob/version-4/packages/nodejs/behaviors/fetch.ts#L10 .
— Reply to this email directly, view it on GitHub https://github.com/pnp/pnpjs/issues/2678#issuecomment-2024214443, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABIQ5ACI6KXO2VNNLLKLL33Y2NSYDAVCNFSM6AAAAAAYCKC5FGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRUGIYTINBUGM . You are receiving this because you commented.Message ID: @.***>
@HughAJWood - I am unfamiliar with react native. If there are things in pnpjs that block it from working, please do open an issue and describe them so we can review and see if/what changes we can make to accomodate. With v4 coming soon it would be a good time to review.
I will do that, I'll do some discovery and testing and submit thanks
On Thu, 28 Mar 2024, 12:28 Patrick Rodgers, @.***> wrote:
@HughAJWood https://github.com/HughAJWood - I am unfamiliar with react native. If there are things in pnpjs that block it from working, please do open an issue and describe them so we can review and see if/what changes we can make to accomodate. With v4 coming soon it would be a good time to review.
— Reply to this email directly, view it on GitHub https://github.com/pnp/pnpjs/issues/2678#issuecomment-2025501170, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABIQ5AD62ISCYISJ72SBXUDY2QZLLAVCNFSM6AAAAAAYCKC5FGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRVGUYDCMJXGA . You are receiving this because you were mentioned.Message ID: @.***>
Thank you everyone for the great feedback and ideas for version 4. As we are getting close to launch I encourage everyone to try out the nightly builds for v4 and report any issues here in the list as normal. And of course please continue to share ideas on how we can continue to improve the library!
Thanks!
This issue is locked for inactivity or age. If you have a related issue please open a new issue and reference this one. Closed issues are not tracked.