How to pass data from html web resource to dynamics 365 ce - javascript

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.

Related

Javascript Check if MS Form in Iframe was submitted

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);

Javascript PostMessage with JSON object as data

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

How to respond to an event after loading a hyperlink page?

I wonder is it possible to respond to an event after the client click the hyperlink and the hyperlink is loaded? Which that event can use properties in the hyperlink(i.e. id, class...etc)?
For example, page_A have a hyperlink
link
But since some_func need to use some properties in page_B, let say page_B have this line
<p id="a">hello world</p>
and some_func want to do something with it(e.g. document.getElementById("a")), how can I first load the hyperlink(page_B) then run some_func?
You could use the localStorage to save the name of the function that you want to execute on the second page, and call it once it loads.
The code would be like this:
JS
// a sample function to be called
function myFunc() {
alert("Called from previous page!");
}
// save the name of the function in the local storage
function saveForLater(func) {
localStorage.setItem("func", func);
}
// if the function exists
if (localStorage.func) {
// call it (not using the evil eval)
window[localStorage.func]();
// remove it from the storage so the next page doesn't execute it
localStorage.removeItem("func");
}
HTML (just for testing)
Go to Page 2<br/>
Go to Page 2 (not saving function)
Notice: as this code runs on the client's side, it is subject to be changed by the user, so you must be careful on how to proceed and execute the "saved" function, or you may find yourself with a security problem.

CRM and iframe aspx page form submission

Scenario :
I have aspx page which I need to Iframe on CRM's Opportunity form. This aspx page has form which submits data into the other database.
Requirement :
I would like when user clicks save button on CRM opportunity form ,aspx page should store the data in external database and opportunity form should also save all the changes on CRM form.
My Efforts :
Till now I have Iframed aspx page on CRM form.I am also submitting the form using OnSave event.
But the only problem is the form gets submitted but by the time it executes the complete code CRM form gets refreshed . End result is that Data on aspx page does not get stored in the external database.
What can be the other possible way to achieve this functionality ?
Thanks for taking time to read. Thank you in advance.
Option 1: The better solution is to do this from an opportunity post event plug-in. This ensures data consistency between CRM and external data (if required). Also you could use WCF or a web service to transmit the data to external DB.
Option 2: If you must use javascript you could (1) bind to opportunity form OnSave, (2) Prevent the form from submitting , (3) submit the iframe and (4) wait until it comes back and then (5) do another save to complete the action. This however might cause inconsistencies between CRM and external DB if opportunity save fails.
Here is a pseudo code example
function OpportunityOnLoad() {
IFRAME.OnReadyStateChange = function() {
// (4) Check success if possible
// (5) unbind save event and complete the opportunity save
Form.RemoveOnSave(OpportunityOnSave)
Form.Save();
}
//OnLoad
Form.AddOnSave (OpportunityOnSave);
}
function OpportunityOnSave(context) {
//(1) Save clicked
//(2) Stop save
context.PreventDefault();
//(3) Submit iframe form
IFRAME.Submit();
}
EDIT:
Regarding Q1 : unfortunately not.
Regarding Q2 :
This is a rough translation of the concept above into Javascript and CRM client side API.
I didn’t test it but it should put you on the right track.
Change the Params to match the iframe id, url etc.
also since you’re using an aspx you might experience cross domain issue that could be easily overcome if you’re browsing IE and not so easily overcome if you’re using CROME for example.
var IFRAME, SaveMode;
var FORM = Xrm.Page.data.entity;
var UI = Xrm.Page.ui;
var SaveModes = {
1 : "save",
2 : "saveandclose",
59: "saveandnew"
}
var Params = {
IframeBaseUrl : "",
IframeId : "IFRAME_test",
IframeFormId : "form1"
}
function OpportunityOnLoad() {
var sUrlparams = "?"; //add required params after ?
var IframeUrl = Params.IframeBaseUrl + sUrlParams;
IFRAME = UI.controls.get(Params.IframeId);
IFRAME.setSrc(IframeUrl);
IFRAME.Dom = document.getElementById(Params.IframeId);
IFRAME.add_readyStateComplete(OnAfterIfameSave);
FORM.addOnSave(OpportunityOnSave);
}
function OnAfterIfameSave() {
//SubmitSuccess indicates that the form has reloaded after a
//successful submit. You'll need to set this variable inside your iframe.
if (IFRAME.contentWindow.SubmitSuccess) {
FORM.removeOnSave(OpportunityOnSave);
FORM.save(SaveModes[SaveMode]);
}
}
function OpportunityOnSave(execObj) {
var evArgs = execObj.getEventArgs();
evArgs.preventDefault();
SaveMode = evArgs.getSaveMode();
IFRAME.contentWindow.document
.getElementById(Params.IframeFormId)
.Submit();
}

Javascript form submission to activate Spring Web Flow transitions with JSF integration

I`m developing an application using Spring WebFlow 2, Facelets and JSF. One of my flows does have a page that must trigger a form submit at certain events. For each different action, a different view must be presented. So, I'm trying to activate the following javascript code to perform the submission:
function myFormSubmit( eventId ) {
var formAction = document.myForm.action;
document.myForm.action = formAction + '&_eventId=' + eventId;
document.myForm.submit();
}
Unfortunatelly, this doesn't triggers the requested transition in my flow. The page doesn't change. Does anyone knows how to deal with this?
Thanks,
Alexandre
Don't know anything about SringFaceletsSF, but I think that event handler should probably return true. Otherwise your browser will not submit the form.
so:
function myFormSubmit( eventId ) {
var formAction = document.myForm.action;
document.myForm.action = formAction + '&_eventId=' + eventId;
document.myForm.submit();
return true;
}
On closer inspection, there are a bunch of problems with this code.
document.myForm.action is a non-standard way of getting elements. The better, cross-browser way is:
document.getElementById('myFormId');
Blindly appending an ampersand to the form action URL assumes that there is already another url parameter, and so there is already a question mark after the URL. If this is not the case the following line breaks:
document.myForm.action = formAction + '&_eventId=' + eventId;
Lastly, if you are calling this function as an onsubmit handler, I believe you should just return true, and not call the myForm.submit() method
I've got the solution in the Spring WebFlow forum. According to Jeremy Grelle, the submission of "_eventId" parameter does not trigger transitions when integrating Spring WebFlow to JSF. The solution he gave was to create a JSF PhaseListener that creates a JSF action when an "_eventId" parameter is sent.
The phaseListener code can be seen at http://forum.springsource.org/showthread.php?p=219358#post219358.
Modifying form.action is a very poor way of adding information to a form submission. I suggest putting a hidden input in your form that you can populate with your eventID.
Are you looking for this parameter in your GET params or your POST params? It won't appear in the POST.
Update:
ok,so to illustrate, try this...
change your function to do this:
function myFormSubmit( eventId ) {
var formAction = document.myForm.action;
//document.myForm.action = formAction + '&_eventId=' + eventId;
var myAction = document.createElement('input');
myAction.setAttribute('name', '_eventId');
myAction.setAttribute('type', 'hidden');
myAction.setAttribute('value', eventId);
document.myForm.appendChild(myAction);
document.myForm.submit();
}
Test in any (non-IE)* browser and see if it works. If so, the GET vs. POST param is the issue.
* non-IE: trying to set the name or type in IE will FAIL, thus don't test there.
Is there any reason you can't use the Spring Faces components which come with SWF? There's an ajaxEvent tag you can use to wrap elements. It activates on given javascript events (onclick, onchange) and invokes an action of your choice.

Categories

Resources