The wiring to do this is mostly there, but lightning apps don't have access to Sfdc.canvas
at present, it seems. If they did have access to Sfdc.canvas
then this would work.
You can send a message from the canvas app, and it will reach the containing window, but it seems there's no way to listen for it at present. You can also subscribe to events in the canvas app, and if you construct and post a correctly formatted message from the top window, the canvas app will receive it. Funnily enough, onCanvasSubscribed
will fire when the canvas app subscribes, but I cannot for the life of my figure out why it would, when it seems impossible to publish
a message from the lightning component.
So, in short, the answer to this is "it's not possible". The long answer is "it's a very bad idea, because you need to partially reimplement the canvas event messaging protocol, which exposes you to the risk that the unpublished, proprietary protocol will change, thus breaking your app without warning."
A note on access to Sfdc.canvas
The Salesforce Spring ’16 Release Notes state that Sfdc JavaScript Global Is Removed for lightning components, however:
The sole exception is the official Force.com Canvas API, which is available using the Sfdc.canvas object. Canvas APIs as documented in the Canvas Developer Guide remain available and are fully supported.
This seems to suggest that Sfdc.canvas
ought to be available to lightning components, and the fact that it appears to be unavailable could be considered a defect.
Warning: rest of this post covers non-standard, probably unsupported techniques
So, for posterity and those unmotivated by pragmatic programming practices, this is how you can send and receive messages from a canvas app within lightning.
Sending messages from canvas to lightning
Send a message as normal from the canvas app:
var srClient = signedRequest.client;
Sfdc.canvas.client.publish(
srClient,
{name : "mynamespace.statusChanged", payload : {status : 'Completed'}});
You ought to be able to listen for this message using:
Sfdc.canvas.parent.subscribe('mynamespace.statusChanged', callbackFn);
And indeed, if you run this in the javascript console, you can listen for these messages. If only lightning components had access to Sfdc.canvas
! Since we don't, the only way to receive this message in the lightning component is by listening for it directly on the window:
window.addEventListener('message', function (event) {
var data = JSON.parse(event.data);
if (data.targetModule === 'Canvas' &&
data.body &&
data.body.event &&
data.body.event.name === 'mynamespace.statusChanged')
console.log('payload from canvas app', data.body.event.payload);
}, false);
Sending messages from the lightning component to canvas app
We can subscribe to messages as normal in the canvas app:
var srClient = signedRequest.client;
Sfdc.canvas.client.subscribe(
srClient,
{
name : 'johnny.begood',
onData : function (event) {
console.log("Subscribed to custom event ", event);
}
});
// at this point, onCanvasSubscribed
in the lightning component seems to fire
It's very odd that onCanvasSubscribed
fires at this point. That seems pointless if there's no way official way to publish. Perhaps there is a way, but if there is, I haven't been able to find it.
Ideally, you'd be able to publish an event from the lightning app this way:
Sfdc.canvas.parent.publish('mynamespace.statusChanged', payload);
As with subscribing, this is not possible, but there is a workaround. From the lightning component, post a correctly formatted message to the outer wrapper iframe:
// canvas apps contain both an inner and outer iframe. The canvas app is
// in the inner iframe, but we post our message to the outer iframe
var outerIframe = document.querySelector('.forceCanvasApp iframe');
// we need the correct target URL for the outer iframe. hard-coding this
// is a Bad Idea. How to do it otherwise left as an exercise for the reader
// Hint: listen for the subscribe message via
// `window.addEventListener('message', listener)`
var wrapperUrl = 'https://my-domain.my.salesforce.com';
// to correctly format this message, you'll need to listen on the window
// for the canvas app subscribe message
// and extract the instance id
var instanceIdFromClientSubscribeMessage = '_:test01:6:0:canvasapp';
var payload = { whatever: 'you want' };
var wrappedPayload = {
parentVersion: '39.0',
clientVersion: '34.0',
body: {
type: 'event',
config: {
client: {
instanceId: instanceIdFromClientSubscribeMessage
}
},
event: {
name: 'johnny.begood',
method: 'onData',
payload: payload
}
}
}
outerIframe.contentWindow
.postMessage(JSON.stringify(wrappedPayload), wrapperUrl);
Best Answer
It really depends on your business Scenario of what you are trying to achieve and your UX approach and design decisions .If you want your users to completely align to standard lightning experience going lightning components route will benefit them in long term
If you are in ISV space ,then you want to try and use lightning component framework to provide end users(Your end users are other salesforce orgs where your apps are installed) flexibility to use the builders that salesforce out of box provides .
Building with React or Angular will imply admins or business consultants wont be able to configure or control the layout .Lets say you provide that ability then you are rebuilding the builders that salesforce has already built for you .
Salesforce is trying to provide a framework that does handle lot of things for you OOB .Lightning Action Services are great step towards that where salesforce will be providing a single tag that handles CRUD respecting org CRUD/FLS and sharing configurations.
In angular or React you are simply rebuilding lot of stuff that platform automatically gives in lightning component framework (Examples include Internationalisation , labels, Locale Date formats etc).
If you ask me as of today (22nd oct 2016) its lot better than how it was an year ago and its keep getting better and better .The base components ,Utility bars ,Quick actions , Lightning Out ,Added Interfaces all are pretty robust now to build a functional apps .While there are few gaps being a new technology with a learning curve and not much libraries available open source compatible its an extra pain which i am sure with time it will be sorted .So if you are thinking of future and planning to use salesforce wont be bad idea to go with lightning component framework and If you feel you are invested in SFDC for short term then frameworks like angular or react makes sense as that can be used with any other Technology Stack .