As SharePoint developers very well know, data can be shared between web part using SharePoint 2010 using standardized set of interfaces called connection interfaces that allowed Web Parts to exchange information with each other at run time.
More info on creating a Connectable Web Part can be found here
In the new SharePoint App model, web parts are replaced with app parts. The problem is they don’t have an equivalent to Web Part Connections. So how can you pass parameters from one part to another?
To answer this you have to consider several things:
1. App parts are basically small applications that are presented in your SharePoint site through Iframes
2. Each app is running in a separate domain and so are their app parts. Because of this any direct manipulation through some JavaScript code is out of the question because it would mean cross-domain scripting and all you would get is an "access denied" message
Thankfully there is a solution for this that is provided through HTML5, post Message and Event Listener method.
http://msdn.microsoft.com/en-us/library/windows/apps/hh441295.aspx
http://msdn.microsoft.com/en-us/library/ie/ff975245(v=vs.85).aspx
These method provides a way for communicating between browsing contents in HTML documents.
To demonstrate this I will take one scenario i.e.
I will create two SharePoint Hosted AppPart using Visual Studio, First one is Sender App and second one is Receiver App
Both Apps having Client Web Part (Host Web) and List Definition with default data
SenderSHAppPart having List Employee Data
ReceiverSHAppPart having List Department Data
Fig 1.1
Create Sender SharePoint Hosted App using Visual Studio
Project Structure as per below Fig 1.2
Right Click on the Project and Add two new items: – Custom List name Employee Data and Client Web Part name SenderAppPart.
Fig1.2
Adding Default Data to List
Fig 1.3
Add HTML and Script to SenderAppPart.aspx
<script type="text/javascript">
'use strict';
function OnChange() {
var myindex = D1.selectedIndex
var SelValue = D1.options[myindex].text
var appMsg = {
SelValue: SelValue
}
;
window.parent.postMessage(appMsg, "*");
return true;
}
</script>
HTML
<div id="Success">
<select class="select" id="select-reviewer" name="D1" onchange='OnChange();'>
</select>
</div>
<div id="error">
</div>
Add Script file SendData.js to Script folder and refer it in SenderAppPart.aspx
'use strict';
var hostweburl;
var appweburl;
var employeeData;
// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model
$(document).ready(function () {
//Get the URI decoded URLs.
hostweburl =
decodeURIComponent(
getQueryStringParameter("SPHostUrl")
);
appweburl =
decodeURIComponent(
getQueryStringParameter("SPAppWebUrl")
);
// resources are in URLs in the form:
// web_url/_layouts/15/resource
var scriptbase = hostweburl + "/_layouts/15/";
// Load the js files and continue to the successHandler
$.getScript(scriptbase + "SP.Runtime.js",
function () {
$.getScript(scriptbase + "SP.js",
function () {
$.getScript(scriptbase + "SP.RequestExecutor.js", execCrossDomainRequest);
}
);
}
);
}
);
// This function prepares, loads, and then executes a SharePoint query to get the current users information
// Function to prepare and issue the request to get
// SharePoint data
function execCrossDomainRequest() {
// context: The ClientContext object provides access to
// the web and lists objects.
// factory: Initialize the factory object with the
// app web URL.
var context = new SP.ClientContext(appweburl);
var factory =
new SP.ProxyWebRequestExecutorFactory(
appweburl
);
context.set_webRequestExecutorFactory(factory);
//Get the web and list objects
// and prepare the query
var web = context.get_web();
var list = web.get_lists().getByTitle("EmployeeData");
var camlString =
"<View><ViewFields>" +
"<FieldRef Name='Title' />" +
"<FieldRef Name='DepartmentId' />" +
"</ViewFields></View>";
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml(camlString);
employeeData = list.getItems(camlQuery);
context.load(employeeData, "Include(Title , DepartmentId)");
//Execute the query with all the previous
// options and parameters
context.executeQueryAsync(
successHandler, errorHandler
);
}
// Function to handle the success event.
// Prints the data to the page.
function successHandler(data, req) {
var enumerator = employeeData.getEnumerator();
while (enumerator.moveNext()) {
var employeedetail = enumerator.get_current();
var departmentId = employeedetail.get_item("DepartmentId");
var employeeName = employeedetail.get_item("Title");
populateUsersDropDown(employeeName, departmentId);
}
}
function populateUsersDropDown(employeeName, departmentId) {
$('#select-reviewer').append("<option value='" + departmentId + "'>" +
employeeName + "</option>");
}
// Function to handle the error event.
// Prints the error message to the page.
function errorHandler(data, error, errorMessage) {
document.getElementById("error").innerText =
"Could not complete cross-domain call: " +
errorMessage;
}
// Function to retrieve a query string value.
// For production purposes you may want to use
// a library to handle the query string.
function getQueryStringParameter(paramToRetrieve) {
var params =
document.URL.split("?")[1].split("&");
var strParams = "";
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
Create Receiver SharePoint Hosted App using Visual Studio
Fig 1.4
Fig 1.5
Add div tags to Receiver App Part
<div id="divMessages" style="color:#f00"></div>
<div id="renderDepartment"></div>
Add Script file GetData.js to Script folder and refer it in ReceiverAppPart.aspx
'use strict';
var departmentId;
var hostweburl;
var appweburl;
var allDepartmentId;
// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model
$(document).ready(function () {
window.addEventListener("message", receiveMessageInApp, false);
function receiveMessageInApp(event) {
var divMsg = document.getElementById('divMessages');
departmentId = event.data;
//Get the URI decoded URLs.
hostweburl =
decodeURIComponent(
getQueryStringParameter("SPHostUrl")
);
appweburl =
decodeURIComponent(
getQueryStringParameter("SPAppWebUrl")
);
// resources are in URLs in the form:
// web_url/_layouts/15/resource
var scriptbase = hostweburl + "/_layouts/15/";
// Load the js files and continue to the successHandler
$.getScript(scriptbase + "SP.Runtime.js",
function () {
$.getScript(scriptbase + "SP.js",
function () {
$.getScript(scriptbase + "SP.RequestExecutor.js", execCrossDomainRequest);
}
);
}
);
}
}
);
// This function prepares, loads, and then executes a SharePoint query to get the current users information
// Function to prepare and issue the request to get
// SharePoint data
function execCrossDomainRequest() {
// context: The ClientContext object provides access to
// the web and lists objects.
// factory: Initialize the factory object with the
// app web URL.
var context = new SP.ClientContext(appweburl);
var factory =
new SP.ProxyWebRequestExecutorFactory(
appweburl
);
context.set_webRequestExecutorFactory(factory);
//Get the web and list objects
// and prepare the query
var web = context.get_web();
var list = web.get_lists().getByTitle("DepartmentData");
var camlString ="<View>" +
"<Query>" +
"<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>" + departmentId + "</Value></Eq></Where>" +
"</Query>" +
"<ViewFields>" +
"<FieldRef Name='Title' />" +
"<FieldRef Name='DepartmentName' />" +
"</ViewFields>" +
"</View>";
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml(camlString);
allDepartmentId = list.getItems(camlQuery);
context.load(allDepartmentId, "Include(Title , DepartmentName)");
//Execute the query with all the previous
// options and parameters
context.executeQueryAsync(
successHandler, errorHandler
);
}
// Function to handle the success event.
// Prints the data to the page.
function successHandler(data, req) {
var enumerator = allDepartmentId.getEnumerator();
while (enumerator.moveNext()) {
var department = enumerator.get_current();
var departmentTitle = department.get_item("Title");
var departmentDescription = department.get_item("DepartmentName");
divMessages.innerHTML = departmentDescription;
}
}
// Function to handle the error event.
// Prints the error message to the page.
function errorHandler(data, error, errorMessage) {
document.getElementById("renderDepartment").innerText =
"Could not complete cross-domain call: " +
errorMessage;
}
// Function to retrieve a query string value.
// For production purposes you may want to use
// a library to handle the query string.
function getQueryStringParameter(paramToRetrieve) {
var params =
document.URL.split("?")[1].split("&");
var strParams = "";
for (var i = 0; i
< params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
Deploy both the Apps and browse you share point Team site.
Create one new site page i.e. CreateConnection.aspx and browse and edit the page. Click on Add Web Part and select Script Editor Web Part
Add Script Editor WebPart
<script>
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event){
procesHello(event.data.msg);
}
function procesHello(msgData){
var iFrame = document.getElementsByTagName("iframe")[1];
iFrame.contentWindow.postMessage(msgData,"*");
}
</script>
Add AppPart i.e. Sender AppPart Title and Receiver AppPart Title.
Click on Stop editing with happy ending!!
Leave a comment