Pnpjs: parentWeb endpoint missing

Created on 13 Apr 2018  路  10Comments  路  Source: pnp/pnpjs

Category

  • [*] Enhancement
  • [ ] Bug
  • [ ] Question
  • [ ] Documentation gap/issue

Version

Please specify what version of the library you are using: [1.0.4]

Expected / Desired Behavior / Question

ParentWeb is available as an endpoint on _api/web but not yet implemented in code

Observed Behavior

endpoint is missing from Web object

Is this endpoint slated to be added anytime soon?

If not, is it possible to use whatever http fetcher pnp uses under the hood to cheekily call web/parentWeb and cast the returned data into a pnp Web object?

code fixed enhancement

Most helpful comment

Hi @jimmywim,

Not an issue to add this enhancement. Actually, I already did it in a local branch and in a process of testing before PR.

Thanks for enhancement suggestion offer!

All 10 comments

Hi @jimmywim,

Not an issue to add this enhancement. Actually, I already did it in a local branch and in a process of testing before PR.

Thanks for enhancement suggestion offer!

After some tests:

ParentWeb endpoint is not the same as having an instance of the web.

And my initial idea of adding:

    /**
     * Gets this web's parent web
     *
     */
    public get parentWeb(): Web {
        return this.clone(Web, `parentWeb`);
    }

to Web class failed on deep testing.

Let me elaborate a bit on this.

My idea was to add sp.web.parentWeb returning an instance of Web. But parentWeb is just a set of properties and can't be chained with other usual endpoints. I.e. sp.web.parentWeb.lists will fail, sp.web.parentWeb.select('Url') won't return the prop.

In existing code base we can actually deal with parentWeb in the following way:

pnp.sp.web.select('ParentWeb').expand('ParentWeb').get().then(console.log);

So... I'm not sure, do we need parentWeb as an additional get method? Any thoughts?

That method appears to get some data about the parent Web but it's not of type Web in the code base, so doesn't have all the methods & properties on it (which is useful, and what I currently need as I'm in a recursive method trying to pull out Publishing's available page layouts - agreed that's not something to deal within Modern sites but the ability to get the full Web object for the parent might still be useful).

The object that comes back does have Id though, so we can use Site.openWebById() on it.

A web object can be constructed using const web = new Web([web absolute url]).
In most situations, I would use existing web URL and pop last path part out and build parent web object with full API support.

Or, as you said, site.openWebById is the case too:

(async () => {

  const { ParentWeb } = await pnp.sp.web.select('ParentWeb/Id').expand('ParentWeb').get();
  const { web: parentWeb } = await pnp.sp.site.openWebById(ParentWeb.Id);

  const lists = await parentWeb.lists.get();
  console.log(lists);

})()
  .catch(console.error)

Almost.

This is a now-working example I have for recursing webs (looking for a property bag value that isn't "__inherits":

async recurseWeb(web: Web): Promise<Web> {
    const bagOValues = await web.allProperties.get();
    if (bagOValues[SitePropertyBagFields.AVAILABLE_PAGE_LAYOUTS]) {
        const layoutsXml = bagOValues[SitePropertyBagFields.AVAILABLE_PAGE_LAYOUTS];
        if (layoutsXml === "__inherit") {
            const response = await web.select('ParentWeb').expand('ParentWeb').get();
            const parentWeb = await sp.site.openWebById(response.ParentWeb.Id);
            return this.recurseWeb(parentWeb.web);
        } else {
            // ... parse the xml and pull out the necessary data
        }
    }
}

Sorry, @jimmywim - did you mean "now" working or "not" working?

If there is no special functionality on that endpoint I am not sure we need to explicitly extend the Web object to include it. However if there is something we can support that will help, please let us know.

What about something like getParentWeb(): Promise<Web>?

Hi Patrick, I do mean "now" working - the same I pasted above works.

getParentWeb(): Promise<Web> is something that I feel would be useful, and the implementation would appear to simply be the two lines:

const response = await web.select('ParentWeb').expand('ParentWeb').get();
return sp.site.openWebById(response.ParentWeb.Id);

Maybe not for merging, but for a review of the helper. Please check the PR - the implementation of getParentWeb(): Promise<{ data: any; web: Web; }>. As openWebById returns Web object together with the data object, I keen on keeping both.

const { data, web: parentWeb } = await web.getParentWeb();

What do you think would it be helpful?

Yep, I think that'd be perfect.

Looks like this was merged, so closing issue. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SpliceVW picture SpliceVW  路  3Comments

simonagren picture simonagren  路  3Comments

SpliceVW picture SpliceVW  路  3Comments

Holden15 picture Holden15  路  3Comments

AJIXuMuK picture AJIXuMuK  路  3Comments