Display external application forms within Microsoft Dynamics 365 - dynamics-crm

We have our own system which we need to integrate with MS Dynamics 365.For Example : In Accounts section we need to add an extra tab that loads IFrame or something that retrieves some extra information from our system.
The following are the things that I reached :
Inserting IFrame within a new Dashboard: (but it will not fetch specific account information, it will only pass the currently logged in user along with the organization name)
Unified Service Desk (USD): (we may add customization but this is a desktop app and we need it to be on web)
Microsoft flow: this would only work in the background when you create or edit an account (not sure if it has another functionality)
Extensions: Not sure how to use it to achieve the same functionality, I believe the solution may be here but I just need from where to start.
Has anybody done a similar thing before?
Thank you

You can definitely do it,
Here is how I just tried on one of my Trail Instance.
I added new Tab as you need, I called it "HTML Page"
On this Tab I added Webresource, you can add Iframe as well and call your external WebPage.
For my simple use case I created a simple HTML page as webresource in CRM and configured it to Webresource tab as below
Sample code for HTML. Dont worry about long html file. Mostly it is bla bla. What is of our importance is <body onload="myFunction()"> and then in
<script>
function myFunction() {
debugger;
alert("Account Id when from fromcontext is ");
alert(parent.Xrm.getformContext().data.entity.getId());
}
</script>
complete HTML code below
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>My first styled page</title>
</head>
<body onload="myFunction()">
<!-- Site navigation menu -->
<ul class="navbar">
<li>Home page
<li>Musings
<li>My town
<li>Links
</ul>
<!-- Main content -->
<h1>My first styled page</h1>
<p>Welcome to my styled page!
<p>It lacks images, but at least it has style.
And it has links, even if they don't go
anywhere…
<p>There should be more here, but I don't know
what yet.
<!-- Sign and date the page, it's only polite! -->
<address>Made 5 April 2004<br>
by myself.</address>
<script>
function myFunction() {
debugger;
alert("Account Id when from fromcontext is ", parent.Xrm.getformContext().data.entity.getId());
}
</script>
</body>
</html>
Also on Form Load of account I added additional Javascript. This javascript will create global variable which could be called from your webresource.
Article Link for additional Javascript
Sample code used for Javascript below
formContext=null;
function onload(executionContext){
debugger;
var formContext = executionContext.getFormContext();
Xrm.getformContext = function (){
return formContext;
};
Xrm.getParentAttribute = function (attrName) {
debugger;
return formContext.getAttribute(attrName);
};
Xrm.getParentControl = function (attrName) {
debugger;
return formContext.getControl(attrName);
};
}
Final Result will be something like below
Summary:
Create Wberesource/Iframe
Create Additiona Js on Load
Use global variable in your webresource.

Related

Pass selected element from list group Thymeleaf

I am using Thymeleaf and Spring MVC for a project and I am displaying a list in Thymeleaf and I want to get the selected items and pass them when I press submit
This is my form with the list:
<form th:action="#{/trip-info}" th:object="${trip}" method="post">
....
<a class="list-group-item list-group-item-action" th:each="currentPerson : ${trip.employees}" th:text="${currentPerson.getFirstName() + ' ' + currentPerson.getLastName()}" onclick="addPerson(this)"></a>
</form>
I have the employees list displayed in my page, now I am not sure if I can pass to a controller the selected values or if I must use javascript and construct a body. Does anybody have any ideas ?
Thanks!
Transferring the selected form item is outside the role of 'Thymeleaf'.
'Thymeleaf' is a server side template engine that simply creates code in html.
The event (item select) changed by the client must be processed by JavaScript.
For a simple example,
Before submitting from the form, check the selected item in javascript and create a function that performs the submit.
If you need an example, show me your source code in more detail.
Additional comments -
There are two ways.
1. How does 'a tag' directly tell you about your event?
2. How to externally liseten events of 'a tag'
I wanted the '2' method, and you chose the '1' method.
Your source will be terminated with the href moved before executing the 'onclick' event.
Take a look at this example.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
some method<br/>
some method2<br/>
some method3<br/>
<script>
function someEvent(event){
console.log(event);
}
</script>
</body>
</html>
'href' works but is invalidated by void (0). Or moved to another window tab by target. And then onclick happens sequentially.
I can not speak English and the explanation is immature. I'm sorry.

Can PDFreactor be used to create PDF documents from browser DOM?

Can PDFreactor be used as a Web Service whereby javascript running on a browser can use the REST API to shuttle page content from the DOM to be converted to PDF? In this application, the content being rendered in the browser is generated exclusively by browser-side javascript (using the D3 library); the requirement here is to provide an "Export to PDF" type action to the browser end-user from the currently rendered page contents (via a button or menu action). The goal would then be to shuttle elements from the current DOM to PDFreactor via the REST API so that the Web Service could generate the PDF. Is this a reasonable use of PDFreactor?
Thank you in advance.
It is of course possible to convert the HTML content which was already processed by the browser with PDFreactor. In this case you could e.g. use the JavaScript API to pass the content extracted from the "body" element to PDFreactor and display the resulting PDF in the same page. Please see an example script below:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="http://www.pdfreactor.com/product/wrappers/javascript/lib/PDFreactor.js"></script>
<script>
window.onload = function() {
convertToPDF();
}
function convertToPDF() {
// Create new PDFreactor instance
var pdfReactor = new PDFreactor();
// Get the content from the body element
var content = "<html><body>"+document.body.innerHTML+"</body></html>";
// Create a new PDFreactor configuration object
var config = {
// Specify the input document
'document': content,
// Set a base URL for images, style sheets, links
baseURL: window.location.href,
}
// Render document and save result
pdfReactor.convert(config, function(result) {
document.body.innerHTML += '<iframe id="result" style="width: 100%; height: 95vh"></iframe>';
document.getElementById("result").src = "data:application/pdf;base64," + result.document;
}, function(error) {
document.body.innerHTML += "<h1>An Error Has Occurred</h1>"
+ "<h2>" + error + "</h2>";
});
}
</script>
</head>
<body>
<p>Hello World</p>
</body>
</html>
However as PDFreactor supports a variety of popular JavaScript libraries including D3.js, jQuery, etc. it might be more efficient to directly pass your input document including the JavaScript to the PDFreactor Web Service instead of converting the HTML rendered by the browser. PDFreactor will process any JavaScript within your input document, as long as JavaScript processing (disabled by default) is enabled in your PDFreactor integration.

How to use AngularJS to lazy load content in a collapsible panel

I am building an application that uses the Bootstrap Collapse component to render a sequence of panels, all of which will initially be in the collapsed state.
Since the page may contain many such panels and each of them may contain a large amount of content, it seems appropriate to populate these panels on demand, by executing an AJAX call when the user expands any panel.
The dynamic content of the page (including the markup for the panels) is rendered using AngularJS, and I assume it's possible to configure Angular to bind to an event on the panel elements, that results in their content being lazy loaded when they expand.
Unfortunately, after looking at the AngularJS docs and the available tutorials, I can't see how best to tackle this. Can anyone throw any light on it?
Thanks in advance,
Tim
This is way old, but the question might still come up now and then. I now find this to be the most suitable solution without polluting your controllers:
(myDirective loading its content via AJAX right after its creation.)
<accordion>
<accordion-group
heading=""
ng-repeat="foo in bar"
ng-init="status = {load: false}"
ng-click="status.load = true">
<myDirective ng-if="status.load"></myDirective>
</accordion-group>
</accordion>
each element created by ng-repeat gets its own $scope, so clicking ab accordion-group will result in only the respective directive being loaded.
edit:
depending on latency and the size of the data that's to be lazy loaded, you might consider using ng-mouseover instead of ng-click. That way loading starts some 100ms before the user opens the accordion which can reduce 'sluggishness' of your UI. Obviously there's the downside of occasionally loading content of groups that are never actually clicked.
#Tim Coulter, I've created something following the idea of #Stewie.
It can definitely be improved, but I guess it's a good starting point.
I've created a small directive to bind the click event of the accordion's panel. When the click event is fired, I passed the panel template via the panel-template= attribute and it updates the main-template which is used inside the panel.
It makes reference to 2 html files (panel1.html and panel2.html) that contains the content of the each panel.
I would recommend to create a service to fetch these files via AJAX - just the way you wanted.
On the code below I created a service called dataService for this purpose and you should bind it to the click event - so files are loaded on demand when the user clicks on it.
Note the the mainTemplate is a common panel to all accordions, so when it changes the all the accordions will have the same content, BUT I am assuming you want to display only one panel at time, right ?!
Anyway as I said before the logic can be improved to fix these little 'gotchas', but I believe the core functionality is there to start with. :)
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
<script>
var myApp = angular.module('myApp', []);
myApp.controller('AccordionDemoCtrl', ['$scope', 'dataService', function ($scope, dataService) {
$scope.oneAtATime = true;
$scope.mainTemplate = '';
$scope.groups = [
{
id: "001",
title: "Dynamic Group Header - 1",
content: "Dynamic Group Body - 1",
template: "panel1.html"
},
{
id: "002",
title: "Dynamic Group Header - 2",
content: "Dynamic Group Body - 2",
template: "panel2.html"
}
];
}]);
myApp.factory('dataService', [ '$http', function($http){
return {
getData: function() {
return // you AJAX content data here;
}
}
}]);
myApp.directive('accordionToggle', [function () {
return {
restrict: 'C',
scope: {
mainTemplate: '=',
panelTemplate: '#'
},
link: function (scope, element, iAttrs) {
element.bind('click', function(e){
scope.mainTemplate = scope.panelTemplate;
scope.$apply();
});
}
};
}]);
</script>
</head>
<body ng-controller="AccordionDemoCtrl">
<div class="accordion" id="accordionParent">
<div class="accordion-group" ng-repeat="group in groups" >
<div class="accordion-heading">
<a class="accordion-toggle" main-template="$parent.mainTemplate" panel-template="{{ group.template }}" data-toggle="collapse" data-parent="#accordionParent" href="#collapse{{ $parent.group.id }}">
Collapsible Group Item {{ $parent.group.id }}
</a>
</div>
<div id="collapse{{ group.id }}" class="accordion-body collapse">
<div class="accordion-inner">
<div class="include-example" ng-include="mainTemplate"></div>
</div>
</div>
</div>
</div>
</body>
</html>

How to Return a View from a Controller to an iFrame

I am new to MVC 3 and have come accross the following scenario:
First let me explain how I have setup my application:
All post backs to the server use jquery ajax which which return a view from the controller that either appended or prepended or replace a targeted div.
The Scenario:
I have come to a point where I would like to upload images but unfortunately because of the jquery ajax posting I cannot get the values for an html in C# Request.Files. I know there are plugins out there to help out with this but I would like to do this myself so I have created an <iframe> which i then use a bit of javascript and post the form targeted to the iframe (old classic way of doing things):
function UploadImg(SACTION) {
alert(SACTION);
validatorform.action = SACTION;
validatorform.target = "fraImage";
validatorform.method = "POST";
validatorform.submit();
}
the SACTION parameter looks like this #Url.Action("UploadFile", "Response"). This all works well as it hits the controllers action method and I can then save the image:
[HttpPost]
public ActionResult UploadFile(string ArticleID)
{
ViewBag.PreviewImage = cFileUploads.UploadFile(ArticleID, Request.Files[0]);
return View("ImagePreview");
}
I would now like to return a view to the iframe (simply to preview the image and then do a couple of other things but this is besides the point)
The View for previewing the Image:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form action="">
<img alt="" src="#ViewBag.PreviewImage" />
</form>
</body>
</html>
The Problem:
Unfortunately when I return the View (ImagePreview.cshtml) in C# the whole page is refreshed, all I want is for the iFrame to be refreshed. How should I return the view from the controller?
Fiqured out the problem, I had a bit of javascript that was replacing the contents of a div that the iframe was sitting in ... (slap on my forehead). All working perfectly now :)
Will leave this question here just incase ..

How to hide jQuery tabs until authenticated and add or show them once authenticated in MVC3?

Summary
I'm currently trying to build a Web application using MVC 3 architecture and jQuery UI controls. I have been able to display tabs and navigate through them so far.
Now, I am able to get the LogOn page to display on my first tab as it is the first required action to this application.
Once authenticated, I'd like to be able to add some other tabs which allows to use use this application.
The application is about a phone book listing containing known people mailing address.
That said, the workflow of this application would be:
Authenticate upon first arrival on the site;
If the user is not yet registered, the app shall let this very user register once and for all, using the same jQuery UI tab or maybe showing a new tab for registration or else, a modal dialog box;
Once authenticated from step 1, the user has now access to the different features of the site.
For example, let's say I want to register a new user and I am this web-application administrator. I shall first authenticate against this application, and then I'll see the common tabs that any user can see, plus a special tab for creating/registering new users who'll be able to authenticate against this app. once registered successfully by the site admin.
I have already been able to display the LogOn view which I deleted the initial view created by the template to recreate as a partial view to be able to contain it within the jQuery UI tab body. This works fine.
I also have a SelectTab method within my HomeController which shall know what partial view to display depending on the value of the id it is passed in as an input parameter.
Now, when I try to navigate from the LogOn partial view on the first jQuery UI tab, that is actually the only available option yet, clicking the Register link won't let me show the Register partial view within the same tab.
Code samples
The HomeController class:
public class HomeController : Controller {
public ActionResult Index() { return View(); }
public ActionResult SelectTab(int id) {
switch (id) {
case 0: return RedirectToAction("Register", "Account");
default: return RedirectToAction("LogOn", "Account");
}
}
}
The AccountController class:
public class AccountController {
public ActionResult LogOn() { return PartialView(new LogOnModel()); }
public ActionResult Register() { return PartialView(new RegisterModel()); }
}
Both models (LogOnModel, RegisterModel) stated here are the template's default.
And my _Layout.cshtml shared view:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/south-street/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js" type="text/javascript"></script>
<script>
$(window).load(function () {
$("#tabs").tabs({ select: function (event, ui) { selectTab(getSelectedTab()); } });
logIn();
});
function logIn() {
selectTab(-1);
selectTab(0);
}
function selectTab(index) {
var url = '#Url.Content("~/Home/SelectTab/")' + index;
var targetDiv = "#tab" + index;
$.get(url, null, function(result) { $(targetDiv).html(result); });
}
function getSelectedTab() { return $("#tabs").tabs("option", "selected"); }
function setSelectedTab(index) { $("#tabs").tabs("option", "selected", index); }
</script>
</head>
<body>
<div id="tabs">
<ul id="menu">
<li><span>Authenticate</span></li>
#if (Request.IsAuthenticated) {
<li><span>About</span></li>
}
</ul>
<div id="tab0"></div><div id="tab1"></div>
</div>
#RenderBody()
</body>
Development environment
I'm using:
VS2010 and .NET 4.0;
jQuery UI (see _Layout.csthml code sample for version and style template);
ASP.NET MVC3.
Question(s)
*How to render the Register partial view once one clicks the 'Register' link contained in the 'LogOn' partial view into the same tab?
Perhaps hiding the actual tab and showing another for registration would appear to be simpler? And yet, how to achieve this?*
I suggest that every other tab (except login) to be loaded via ajax. You submit the login from via ajax and on succesful response you destroy the login tab then add dynamically a new one with href set to an ajax action.
You can accomplish what you want to do, but it will require lots of jquery and ajax (I recommend to give knockoutjs a try).The server-side part is the easiest one.
I think it's also better to call the actions directly without the SelectTab switch.

Resources