Forum Discussion
Changing a Page Banner Image inside a Modern Page using PnP
- Sep 01, 2017
My initial Regular Expression works only when banner is not set. So it will not work for the pages with banner.
Below is the code to process any pages:
var ctx = SP.ClientContext.get_current(); // SP context var web = ctx.get_web(); // current web var list = web.get_lists().getByTitle('Site Pages'); // pages library var items = list.getItems(SP.CamlQuery.createAllItemsQuery()); // all items ctx.load(items); // loading items from server... ctx.executeQueryAsync(function() { var item = items.get_item(7); // here I'm working with single item by index. But you can iterate through all pages here var layoutWebpartsContent = item.get_item('LayoutWebpartsContent'); // getting content console.log(layoutWebpartsContent); // let's display the content var dataAttrContent = /data-sp-controldata="([^"]+)"/gmi.exec(layoutWebpartsContent); // getting data-sp-controldata content if (dataAttrContent.length) { // we found the attribute. // Let's unescape and parse it to JSON // the content of the attribute is a 'group' in RegExp result. It will be located as second entry (with index 1) var unescaped = unescape(dataAttrContent[1]) // unescape //unescaped = unescape(unescaped); var content = JSON.parse(unescaped.replace(/:/gmi, ':')); // replace : with : // // changing imageSource // if (!content.serverProcessedContent) { content.serverProcessedContent = {}; } if (!content.serverProcessedContent.imageSources) { content.serverProcessedContent.imageSources = {}; } content.serverProcessedContent.imageSources.imageSource = '/sites/documents-aggregator/SiteAssets/SitePages/1200px-MarvelLogo.svg.png'; // // Changing imageSourceType // if (!content.properties) { content.properties = {}; } content.properties.imageSourceType = 2; // // escaping back and updating item // debugger; var newContent = JSON.stringify(content); newContent = escape(newContent); // escaping newContent = newContent.replace(/%3A/gmi, ':').replace(/%2C/gmi, ','); // we need to replace %3A (:) with : and %2C (,) with , layoutWebpartsContent = layoutWebpartsContent.replace(dataAttrContent[1], newContent); item.set_item('LayoutWebpartsContent', layoutWebpartsContent); item.update(); ctx.executeQueryAsync(function() { console.log('success'); }, function() { console.log('fail'); }); } });
Here is a code in JavaScript (JSOM).
First, let's say you've added some picture that should be used on the page. For example, to Site Assets.
Then, you can run next code:
var ctx = SP.ClientContext.get_current(); // current context var web = ctx.get_web(); // current web var list = web.get_lists().getByTitle('Site Pages'); // getting Site Pages library var items = list.getItems(SP.CamlQuery.createAllItemsQuery()); // all pages ctx.load(items); // loading items ctx.executeQueryAsync(function() { var item = items.get_item(6); // in my case I'll work with some page under index 6 // // LayoutWebpartsContent field contains settings for the page layout // var layoutWebpartsContent = item.get_item('LayoutWebpartsContent'); console.log(layoutWebpartsContent); // let's look at it // providing image source layoutWebpartsContent = layoutWebpartsContent.replace(/%22imageSources%22:%7B[^%7D]*%7D/gmi, '%22imageSources%22:%7B%22imageSource%22:%22server-relative-url-to-img-goes-here%22%7D'); // changing imageSourceType from 4 to 4 if needed layoutWebpartsContent = layoutWebpartsContent.replace(/%22imageSourceType%22:4/gmi, '%22imageSourceType%22:2'); // saving changes item.set_item('LayoutWebpartsContent', layoutWebpartsContent) item.update(); ctx.executeQueryAsync(); });
So, basically
- you can get a page as a list item
- change LayoutWebpartsContent property
- update list item
In LayoutWebpartsContent first thing to change is imageSource. It may be absent (for new created page) or contain server relative url to current page.
The second thing to change is imageSourceType. For new created page without image it's equal to 4 and we need to change it to 2.
Of course, it's more like a hack. But it works for your scenario.
- Aleksei TerentievSep 01, 2017Copper Contributor
My initial Regular Expression works only when banner is not set. So it will not work for the pages with banner.
Below is the code to process any pages:
var ctx = SP.ClientContext.get_current(); // SP context var web = ctx.get_web(); // current web var list = web.get_lists().getByTitle('Site Pages'); // pages library var items = list.getItems(SP.CamlQuery.createAllItemsQuery()); // all items ctx.load(items); // loading items from server... ctx.executeQueryAsync(function() { var item = items.get_item(7); // here I'm working with single item by index. But you can iterate through all pages here var layoutWebpartsContent = item.get_item('LayoutWebpartsContent'); // getting content console.log(layoutWebpartsContent); // let's display the content var dataAttrContent = /data-sp-controldata="([^"]+)"/gmi.exec(layoutWebpartsContent); // getting data-sp-controldata content if (dataAttrContent.length) { // we found the attribute. // Let's unescape and parse it to JSON // the content of the attribute is a 'group' in RegExp result. It will be located as second entry (with index 1) var unescaped = unescape(dataAttrContent[1]) // unescape //unescaped = unescape(unescaped); var content = JSON.parse(unescaped.replace(/:/gmi, ':')); // replace : with : // // changing imageSource // if (!content.serverProcessedContent) { content.serverProcessedContent = {}; } if (!content.serverProcessedContent.imageSources) { content.serverProcessedContent.imageSources = {}; } content.serverProcessedContent.imageSources.imageSource = '/sites/documents-aggregator/SiteAssets/SitePages/1200px-MarvelLogo.svg.png'; // // Changing imageSourceType // if (!content.properties) { content.properties = {}; } content.properties.imageSourceType = 2; // // escaping back and updating item // debugger; var newContent = JSON.stringify(content); newContent = escape(newContent); // escaping newContent = newContent.replace(/%3A/gmi, ':').replace(/%2C/gmi, ','); // we need to replace %3A (:) with : and %2C (,) with , layoutWebpartsContent = layoutWebpartsContent.replace(dataAttrContent[1], newContent); item.set_item('LayoutWebpartsContent', layoutWebpartsContent); item.update(); ctx.executeQueryAsync(function() { console.log('success'); }, function() { console.log('fail'); }); } });
- kevmcdonkSep 01, 2017MVPNot got my code handy but I believe you can set the bannerimageurl property on the page.