I have to post JSON object as data using javascript PostMessage method, below is the object that I would like to post:
{
"Type" : "Login"
}
I believe this method is used to between iframe implemented inside a website, the iframe source URL is different from the parent window, how do I implement it in code?
I have this sample code I used, but I don't understand how to it work and how can I test it. Appreciate if someone can help!!
Code:
#{
string jsonParameter = Newtonsoft.Json.JsonConvert.SerializeObject("Login");
}
var jsonData = "#Html.Raw(jsonParameter)";
parent.postMessage({ "Type": jsonData }, "*");
You are correct, PostMessage is used to send messages between ifames. The code you have given in your sample is intended to be used in a child iframe and it is sending a message to the parent iframe.
In the parent iframe You also need to listen for messages coming in, for example
window.addEventListener("message", (event) => {
console.log("Received data from child iframe ", event.data);
});
Assuming you are sending a static message, the code sample you have given that sends a message to the parent iframe can also be simplified as there is no need for the c#
parent.postMessage({ "Type": ""Login }, "*");
Please also note the second parameter to PostMessage should be an expected domain instead of "*" as it prevents malicious sites from intercepting messages. I would recomend reading the mdn page for more information https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Related
I have a Web based Training where we'd like to embed an MS-Form as an Iframe into a page and via Javascript would like to enable the next page when the user has submitted the form.
Is there any way possible to check if the MS-Form inside the iframe was submitted?
I tried by getting the iframe via an assigned ID, but it is not possible to access the iframes #document (security cross-origin reason) and for example check buttons.
Maybe there are some messages that can be posted to the contentWindow?
I've also seen, that there is no API that would support checking if I've already submitted a certain form. As far as I have seen it is only possible to access your own forms via API.
You can use the PostMessage api to listen/send events from and to the iframe.
https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/online/scenarios/postmessage
You can listen to events by adding this event listener after the iframe has loaded:
function handlePostMessage(e) {
// The actual message is contained in the data property of the event.
var msg = JSON.parse(e.data);
// The message ID is now a property of the message object.
var msgId = msg.MessageId;
// The message parameters themselves are in the Values
// parameter on the message object.
var msgData = msg.Values;
// Do something with the message here. }
window.addEventListener('message', handlePostMessage, false);
I want to pass data from my dynamic html table on button click event to model driven app account form in dynamic 365 crm. But I'm not be able to pass the data. Please refer the below java script function that I used to pass data.
function addAddress(event) {
var row = $(event);
var parent = row.parent();
parent = parent.parent();
window.parent.Xrm.Page.getAttribute("address1_line1").setValue(parent.closest("tr").find('td:eq(0)').text());
window.parent.Xrm.Page.getAttribute("address1_line2").setValue(parent.closest("tr").find('td:eq(1)').text());
window.parent.Xrm.Page.getAttribute("address1_line3").setValue(parent.closest("tr").find('td:eq(2)').text());
window.parent.Xrm.Page.getAttribute("address1_city").setValue(parent.closest("tr").find('td:eq(3)').text());
window.parent.Xrm.Page.getAttribute("address1_stateorprovince").setValue(parent.closest("tr").find('td:eq(4)').text());
window.parent.Xrm.Page.getAttribute("address1_country").setValue(parent.closest("tr").find('td:eq(6)').text());
}
One simple option is to refactor your code to use the postMessage() function. Once that button is clicked on your HTML WebResource, you can post a message that can be handled by the form which can take action based on that.
As an example, when X event is triggered on your HTML WebResource, the following code sends a message (you can format your object whatever you like) to the parent window (account form):
// Please change the targetOrigin parameter
window.parent.postMessage({ "line1": "value1", "line2": "value2"}, "*");
On your account form JS WebResource, the following code registers an event handler that will listen for your message and take action using the _formContext object which can be saved on the onLoad event (as a replacement of Xrm.Page which has been deprecated):
window.addEventListener('message', function (event) {
// Important. Only accept messages from trusted origins
if (event.origin === "XXX") {
var messageData = event.data;
_formContext.getAttribute("address1_line1").setValue(messageData.line1);
_formContext.getAttribute("address1_line2").setValue(messageData.line2);
}
});
It's important that you use the postMessage and addEventListener methods on the correct window object so if the above code doesn't work as is (I've just taken the Mozilla documentation code and changed it to fit your scenario) please review this, as you might need to change window.addEventListener to window.parent.addEventListener.
I have this working example of how to use POST and put the server-generated html in a new window:
const response = await this.axiosInstance.post(url, postData)
const htmlResponse = response.data
const newWindow = window.open()
newWindow.document.write(htmlResponse)
However I'm not sure if this is the best or even correct way to do it. I see a few warnings with this. I get a warning on the last line that newWindow is possibly 'null'. If switching to TypeScript I am also not sure the type of htmlResponse. I would assume Document, but write() only supports string, so it might be the correct classification.
Is there a better way to put the content of a post-request into a new window?
Update: The content-type is of type text/html; charset=UTF-8, not sure if it changes anything.
What you have there might be enough for your use case. One might recommend waiting for some form of a ready event before manipulating the DOM.
const newWindow = window.open();
newWindow.onload = (event, f, g, h) => newWindow.document.write('Do great things.');
A much better solution might be fetching actual data instead of an HTML string from the server, creating a template page to receive the data, and rendering a well-formatted page.
The Window.postMessage() API could be used to send data between parent and child windows. This is especially useful if you need to circumvent the Same-origin policy.
I have made several assumptions, and this suggestion might not work for your use case.
I am trying to have a function in an injected script which gets some paramaters and forwards them to the content script, which in turn forwards it to the background script. I have read Chrome extension - retrieving Gmail's original message, but applying that code does not work properly. I have the following code which is injected.
window.postToContentScript = function(cmd, payload) {
var obj = {"command": cmd, "data": payload};
console.error(obj);
document.dispatchEvent(new CustomEvent('MyCustomEvent', {
detail: obj,
}));
}
When called, it logs my passed parameters to the console (so that's not an issue..). In the content script, I have the following code:
document.addEventListener("MyCustomEvent", function(e) {
console.error(e);
})
I would guess that it should actually contain an object with properties command and data, however the detail property of the event is just null. I realize that one way of approaching this is to add e.g. a hidden textarea into the document, filling that and subsequently reading it from the content script. However, this hardly seems as elegant as appending details to an event..
Any thoughts?
There is a similar post Retrieving HTTP status code from loaded iframe with Javascript but the solution requires the server-side to return javascript calling a function within the iframe. Instead, I would simply like to check the HTTP status code of the iframe without having to call a function within the iframe itself since my app either returns the full site through HTML or the single object as JSON. Essentially I've been trying to implement a callback method which returns success|failure dependent upon the HTTP status code.
Currently I have uploadFrame.onLoad = function() { ... so far pretty empty ... } and I am unsure what to check for when looking for HTTP status codes. Up until now, I've mainly relied upon jQuery's $.ajax() to handle success|failure but would like to further understand the mechanics behind XHR calls and iframe use. Thanks ahead of time.
UPDATE
The solution I came up with using jQuery
form.submit(function() {
uploadFrame.load(function() {
//using eval because the return data is JSON
eval( '(' + uploadFrame[0].contentDocument.body.children[0].innerHTML + ')' );
//code goes here
});
});
I think the best solution is injecting <script> tag into your iframe <head> and insert your "detecting" javascript code there.
something like this:
$('#iframeHolderDivId').html($.get('myPage.php'));
$('#iframeHolderDivId iframe head').delay(1000).append($('<script/>').text('your js function to detect load status'));
Maybe it's not the best solution but I think it works