Display Fetch in IFRAME – Part 2
原始網址:http://mscrm4ever.blogspot.com/2009/03/display-fetch-in-iframe-part-2.html
不知什麽原因總是沒有辦法開啟,這是我通過台北才連上的.
所以備份一下.
My first post about displaying fetch inside an IFRAME has two disadvantages. The first is that the context of the parent window does not follow to the new entity window when you click on add new record (grid) button. This is might be annoying if you’re counting on the default mapping between the two entities. The second problem is that the grid does not refresh after you add (new button) or remove (delete button) a record. This means you are not able to see the changes unless you press on the grid refresh button your self.
I made piece with the fact that the parent context did not follow through to the child window since I was using advanced find. But the fact that the gird does not refresh automatically came as a surprise since I remember this feature working “AS IS” in v3.0. I guess ms did a few changes to the auto function which searched and refreshed the grid. Thanks to Dave Berry who commented / Posted about this and brought it to my attention.
In order to overcome this issue I added two new properties to the FetchViewer class.
The first parameter is called WithParentContext. This property allows you to decide whether the parent window object id is passed to the child window. I made it a public (as opposed to internal) choice since I figured you can display any type of query inside the FetchViewer including a query that does not reflect a direct parent child relationship.
The second parameter is the EntityCode (ObjectTypeCode) of the entity being fetched. If you want the grid to refresh automatically you must supply this value. This is important since the value is eventually passed to MS original auto function which expects this value.
The rest of the fetch viewer class was not changed and you can read all about it here.
function OnCrmPageLoad()
{
window.fetchContacts = new FetchViewer("IFRAME_test");
fetchContacts.WithParentContext = true;
fetchContacts.EntityCode = 2;
fetchContacts.FetchXml = getFetchXml();
fetchContacts.LayoutXml = getLayoutXml();
fetchContacts.Entity = "contact";
fetchContacts.QueryId = "{00000000-0000-0000-00AA-000000666400}";
fetchContacts.RegisterOnTab(0); //IFRAME ON THE FIRST TAB
}
function getFetchXml()
{
return '<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false"><entity name="contact"><attribute name="fullname"/><attribute name="telephone1"/><attribute name="contactid"/><order attribute="fullname" descending="false"/><filter type="and"><condition attribute="parentcustomerid" operator="eq" uitype="account" value="' + crmForm.ObjectId + '"/></filter></entity></fetch>';
}
function getLayoutXml()
{
return '<grid name="resultset" object="2" jump="lastname" select="1" icon="1" preview="1"><row name="result" id="contactid"><cell name="fullname" width="300" /><cell name="telephone1" width="125" /></row></grid>';
}
function FetchViewer( iframeId )
{
var Instance = this;
var vDynamicForm;
var m_iframeTab;
var m_iframeDoc;
var m_iframeShowModalDialogFunc = null;
var m_windowAutoFunc = null;
Instance.WithParentContext = false;
Instance.EntityCode = 0;
Instance.Entity = "";
Instance.Iframe = null;
Instance.FetchXml = "";
Instance.QueryId = "";
Instance.LayoutXml = "";
Instance.RegisterOnTab = function( tabIndex )
{
Instance.Iframe = document.getElementById( iframeId );
if( !Instance.Iframe )
{
return alert( "Iframe " + iframeId + " is undefined" );
}
m_iframeDoc = getIframeDocument();
var loadingGifHTML = "<table height='100%' width='100%' style='cursor:wait'>";
loadingGifHTML += "<tr>";
loadingGifHTML += "<td valign='middle' align='center'>";
loadingGifHTML += "<img alt='' src='/_imgs/AdvFind/progress.gif'/>";
loadingGifHTML += "<div/><b>Loading View
</b>";
loadingGifHTML += "</td></tr></table>";
m_iframeDoc.body.innerHTML = loadingGifHTML;
if( parseInt( "0" + tabIndex ) == 0 )
{
Instance.Refresh();
}
else
{
Instance.Iframe.attachEvent( "onreadystatechange" , RefreshOnReadyStateChange );
}
}
function RefreshOnReadyStateChange()
{
if( Instance.Iframe.readyState != 'complete' )
{
return;
}
Instance.Refresh();
}
Instance.Refresh = function()
{
if( !Instance.Iframe )
{
return alert( "Iframe " + iframeId + " is undefined" );
}
m_iframeDoc = getIframeDocument();
Instance.Iframe.detachEvent( "onreadystatechange" , RefreshOnReadyStateChange );
var create = m_iframeDoc.createElement;
var append1 = m_iframeDoc.appendChild;
vDynamicForm = create("<FORM name='vDynamicForm' method='post'>");
var append2 = vDynamicForm.appendChild;
append2(create("<INPUT type='hidden' name='FetchXml'>"));
append2(create("<INPUT type='hidden' name='LayoutXml'>"));
append2(create("<INPUT type='hidden' name='EntityName'>"));
append2(create("<INPUT type='hidden' name='DefaultAdvFindViewId'>"));
append2(create("<INPUT type='hidden' name='ViewType'>"));
append1( vDynamicForm );
vDynamicForm.action = "/" + ORG_UNIQUE_NAME + "/AdvancedFind/fetchData.aspx";
vDynamicForm.FetchXml.value = Instance.FetchXml;
vDynamicForm.LayoutXml.value = Instance.LayoutXml;
vDynamicForm.EntityName.value = Instance.Entity;
vDynamicForm.DefaultAdvFindViewId.value = Instance.QueryId;
vDynamicForm.ViewType.value = 1039;
vDynamicForm.submit();
Instance.Iframe.attachEvent( "onreadystatechange" , OnViewReady );
}
function OnViewReady()
{
if( Instance.Iframe.readyState != 'complete' )
{
return;
}
Instance.Iframe.style.border = 0;
Instance.Iframe.detachEvent( "onreadystatechange" , OnViewReady );
if (Instance.WithParentContext == true)
{
getIframeWindow().open = OnWindowOpen;
}
if (m_iframeShowModalDialogFunc == null)
{
m_iframeShowModalDialogFunc = getIframeWindow().showModalDialog;
getIframeWindow().showModalDialog = OnIframeShowModalDialog;
}
if (Instance.EntityCode > 0)
{
if (m_windowAutoFunc == null)
{
m_windowAutoFunc = window.auto;
window.auto = OnWindowAuto;
}
}
m_iframeDoc = getIframeDocument();
m_iframeDoc.body.scroll = "no";
m_iframeDoc.body.style.padding = "0px";
}
function OnWindowOpen(url, name, features)
{
//new window
if (url.indexOf('?') == -1)
{
if (url.indexOf('userdefined') == -1 )
{
url = url + "?_CreateFromType=" + crmForm.ObjectTypeCode + "&_CreateFromId=" + crmForm.ObjectId;
}
else
{
url = url + "?_CreateFromType=" + crmForm.ObjectTypeCode + "&_CreateFromId=" + crmForm.ObjectId + "&etc=" + Instance.EntityCode + "#";
}
}
return window.open(url, name, features);
}
function OnIframeShowModalDialog(sUrl, vArguments, sFeatures)
{
m_iframeShowModalDialogFunc(sUrl, vArguments, sFeatures);
Instance.Refresh();
}
function OnWindowAuto(otc)
{
if ( otc == Instance.EntityCode )
{
getIframeDocument().all.crmGrid.Refresh();
}
m_windowAutoFunc(otc);
}
function getIframeDocument()
{
return getIframeWindow().document;
}
function getIframeWindow()
{
return Instance.Iframe.contentWindow;
}
}
OnCrmPageLoad();
不知什麽原因總是沒有辦法開啟,這是我通過台北才連上的.
所以備份一下.
My first post about displaying fetch inside an IFRAME has two disadvantages. The first is that the context of the parent window does not follow to the new entity window when you click on add new record (grid) button. This is might be annoying if you’re counting on the default mapping between the two entities. The second problem is that the grid does not refresh after you add (new button) or remove (delete button) a record. This means you are not able to see the changes unless you press on the grid refresh button your self.
I made piece with the fact that the parent context did not follow through to the child window since I was using advanced find. But the fact that the gird does not refresh automatically came as a surprise since I remember this feature working “AS IS” in v3.0. I guess ms did a few changes to the auto function which searched and refreshed the grid. Thanks to Dave Berry who commented / Posted about this and brought it to my attention.
In order to overcome this issue I added two new properties to the FetchViewer class.
The first parameter is called WithParentContext. This property allows you to decide whether the parent window object id is passed to the child window. I made it a public (as opposed to internal) choice since I figured you can display any type of query inside the FetchViewer including a query that does not reflect a direct parent child relationship.
The second parameter is the EntityCode (ObjectTypeCode) of the entity being fetched. If you want the grid to refresh automatically you must supply this value. This is important since the value is eventually passed to MS original auto function which expects this value.
The rest of the fetch viewer class was not changed and you can read all about it here.
function OnCrmPageLoad()
{
window.fetchContacts = new FetchViewer("IFRAME_test");
fetchContacts.WithParentContext = true;
fetchContacts.EntityCode = 2;
fetchContacts.FetchXml = getFetchXml();
fetchContacts.LayoutXml = getLayoutXml();
fetchContacts.Entity = "contact";
fetchContacts.QueryId = "{00000000-0000-0000-00AA-000000666400}";
fetchContacts.RegisterOnTab(0); //IFRAME ON THE FIRST TAB
}
function getFetchXml()
{
return '<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false"><entity name="contact"><attribute name="fullname"/><attribute name="telephone1"/><attribute name="contactid"/><order attribute="fullname" descending="false"/><filter type="and"><condition attribute="parentcustomerid" operator="eq" uitype="account" value="' + crmForm.ObjectId + '"/></filter></entity></fetch>';
}
function getLayoutXml()
{
return '<grid name="resultset" object="2" jump="lastname" select="1" icon="1" preview="1"><row name="result" id="contactid"><cell name="fullname" width="300" /><cell name="telephone1" width="125" /></row></grid>';
}
function FetchViewer( iframeId )
{
var Instance = this;
var vDynamicForm;
var m_iframeTab;
var m_iframeDoc;
var m_iframeShowModalDialogFunc = null;
var m_windowAutoFunc = null;
Instance.WithParentContext = false;
Instance.EntityCode = 0;
Instance.Entity = "";
Instance.Iframe = null;
Instance.FetchXml = "";
Instance.QueryId = "";
Instance.LayoutXml = "";
Instance.RegisterOnTab = function( tabIndex )
{
Instance.Iframe = document.getElementById( iframeId );
if( !Instance.Iframe )
{
return alert( "Iframe " + iframeId + " is undefined" );
}
m_iframeDoc = getIframeDocument();
var loadingGifHTML = "<table height='100%' width='100%' style='cursor:wait'>";
loadingGifHTML += "<tr>";
loadingGifHTML += "<td valign='middle' align='center'>";
loadingGifHTML += "<img alt='' src='/_imgs/AdvFind/progress.gif'/>";
loadingGifHTML += "<div/><b>Loading View
![](https://www.cnblogs.com/Images/dot.gif)
loadingGifHTML += "</td></tr></table>";
m_iframeDoc.body.innerHTML = loadingGifHTML;
if( parseInt( "0" + tabIndex ) == 0 )
{
Instance.Refresh();
}
else
{
Instance.Iframe.attachEvent( "onreadystatechange" , RefreshOnReadyStateChange );
}
}
function RefreshOnReadyStateChange()
{
if( Instance.Iframe.readyState != 'complete' )
{
return;
}
Instance.Refresh();
}
Instance.Refresh = function()
{
if( !Instance.Iframe )
{
return alert( "Iframe " + iframeId + " is undefined" );
}
m_iframeDoc = getIframeDocument();
Instance.Iframe.detachEvent( "onreadystatechange" , RefreshOnReadyStateChange );
var create = m_iframeDoc.createElement;
var append1 = m_iframeDoc.appendChild;
vDynamicForm = create("<FORM name='vDynamicForm' method='post'>");
var append2 = vDynamicForm.appendChild;
append2(create("<INPUT type='hidden' name='FetchXml'>"));
append2(create("<INPUT type='hidden' name='LayoutXml'>"));
append2(create("<INPUT type='hidden' name='EntityName'>"));
append2(create("<INPUT type='hidden' name='DefaultAdvFindViewId'>"));
append2(create("<INPUT type='hidden' name='ViewType'>"));
append1( vDynamicForm );
vDynamicForm.action = "/" + ORG_UNIQUE_NAME + "/AdvancedFind/fetchData.aspx";
vDynamicForm.FetchXml.value = Instance.FetchXml;
vDynamicForm.LayoutXml.value = Instance.LayoutXml;
vDynamicForm.EntityName.value = Instance.Entity;
vDynamicForm.DefaultAdvFindViewId.value = Instance.QueryId;
vDynamicForm.ViewType.value = 1039;
vDynamicForm.submit();
Instance.Iframe.attachEvent( "onreadystatechange" , OnViewReady );
}
function OnViewReady()
{
if( Instance.Iframe.readyState != 'complete' )
{
return;
}
Instance.Iframe.style.border = 0;
Instance.Iframe.detachEvent( "onreadystatechange" , OnViewReady );
if (Instance.WithParentContext == true)
{
getIframeWindow().open = OnWindowOpen;
}
if (m_iframeShowModalDialogFunc == null)
{
m_iframeShowModalDialogFunc = getIframeWindow().showModalDialog;
getIframeWindow().showModalDialog = OnIframeShowModalDialog;
}
if (Instance.EntityCode > 0)
{
if (m_windowAutoFunc == null)
{
m_windowAutoFunc = window.auto;
window.auto = OnWindowAuto;
}
}
m_iframeDoc = getIframeDocument();
m_iframeDoc.body.scroll = "no";
m_iframeDoc.body.style.padding = "0px";
}
function OnWindowOpen(url, name, features)
{
//new window
if (url.indexOf('?') == -1)
{
if (url.indexOf('userdefined') == -1 )
{
url = url + "?_CreateFromType=" + crmForm.ObjectTypeCode + "&_CreateFromId=" + crmForm.ObjectId;
}
else
{
url = url + "?_CreateFromType=" + crmForm.ObjectTypeCode + "&_CreateFromId=" + crmForm.ObjectId + "&etc=" + Instance.EntityCode + "#";
}
}
return window.open(url, name, features);
}
function OnIframeShowModalDialog(sUrl, vArguments, sFeatures)
{
m_iframeShowModalDialogFunc(sUrl, vArguments, sFeatures);
Instance.Refresh();
}
function OnWindowAuto(otc)
{
if ( otc == Instance.EntityCode )
{
getIframeDocument().all.crmGrid.Refresh();
}
m_windowAutoFunc(otc);
}
function getIframeDocument()
{
return getIframeWindow().document;
}
function getIframeWindow()
{
return Instance.Iframe.contentWindow;
}
}
OnCrmPageLoad();
Adi,
Change your function below as I have updated:
function OnIframeShowModalDialog(sUrl, vArguments, sFeatures) {
var returnVar = m_iFrameShowModalDialogFunc(sUrl, vArguments, sFeatures);
if (sUrl.search(/OnDemandWorkflow/) < 0) {
Instance.Refresh();
}
return returnVar;
}
I've made this update in my code as well. It allows the "Run Workflow" button to work.
Hi Adi,
How to make this code dynamic? I want specific records in the iframe only. Currently by using the fetch xml I'm getting only a specific record always, the one which I gave in AF. How to get other records?
What other records are you interested in? what are you trying to achieve
the code is dynamic since it uses the crmForm.ObjectId to retrieve the records.
Hi Adi,
Thanx for the update, I had ignored that part. Its working now with dynamic values.
I have put a workflow inside the iFrame entity and its not working when I see from the iFrame but I can see it working from the main record page? I have even incorporated Dave's commented code for workflows into mine but no rescue. Any clue?
I want to put a fetch and auto refresh for quote detail, how can i achieve this? Because quote details is natively integrated with quotes it doesnt show up in AF also.
If you need to show quote details for a single quote then you need to implement the quote associated view. If you’re looking to display multiple quote details from different quotes the only solution is to write a report and show that in you iframe. Of course you won’t be able to easily use the workflow button.
Thanx for the prompt response.
Wat i discovered now is that watever fields I am filling inside the iFrame is not seen once I save & close it and open it again. But the fields are showing in the view part. I can see the filled records from the main page of the entity. Wer am I going wrong?
Yes I need to show quote details for a single quote.I have created the iFrame inside the quote entity for quote details. How can i put a auto refresh to it?
Since I can see the "view" with data but the attributes inside the form are empty I guess I should change the URL inside the iFrame, not sure.... I'm sure i'm missing somethng here...
I wrote a new post about showing an associated view in an iframe. It also handles the refresh button.
can anyone provide me some snippet to retreive the selected record from the grid to display the into the field above the IFrame.
Hi Adi,
I need few help from ur side, a I have an IFRAME I need to display the quarters from a quarters entity based on the start date and end date entered...
kindly help me..
Wishwaz, i replied to your post on ms forums.
Adi, Can you please help me on this one..I really got stuck since past couple of days..
I want to poplulate the selected record from the view to the above main forms fields..
Is there any way to do that...?
Thanks ADI for ur reply..
can u give me the link of the thread
This is your post
Kumar, I’m not sure I completely understand you requirement.
Please open a new thread on ms forums and I’ll try to help you out.
Thanks Adi,
I have just open a thread in this forum.
Actually, with above method, we are placing the Advanced find result in grid view of contact in the Account entity form.
And from the Contact entity view, how Account entity form can retrieve which record is selected from the contact gridview that is embedded in the Account entity view.
I would like get the selected record from that grid view and display that selected row records in appropriate field of the account entity form.
Any help with some code snippet would be great..
Thanks ADI, Its perfect and working fine for me after a long struggle just because of my stupidity....
Just for Improvement: In THE IFRAME GRID(Advanced find window that is displayed in the IFRAME) Can remove the NEW button??
You can only remove the button by using JavaScript.
After line 144 you can insert a line similar to the following code:
m_iframeDoc.all.<id of new button>.style.display = ‘none’
Hi Adi, thank you for sharing these great code masterpieces. It works fine.
I have the following request: the resulting grid in an iframe is the same as in the advancedfind window, including grid menubar and its functionality. Can I somehow change it to the one used in associated grid view?
I can show associated grid view in an iframe, but I need to show a tabset based on advanced find query, that can be achieved with your fetch an an iframe code example. However, its funcionality is not sufficient for me.
Is it possible at all?
Hi Alex, What functionality of the associated view do you need to see in the fetchviewer? The toolbars look almost the same? Which entity’s associated view are you referring to?
Hi Adi, thank you for quick response. I am working with custom entities. Associated grid menubar has the following buttons: (1) Create new object ObjectName; (2) Add existing object ObjectName. The one in advanced find view has only one button "Create new". And the grid intself behave differently: when I doubleclick a record I get a form to create new object instead of editing form for selected object.
I was trying to find a solution myself by reverse engeneering the code behind for fetchdata.aspx and stuck at CofigurePage method of the inherited class FetchData, which set protected field crmGridMenuBar to GridTypeCode.AdvancedFind (this.crmGridMenuBar.GridType = GridTypeCode.AdvancedFind;).
Is there a way to override this setting?