Business Solutions Archives - Aric Levin's Digital Transformation Blog http://aric.isite.dev Microsoft Dynamics 365, Power Platform and Azure Wed, 11 May 2022 23:58:05 +0000 en-US hourly 1 https://wordpress.org/?v=5.9.3 Showing page status of multi-page forms in Power Apps Portals http://aric.isite.dev/dynamics/post/multipage-status-powerapps-portals/ Sat, 23 May 2020 00:47:00 +0000 https://aric.isite.dev/index.php/2020/05/23/showing-page-status-of-multi-page-forms-in-power-apps-portals/ Creating navigation in a Power Apps portal application is straight forward, and can easily be done using Web Link Sets, but how about showing to the user where they are in the process and modifying the style of each element once the user has finished entering the data for that page. We have done this a few times and this involves the combination of liquid and JavaScript code on the different pages.

The post Showing page status of multi-page forms in Power Apps Portals appeared first on Aric Levin's Digital Transformation Blog.

]]>
Creating navigation in a Power Apps portal application is straight forward, and can easily be done using Web Link Sets, but how about showing to the user where they are in the process and modifying the style of each element once the user has finished entering the data for that page. We have done this a few times and this involves the combination of liquid and JavaScript code on the different pages.

Let’s start from the beginning. The first thing that we need to do is to create the Web Link Set that we are going to use. In our case, we are using a web link set called Legal. Notice that the Display Order is important, because we are going to write that back to the record every time we navigate from one page to the next.

The screenshot below shows a sample of the Web Link view for our Legal Web Link Set.

Power Apps Portal Web Link Set

The next thing that we want to do is create the field on the entity that will capture that page that we are currently on (or the change of the record during submission. We will need to add the field to the entity, but also add the field to every tab (entity form) that is displayed on the application. The first screenshot shows the field that is created on the Application entity. For our purpose we used two field, but only the Last Page completed field is required.

Power Apps Portal - Required Attributes

Once the field is created, we will add that field to all of the tabs that are displayed in Entity forms. We have a custom form called Portal Application, where everything that is displayed on the portal is set. In our Legal Advice page for example, you can see that the page contains the Last Page Visited and Last Page Completed so that they can be populated on the portal form.

Power Apps Portal - Model Driven Forms Designer

We have a web template that displays the navigation area of the application. In that web template, we are retrieving the value of the last page completed, and will perform some logic on it.

We start by verifying the template has a unique identifier that will allow us to retrieve the application, and assigning the app variable to the application entity, and then setting the category and the last page completed fields to the assigned variables.

{% if request.params.id != null and request.params.id != empty %}
   {% assign app = entities["bac_application"][request.params.id] %}
   {% assign application_category = app["bac_applicationcategoryid"].name %}
   {% assign last_page_completed = app["bac_lastpagecompleted"] %}
{% endif %}

We then retrieve the Web Link set for the category that we specified

{% case application_category %}
  {% when 'Legal Assistance' %}
    {% assign app_nav = weblinks["Legal"] %}
  {% else %}
    {% assign app_nav = weblinks["General"] %}
{% endcase %}

Now that we have the Web Link Set and the Last page completed, we will loop through the Web Link Set and perform a few checks. We will check the application status to verify if the application has been completed or not and check the value of the last page completed to verify whether or not we have already reached a particular page. We will also check if the current page is the same as the Url of the page on linkset so that we can have different style for the current page to notify the user this is the page we are on.

In every condition we include a link to the Navigation Item which contains that code to the styling of the link, passing the style that the link should display. The loop code is displayed below:

{% if app_nav %}
    {% for link in app_nav.weblinks %}
        {% if request.params.id != null and request.params.id != empty %}
            {% if link.adx_displayorder > 20 %}
                {% if link.adx_displayorder <= last_page_completed %}
                    {% if (application_status == 'In Progress') %}
                        {% include 'Application Navigation Item' with link, special_class: ' cvd-list-row-thread-completed'  %}
                    {% else %} 
                        {% include 'Application Navigation Item' with link, special_class: ' cvd-list-row-thread-submitted'  %}
                    {% endif %}
                {% else %}
                    {% if link.url == request.path %}
                        {% if forloop.last %}
                            {% if (application_status == 'In Progress') %}
                                {% include 'Application Navigation Item' with link, special_class: ' cvd-list-row-thread-completed'  %}
                            {% else %} 
                                {% include 'Application Navigation Item' with link, special_class: ' cvd-list-row-thread-submitted'  %}
                            {% endif %}
                        {% else %}
                            {% include 'Application Navigation Item' with link, special_class: ' cvd-thread-current'  %}
                        {% endif %}        
                    {% else %}
                        {% include 'Application Navigation Item' with link, special_class: ' '  %}
                    {% endif %}
                {% endif %}
            {% endif %} <!-- link.adx_displayorder > 20 -->
    {% endfor %}
{% endif %}

Since we are also displaying the controls on the form, we need to add JavaScript code to hide the controls and set the value of the next page on the last page completed, so that when the page is submitted that will be written to the entity record. The code below shows the JavaScript.

$(document).ready(function () {
   var url = window.location.href;
   $("#bac_lastpagecompleted").parent().parent().hide();
   $("a").filter(".page-link.cvd-link-navigation.cvd-custom-event").each(function () {
      if (this.href == url) {
         var maxPageNumber = 0;
         if ($("#bac_lastpagecompleted").val() != "")
            maxPageNumber = parseInt($("#bac_lastpagecompleted").val());
         var displayOrder = parseInt($(this).attr("adx_displayorder"));
         var nextPage = displayOrder;
         if (nextPage > maxPageNumber)
            $("#bac_lastpagecompleted").val(nextPage);
      }
   });
});

Now that we have completed our review, we can take a look at the final result.

Power Apps Portal Page Navigation Demo

The post Showing page status of multi-page forms in Power Apps Portals appeared first on Aric Levin's Digital Transformation Blog.

]]>
New Features in Form Processing for AI Builder http://aric.isite.dev/business-solutions/post/ai-builder-form-processing-new-features/ Tue, 05 May 2020 08:30:00 +0000 https://aric.isite.dev/index.php/2020/05/05/new-features-in-form-processing-for-ai-builder/ Over the past year, I played here and there with AI Builder, and particularly form processing, but have found that it was somewhat cumbersome for some of the forms that I wanted to build, especially when working a lot in the government space. Yesterday, May 4th, Microsoft announced some new changes to the AI Builder Form processing that allows recognition of undetected fields. I decided to test this out, and in order to implement this, used the IRS W-9 form, which is not such as easy form to implement.

The post New Features in Form Processing for AI Builder appeared first on Aric Levin's Digital Transformation Blog.

]]>
Over the past year, I played here and there with AI Builder, and particularly form processing, but have found that it was somewhat cumbersome for some of the forms that I wanted to build, especially when working a lot in the government space. Yesterday, May 4th, Microsoft announced some new changes to the AI Builder Form processing that allows recognition of undetected fields. I decided to test this out, and in order to implement this, used the IRS W-9 form, which is not such as easy form to implement.

First thing is first, login to your Power Apps environment, and in the left navigation under AI Builder click on Build. This will show you the available models that you can use. In our case we will use the Form Processing Model which was recently updated.

AI Builder Start Screen

To get started we will provide a name to the AI model, and click on create. Notice that we will be required to provide 5 documents (or more) with the same layout.

AI Builder Form Processing

The AI Builder Model wizard will start and ask us to upload the documents. You can click on the Add documents button on the command bar or on the screen to start.

AI Builder - Add Documents

You can add your documents from local storage, SharePoint or an Azure Blob Storage, something that was not available in earlier releases.

AI Builder - Add Documents from Local Storage, SharePoint or Azure Storage Container Blob

In my case, I had 6 documents of the IRS W-9 form that I prepared earlier available at local storage.

Upload Documents

The wizard will then show you the list of documents that you selected. Make sure that you select at least 6 documents for this purpose. Click on the Upload documents button

Upload Documents

You will then see that the documents have been uploaded. Click on the Close button to continue with the wizard and analyze the document structure.

AI Builder Upload Documents Successfully

Next you will thumbnails of all the documents that you uploaded. To start analyzing the documents click on Analyze, or if you need to add additional documents, click on the Add documents button in the command bar.

AI Builder Start Analyzing Documents

A modal window will pop up showing that the process is analyzing the documents. Based on the complexity of the documents, the number of pages and the amount of fields this can take up to a few minutes. In my case, since they were all single page with not too many fields, this took a little under a minute.

AI Builder - Analyzing Documents

After the analysis has been completed, the wizard will move to the next phase which is adding the form fields. It will show you that 0 fields have been selected. Click on the thumbnail and then click on the Next button to start selecting the fields

AI Builder - Field Selection

You will be navigated to a page that contains a copy of your form with the fields that AI Builder found. You will need to click on each of the fields that you want as part of the form and add it to the list of selected fields

AI Builder Form Processing Field Selection

You can simply select the field on the form, change the name of the field if you need to, and click on the check mark in the tooltip window

AI Builder Select Fields

Repeat this for all the fields that you want. If there are fields that AI Builder did not detect or select for you, you can select them yourselves (a new feature from yesterday’s release), and add them to the list of fields.

AI Builder Select Fields

Once done accept the fields, which will redirect you to a Save page. Select the form fields that you want to save, and Save your changes.

AI Builder - Form fields selection complete

The next and almost final phases is to train the AI model. Click on the button that will start the training. This might take some time, so you can navigate away and come back later when the training has been completed.

AI Builder Form Processing Training

Once the training has been completed, you can do a test run with a different form, and then publish your changes. When your changes have been published you can use the AI Builder form directly from a Canvas App or Power Automate flow.

AI Builder Form in Power Apps Canvas App

This entire process took less than an hour from start to finish (once I had the forms completed and ready). Now it’s your turn. Find a form that you would like to use AI for, and see how easy it is to get this up and running.

Please review the blog post from Joe Fernandez on the Microsoft Power Apps blog:

https://powerapps.microsoft.com/en-us/blog/ai-builder-form-processing-now-lets-you-recognize-undetected-fields/

The post New Features in Form Processing for AI Builder appeared first on Aric Levin's Digital Transformation Blog.

]]>
Advanced AutoNumber Source Code now available http://aric.isite.dev/dynamics/post/autonumber-enterprise-source-code-github/ Sat, 28 Mar 2020 01:00:00 +0000 https://aric.isite.dev/index.php/2020/03/28/advanced-autonumber-source-code-now-available/ A few years back we developed an AutoNumber solution that enables the implementation of AutoNumbers for Dynamics 365 and the Common Data Service. This AutoNumber solution allows the creation of rules for simple autonumbers with prefix, suffix and number of digits, but also has a lot of advanced features for getting numbers from related fields or option sets.

The post Advanced AutoNumber Source Code now available appeared first on Aric Levin's Digital Transformation Blog.

]]>
A few years back we developed an AutoNumber solution that enables the implementation of AutoNumbers for Dynamics 365 and the Common Data Service. This AutoNumber solution allows the creation of rules for simple autonumbers with prefix, suffix and number of digits, but also has a lot of advanced features for getting numbers from related fields or option sets.

These include:

  • Creating an AutoNumber for the current entity
  • Create an AutoNumber for an entity based a value in a related entity, and stores the AutoNumber in a text field in the entity
  • Create an AutoNumber for an entity based a multiple values of a related entity, and stores the AutoNumber in a text field in the entity
  • Create an AutoNumber for an entity based a value in an option set field, and stores the AutoNumber in a text field in the entity
  • Create an AutoNumber for an entity based a multiple values of an option set, and stores the AutoNumber in a text field in the entity

The source code, documentation and managed and unmanaged solutions are now available on Github, and can be downloaded from here:

https://github.com/ariclevin/autonumber/tree/master/Enterprise

The post Advanced AutoNumber Source Code now available appeared first on Aric Levin's Digital Transformation Blog.

]]>
Configuring oAuth authentication for CDS http://aric.isite.dev/dynamics/post/configuring-oauth-cds/ Mon, 11 Nov 2019 02:37:00 +0000 https://aric.isite.dev/index.php/2019/11/11/configuring-oauth-authentication-for-cds/ It has been quite some time since Microsoft announced the use of oAuth to connect between Server environments, but many organizations are still using username and password to connect to Dynamics 365 or the Command Data Service (CDS).

The post Configuring oAuth authentication for CDS appeared first on Aric Levin's Digital Transformation Blog.

]]>
It has been quite some time since Microsoft announced the use of oAuth to connect between Server environments, but many organizations are still using username and password to connect to Dynamics 365 or the Command Data Service (CDS).

I recently had to work on a migration project, and while this customer was using legacy credentials to authenticate, they had no problems doing so with all of their environments. After they provisioned a new environment, suddenly they started receiving authentication exceptions from their data migration tool (using Kingswaysoft and SSIS).

When trying different methods of authentications, we received several different errors, but the basic error was Authentication Failed:
Authentication Failed to CDS
George Doubinski from crmtipoftheday.com pointed me out to checking if I was blocked by conditional access. Check his blog post here.
After going through several posts on Microsoft, I set up Server to Server connection using an App Registration and Azure Active Directory. Below are the step by step instructions on how to implement this.
We start by logging in to Azure Active Directory using the Url and logging in with an Azure Admin account below:
The first thing that we want to do is register an Application. We do this by clicking on the Azure Active Directory (1) and then selecting App Registrations (2), and in the App registrations section, click on New Registration (3).
Fill out the registration information by entering the name of the App and selecting Accounts in this organization directory only (Single tenant). You can ignore the Redirect URI for this purpose now.
Azure AD - Register an Application
After you click on the register button, you will see the new registered app in your list of App registrations.
Azure AD - Registered Applications
Click on the hyperlink of the App that you just created. This will navigate you to the properties of the application so that you can configure it. In the App overview page you will see the information about your app which includes the Application (client) ID, Directory (tenant) ID and Object Id as well as additional settings. You will also see a button that says View API permissions under the Call APIs section.
Click on the View API permissions button to allow this new app to delegate to Dynamics 365/CDS.
Azure AD App Registration - Call APIs
In the API permissions section, click on Add a permission to Add a permission to Dynamics 365. By default you will see in that window that there is Read permissions to the Microsoft Graph API.
Azure AD App Registration - Add a permission
This will pop up the Request API permissions area. In there look for Dynamics CRM under the Microsoft APIs. Click on the Dynamics CRM API, to request access to that API.
Azure AD App Registration - Select an API
The Dynamics CRM API will allow you to only choose Delegated permissions, and the only available permission is user_impersonation. Select the user_impersonation check box and click on the Add permissions button.
Azure AD App Registration - Request API permissions
This will bring back the previous screen, but you will not see both the Dynamics CRM and Microsoft Graph permissions on the list. At the bottom of the screen, click on the Grant admin consent. This will ask you if you are sure. Click Yes to finish granting the consent.
Azure AD App Registration - Grant Consent
At this point you will finalize the App permissions. We will not need to provide a Client Secret, as this value is required for Server to Server connectivity.
Click on the Certificates & secrets in the navigation, and in the new area, click on the New client secret button.
Azure AD App Registration - Certificates and secrets
In the Add a client secret popup enter a description and expiration option (1 year, 2 years or never expires). When done, click the Add button
Azure AD App Registration - Add a client secret
The newly created Client secret will be displayed in the Client Secret section, with a copy button. Copy the Client secret, and store in a location where you have access to it. You will not be allowed to copy it again after you navigate away, and you will need it to connect to your environment.
Azure AD App Registration - Client Secret
The next step is to create an application user. This user will be added to Dynamics 365 and will have access to run as an Application User.
Click on the Users link on the left hand side (under Azure Active Directory), and the click on the New User button. You can also click on the User link from within Azure Active Directory if Users is not available under your favorites.
Azure AD - Add New User
In the New user window select the Create User option, and then provide the identity information: Username, Name, First Name, Last Name, and the click on the Create button.
Azure AD - New User Registration
Once you are done adding the user, the new user will appear in the All Users list. You can click on Reset password to change the password for this user.
Azure AD - New User Added
The final step is to add this user to Dynamics 365 (or your CDS environment). Login to your Dynamics 365 environment and navigate to the Users entity, by click on Advanced Settings from the Settings area.
Common Data Service - Advanced Settings
Navigating to Settings -> Security, and click on the Users group.
Common Data Service - Select Users
Change the selected view from Enabled Users to Application Users, and click on the + New button.
Common Data Service - New Application User
The new User: Application User form will open up. Specify the User Name (Email Address from Azure AD), the Application ID, the User Full Name and the Primary Email of the User that you created. When you save the record, the Application ID URI and the Azure AD Object ID should be automatically filled out.
Common Data Service - Newly Added Application User
Finally, once you have completed these steps, you should be able to re-authenticate with Kingswaysoft using oAuth as shown below. You are not going to need to enter user credentials, but just the Client Id, Client Secret and the organization url as shown below.
Kingswaysoft to CDS Server to Server oAuth Connection
Clicking on the Test Connection button will now allow you to Connect to your CDS or Dynamics 365 environment and start moving your data.

The post Configuring oAuth authentication for CDS appeared first on Aric Levin's Digital Transformation Blog.

]]>
Creating a NAICS Code PCF Control using WebApi http://aric.isite.dev/powerplatform/powerapps/post/create-naics-pcf-control-webapi/ Fri, 18 Oct 2019 06:43:00 +0000 https://aric.isite.dev/index.php/2019/10/18/creating-a-naics-code-pcf-control-using-webapi/ In many of the projects that I have worked over the past years, either government of private sector, while working with other businesses it has become a common practice to request that Industry information from the companies that you work with, and furthermore the NAICS code. While not every company knows their NAICS code, drilling down to get it using the Industry (2-digit code), Subsector (4-digit code) and NAICS title (6-digit code) might be the way to go, sometimes you might want to bypass this complex search if you know ahead of time your business’ NAICS code and have it auto populated for you.

The post Creating a NAICS Code PCF Control using WebApi appeared first on Aric Levin's Digital Transformation Blog.

]]>
In many of the projects that I have worked over the past years, either government of private sector, while working with other businesses it has become a common practice to request that Industry information from the companies that you work with, and furthermore the NAICS code. While not every company knows their NAICS code, drilling down to get it using the Industry (2-digit code), Subsector (4-digit code) and NAICS title (6-digit code) might be the way to go, sometimes you might want to bypass this complex search if you know ahead of time your business’ NAICS code and have it auto populated for you.

In this article I will demonstrate the prep work that I did in order to have the NAICS codes stored within the Model-Driven app, and how to create the PowerApps Component Framework custom control that will retrieve the NAICS code.

The first thing that I needed to do was create the entities that will store the NAICS information. I created three separate entities for Industry, subsector and NAICS codes/titles. The image below shows that entities that are used as part of this solution. The account entity is used to display the custom control.

Entity List
Next, I will show the data that makes up these three entities. You will see the 4-digit and 6-digit NAICS codes have lookups to the parent entities to simplify the entry and search process.

Industries [2-digit NAICS]
Industries

Subsectors [4-digit NAICS]
Subsectors

NAICS Titles [6-digit NAICS]
NAICS title

Once we have created the entities and the fields in the 3 lookup entities, we will create the fields in the account entity where they can be viewed from. The two images below will show the fields and the form design.

Account Entity NAICS related fields:
Account Entity fields
Account Entity form design:
Account Entity form design
Now that we have done all the prep work, we are ready to start creating our new PowerApps Component Framework custom control. In this post, I will go through a step by step explanation create the PCF control and deploy it to your Model-Driven app/CDS environment.

I will be using Visual Studio Code for the development of the PCF control, and Developer PowerShell for Visual Studio 2019. You can use the Command Prompt for Visual Studio 2017/2019 as well.

The first thing that we need to do is download and install Node.js and the PowerApps Command Line Interface. For Step by step instructions, please view the PCF Control Guide.

To start we will create a folder on our workstation where we want to store the PowerApps Component Framework custom control project. In our case we used the D:PowerPlatformPCFNAICSGenerator folder. Once this folder has been created, we open Visual Studio Code, and from the Start page, we select Open Folder and point it to the folder that we created for this solution.

Next, we select Terminal from the View menu in order to allow us to run PowerShell commands to add the required components, test and build the solution. The first command that we will need to run is the pac pcf init command, which will create the manifest and typescript files for us.
PAC PCF Init

After the project has been created, you can navigate to the project directory, and you will notice that a subfolder with the name of the component has been created. The subfolder contains the ControlManifest.Input.xml and index.ts files.

We can now go ahead and install all the required dependencies that are required. This steps can take a few minutes to complete. The command to install the dependencies is npm install. While this task is executing you will see progression on your command prompt window, and you might see a few warnings or errors.
NPM Install

You will notice in Visual Studio code that a node_modules folder was created with a lot of subfolders containing script files. This contains a large variety of available modules that can be added to your typescript project.
Next, we will need to update the manifest file to include the required control and properties. The below shows the final view of the manifest file.

<?xml version="1.0" encoding="utf-8" ?>
<manifest>
  <control namespace="PCFControls" constructor="PCFNaicsCodeSplitter" version="0.1.1" display-name-key="PCFNaicsCodeSplitter" description-key="PCFNaicsCodeSplitter description" control-type="standard">
    <property name="NAICSCode" display-name-key="PCFNaicsCodeSplitter_NAICSCode" description-key="NAICS Code Field" of-type="SingleLine.Text" usage="bound" required="true" />
    <property name="NAICS2Control" display-name-key="PCFNaicsCodeSplitter_NAICS2Control" description-key="NAICS2 Control Field Name" of-type="SingleLine.Text" usage="input" required="true" />
    <property name="NAICS4Control" display-name-key="PCFNaicsCodeSplitter_NAICS4Control" description-key="NAICS4 Control Field Name" of-type="SingleLine.Text" usage="input" required="true" />
    <property name="NAICS6Control" display-name-key="PCFNaicsCodeSplitter_NAICS6Control" description-key="NAICS6 Control Field Name" of-type="SingleLine.Text" usage="input" required="true" />
    <resources>
      <code path="index.ts" order="1"/>
      <css path="pcfcontrols.css" order="1" />
    </resources>
    <feature-usage>
      <uses-feature name="WebAPI" required="true" />
      <uses-feature name="Utility" required="true" />
    </feature-usage>
  </control>
</manifest>

You will notice in the above file that the control has 4 properties. The first property contains the bound control that contains the 6 digit NAICS code that the user will type. The next 3 properties are text fields that contain single like of text, which contain the names of the three lookup controls. Lookup controls are currently not available for use as bound controls within PCF solutions.

You will also see that we include the WebApi and the Utility features. These features allow us to call the classes of the Xrm namespace which contain the methods for accessing the WebApi and Utility methods.

We not start making changes to the typescript file in order to provide the functionality that we are looking for. Note that the typescript contains several parameters that were used for testing and debugging purposes, and can be removed if so required.
We will first look at the variable declarations of the class.

    private _context: ComponentFramework.Context<IInputs>;
    private _notifyOutputChanged: () => void;
    private _container: HTMLDivElement; 
    
    private _naicsCodeElement: HTMLInputElement;
    private _naicsCodeErrorElement: HTMLElement

    private _naicsCodeChanged: EventListenerOrEventListenerObject;
    private _naics6id: string;

    private _naics2FieldName: string | null;
    private _naics4FieldName: string | null;
    private _naics6FieldName: string | null;

The variable declarations include the default context, notifyOutputChanged and container parameters, as well as the HTML elements, event listener object and other string variables. These variables will be initialized in the init function.

    public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container:HTMLDivElement)
    {
        // Add control initialization code
        this._context = context; 
        this._notifyOutputChanged = notifyOutputChanged; 
        this._container = container;

        this._naicsCodeChanged = this.naicsCodeChanged.bind(this);

        // textbox control
        this._naicsCodeElement = document.createElement("input");
        this._naicsCodeElement.setAttribute("type", "text");
        this._naicsCodeElement.setAttribute("placeholder", "Enter a 6 Digit NAICS Code");
        this._naicsCodeElement.setAttribute("class", "pcfinputcontrol");
        this._naicsCodeElement.addEventListener("change", this._naicsCodeChanged);

        this._naicsCodeErrorElement = document.createElement("div");
        this._naicsCodeErrorElement.setAttribute("class", "pcferrorcontroldiv");
        var naicsErrorChild1 = document.createElement("label");
        naicsErrorChild1.setAttribute("class", "pcferrorcontrolimage")
        naicsErrorChild1.innerText = "";

        var naicsErrorChild2 = document.createElement("label");
        naicsErrorChild2.setAttribute("id", "errorelementlabelid");
        naicsErrorChild2.setAttribute("class", "pcferrorcontrollabel");
        naicsErrorChild2.innerText = "Invalid NAICS Code Entered";

        this._naicsCodeErrorElement.appendChild(naicsErrorChild1);
        this._naicsCodeErrorElement.appendChild(naicsErrorChild2);
        this._naicsCodeErrorElement.style.display = "none";

        this._container.appendChild(this._naicsCodeElement);
        this._container.appendChild(this._naicsCodeErrorElement);   

        this._naics2FieldName = context.parameters.NAICS2Control.raw;
        this._naics4FieldName = context.parameters.NAICS4Control.raw;
        this._naics6FieldName = context.parameters.NAICS6Control.raw;
    }

The init function contains the variable initialization, creation of child elements (such as error element), and reading of the names of the fields used for the 3 lookup controls.
The naicsCodeChanged function below retrieves the data from the HTML element, and calls the RetrieveNAICSReferences function passing to it the 6 digit NAICS code. After this is complete the nofifyOutputChanged function is called.

    public naicsCodeChanged(evt: Event):void
    {
        var naicsCode = this._naicsCodeElement.value;
        console.log(naicsCode);
        this.RetrieveNAICSReferences(naicsCode);
        this._notifyOutputChanged();
    }

The RetrieveNAICSReferences function call the WebApi to retrieve the values of the NAICS 2, 4 and 6 lookups from the NAICS6 – Title entity.

    private RetrieveNAICSReferences(naicsCode : string) {
        var entityName = "cdsp_naics6title";
        var retrieveMultipleOptions = "?$select=_cdsp_naics2_value,_cdsp_naics4_value,cdsp_naics6titleid,cdsp_title&$filter=cdsp_number eq '" + naicsCode + "'";
        var thisRef = this;
        this._context.webAPI.retrieveMultipleRecords(entityName, retrieveMultipleOptions).then(function (results: any) {
            for (let entity of results.entities) {
                var naics2Value = entity["_cdsp_naics2_value"];
                var naics2Text = entity["_cdsp_naics2_value@OData.Community.Display.V1.FormattedValue"];

                var naics4Value = entity["_cdsp_naics4_value"];
                var naics4Text = entity["_cdsp_naics4_value@OData.Community.Display.V1.FormattedValue"];
                
                var naics6Value = entity["cdsp_naics6titleid"];
                var naics6Text = entity["cdsp_title"];

                // @ts-ignore
                Xrm.Page.getAttribute(thisRef._naics2FieldName).setValue([{ id: naics2Value, name: naics2Text, entityType: "cdsp_naics2industry" }]);

                // @ts-ignore
                Xrm.Page.getAttribute(thisRef._naics4FieldName).setValue([{ id: naics4Value, name: naics4Text, entityType: "cdsp_naics4subsector" }]);

                // @ts-ignore
                Xrm.Page.getAttribute(thisRef._naics6FieldName).setValue([{ id: naics6Value, name: naics6Text, entityType: "cdsp_naics6title" }]);
                break;
            }
        }, function (error) {
            thisRef._context.navigation.openAlertDialog(error.message);
            return [];
        });
    }

We retrieve each of the three values and call the setValue function on each of the lookup fields. The reason for using this is the bound attributes are not yet available for lookup controls.
We call the updateView to display any errors that might have occurred. In this solution we have not really captured any errors.

    public updateView(context: ComponentFramework.Context<IInputs>): void
    {
        // Add code to update control view

        // Display Error
        if (this._naicsCodeErrorElement.style.display != "none")
        {
            var message = "The NAICS COde  is not valid.";
            var type = "ERROR";  //INFO, WARNING, ERROR
            var id = "9443";  //Notification Id
            var time = 5000;  //Display time in milliseconds
            
            // @ts-ignore 
            Xrm.Page.ui.setFormNotification(message, type, id);
            
            //Wait the designated time and then remove the notification
            setTimeout( function () {
            // @ts-ignore 
                Xrm.Page.ui.clearFormNotification(id);
            }, time );

        }       
    }

Finally in the getOutput we return the value of the 6 digit search code:

    public getOutputs(): IOutputs
    {
        return {
            NAICSCode: this._naics6id
        };
    }

The last two method which are not commonly used are the construction and destructor as shown below:

    constructor()
    {

    }

    public destroy(): void
    {
        // Add code to cleanup control if necessary
        this._naicsCodeElement.removeEventListener("change", this._naicsCodeChanged);
    }

Once all the code is done we can test the application and run it. Since this application uses WebApi, this cannot be tested properly from within the context of the PowerApps Component Framework Test environment, but we can still do this by passing some sample data.

The command to build to solution is npm run build, and in order to run it within the Test environment it is npm start.

npm run build, npm start

We not open Developer PowerShell for VS2019, create a directory for the solution (can be called solution or something similar) and will run various commands within that new empty directory. You can create a powershell script file so that you don’t have to redo this, as every time that you will have to run this, it will save you some time.

Build Solution

Once the solution has been we are ready to deploy it. Again here, there are a couple of calls that have to made in order to have the completed deployment.

We will call the pac auth create and pac pcf push to deploy the solution to our CRM environment.

pac auth create –url https://pcfapps.crm.dynamics.com
pac pcf push –publisher-prefix PCFC

Once the solution is deployed, we will open that account form, and configure the control. Within the account form, select the control, and double click or click and choose properties. This will open the control’s property window. Within the property window we will click on the Controls tab, and choose Add Control, and then add the control that we created. The window should look similar to what is displayed below.

Field Properties

The next three images show us how the controls look on the form and the result.

NAICS PCF Step 1

NAICS PCF Step 2

NAICS PCF Step 3

You can download the lab instructions, source code and solution using the links below:

Dynamics 365 Solution file

PCF Control Source Code files

The post Creating a NAICS Code PCF Control using WebApi appeared first on Aric Levin's Digital Transformation Blog.

]]>
Creating a simple canvas app component http://aric.isite.dev/powerplatform/powerapps/post/create-canvas-app-component/ Sun, 08 Sep 2019 19:08:00 +0000 https://aric.isite.dev/index.php/2019/09/08/creating-a-simple-canvas-app-component/ As part of the 2019 October Release (Wave 2), Microsoft is introducing PowerApps Canvas App Components. Canvas App Components are reusable components that can be shared across multiple screens of your app, without the need to create or copy the component across the multiple screens. Create once, and use multiple times. Canvas App components can also be imported and exported, so that they can be used across multiple applications. This post will demonstrate how to create a simple component, add custom properties and use it from within your Canvas application

The post Creating a simple canvas app component appeared first on Aric Levin's Digital Transformation Blog.

]]>
As part of the 2019 October Release (Wave 2), Microsoft is introducing PowerApps Canvas App Components. Canvas App Components are reusable components that can be shared across multiple screens of your app, without the need to create or copy the component across the multiple screens. Create once, and use multiple times. Canvas App components can also be imported and exported, so that they can be used across multiple applications. This post will demonstrate how to create a simple component, add custom properties and use it from within your Canvas application

At the time of writing this post, Canvas App Components are in Preview, and must be enable via the App Settings. In order to enable Components, Navigate to File -> App Settings and select Advanced Settings from there. In Advanced Settings, under Experimental Features, change the slider under Components from Off to On. Once this is done, go back to your application, and you will see that Components are now available under the Tree View and in the Insert menu.

Canvas App Component Menu

To Start creating your Canvas App Component, click on the Components menu  in the Insert Tab and Select New Component. You can also import a component from that menu. Alternatively in the Tree View, if you click Components Tab, you can choose New Component as well. Once you click on the New Component link, it will open up a new Screen where you can develop your Component. For this sample, we will create a Screen header containing custom text, and two icons, one which will contain a link to navigate to a different Screen.

Add a Textbox and set a background color for it, a Home icon and a User icon as shown in the below image.
Canvas App Component

The next thing that we need it to set the Text and the link for the Home page to be Dynamic, so that it can be set from any screen where the component was added to.
In the Tree View, under components, click on the name of the new component (in this case called HeaderComponent). In the Component Details on the right hand side, click on New custom property, under the CUSTOM PROPERTIES section.
Add New custom property

When you click on the New custom property, the New custom property panel will show up. Here we specify a Display Name, Name and Description for the new property. We also need to select whether the property is an Input or Output property. Input properties receive data from the app, whereas Output properties send data back to the app. In our case lets enter the following as in the screenshot below. As this is a Label/Textbox, we will set the Data Type as Text.
Available Date Types include: Text, Number, Boolean, Date and Time, Screen, Record, Table, image, Video/Audio, Color and Currency. The image below shows you how to add those Custom properties.
Canvas App Component Custom Properties
NOTE: The names that I used for the application where this is used are Header Text and Home Screen. If you follow the directions, please replace the Display name and Name fields to match the table below.

Header Text Property Home Screen Property
Display Name Header Text Home Screen
Name HeaderText HomeScreen

Click on the Textbox Control within the Component. Select the Text Property, and in the function enter HeaderComponent.HeaderText – (1). This is the name of your component, followed by the name of the custom property. This will show the proper label for each screen in the header of the Component. Do the same for the Home Screen icon. Select the OnSelect Property/Action, and in the function enter Navigate(HeaderComponent.HomeScreen, ScreenTransition.None) – (2). This will make sure that clicking on the Home button will navigate to the proper screen.
Component App Property functions

At this point, the component is done, and you can use it within your Canvas App. Of course you can extend it as much as you need.
Click on the Screens navigation in your Tree view. On the Insert Menu, under Components, you will now see one additional menu item on top named HeaderComponent. This is the name of the component you just created. Select it, and place it on the top of your screen. When you click on the Component within your app, your will see in the properties window on the right the Custom Properties. Enter the Header Text and Home Screen properties.

Component Displayed within App Screen

That’s basically it. You can now add the component to every screen of your application, without having to write additional custom logic. This was a simple component, but you can extend it to perform most of the functions that you need.
For the full information of creation of components in Canvas Apps, visit the Microsoft Docs website.

The post Creating a simple canvas app component appeared first on Aric Levin's Digital Transformation Blog.

]]>
Error Notification UCI Enhancements in October Release http://aric.isite.dev/dynamics/post/error-notifications-uci-enhancements-wave2/ Fri, 30 Aug 2019 19:00:00 +0000 https://aric.isite.dev/index.php/2019/08/30/error-notification-uci-enhancements-in-october-release/ As part of the October 2019 release (Wave 2), the Unified Interface will receive a few usability enhancements that will address some of the issues that were reported by the community. These enhancements include: Anchoring error notifications, Viewing inline images for emails that are read-only, Improved usability/density and filtering in views and form header usability enhancements.

The post Error Notification UCI Enhancements in October Release appeared first on Aric Levin's Digital Transformation Blog.

]]>
As part of the October 2019 release (Wave 2), the Unified Interface will receive a few usability enhancements that will address some of the issues that were reported by the community. These enhancements include: Anchoring error notifications, Viewing inline images for emails that are read-only, Improved usability/density and filtering in views and form header usability enhancements.

Anchoring error notifications
Error notifications get displayed on the form prior to saving the data. When you have multiple errors you will see the error notification banner showing that you have multiple errors.
Multiple Error Notifications

Clicking on the error notification banner, will expand and show you the individual errors.
Expanded Error Notifications

If you click on either of those errors, the application will redirect you to the field that has the issues, where it can be fixed.
Selecting an Error

Once the error is fixed the message will go away. When there is only a single error left, it will show a single notification about the error, and not a notification that there are multiple errors left:
Single Error

If you try to navigate away from the page, it will display a dialog saying that you have unsaved changes. The dialog provides you with the choice to discard the changes, or to Save and Continue. Save and Continue will keep you on the page until your errors have been fixed, or will save your changes and navigate away to the page that you selected (if there are no errors). Discard changes will ignore any unsaved changes on your page.
Navigate Away

After the last error is resolvedyou should be able to save the record. As shown in the screenshot below, after the record is saved.
All Errors Resolved

The post Error Notification UCI Enhancements in October Release appeared first on Aric Levin's Digital Transformation Blog.

]]>
Lead Qualification Updates in Wave 2 http://aric.isite.dev/dynamics/post/lead-qualification-wave2/ Mon, 26 Aug 2019 06:27:00 +0000 https://aric.isite.dev/index.php/2019/08/26/lead-qualification-updates-in-wave-2/ Over the past 10 years almost CRM had gone through many revisions and features, and one of the things that has changed multiple times is the lead qualification and conversion process. The idea behind this is to reduce the work effort.

The post Lead Qualification Updates in Wave 2 appeared first on Aric Levin's Digital Transformation Blog.

]]>
Over the past 10 years almost CRM had gone through many revisions and features, and one of the things that has changed multiple times is the lead qualification and conversion process. The idea behind this is to reduce the work effort.

In CRM 2011, when the user would click on the Qualify button, a popup window would appear, where the user would have the option to convert the Lead into an Account, a Contact and/or an Opportunity.

If the Account would be checked, an Account record would be created from information in the Lead form. If a Contact would be checked, a Contact record would be created from the information in the Lead form.

If an Opportunity is checked, and you did not select an Account or Contact as well, then the Potential Customer is required in order to convert the lead into the Opportunity. If the Account and/or Contact are checked as well, that information will be used in the Opportunity record.

Qualify Lead (CRM 2011)

That is old news, as this functionality was changed in CRM 2015. In CRM 2015 (all the way to Dynamics 365 v9), the popup was removed, and the qualification was based on the logic and the information in the Lead entity.

The fields Existing Account and Existing Contact fields would specify whether the lead is using an existing customer which would determine what would be used to Create the Opportunity. If the information in the existing Account and existing Contact lookup fields do not contain any data, upon Qualification, the Account and Contact record would be created. The duplicate detection rules would of course kick in if the information in the Company Name and Email address fields match existing Accounts or Contacts.

Qualify Lead (CRM 2015)

Now, in 2019 Wave 2, this is changing again, and it seems like we have found a middle ground. Microsoft is simplifying the lead management experience by first autopopulating contact and company related fields when the existing account and/or existing contact fields are selected. The notes and attachments captured in the lead phase will be displayed in the opportunity as well.

Finally we come back to the popup. The popup is back, but can be configured not to be displayed based on organization settings.

Qualify Lead (Wave 2 - Admin Setting)
If selected to be displayed, the only questions that would be displayed is Yes/No questions whether or not to create an Account, a Contact and/or an Opportunity when the lead is qualified.

Qualify Lead (Dynamics 365 - 2019 Wave 2)

Let’s hope that this is a viable solutions for most organizations. I know that for some of my projects, we had to come up with alternatives to some of the newly created OOB functionality, and am definitely glad of this additions to the product.

The post Lead Qualification Updates in Wave 2 appeared first on Aric Levin's Digital Transformation Blog.

]]>
Microsoft Dynamics 365 and Power Platform 2019 Release Wave 2 http://aric.isite.dev/dynamics/post/dynamics365-powerplatform-2019-wave2/ Thu, 08 Aug 2019 08:15:00 +0000 https://aric.isite.dev/index.php/2019/08/08/microsoft-dynamics-365-and-power-platform-2019-release-wave-2/ The Microsoft Dynamics 365 2019 Release Wave 2 is not available for early adopters. The release is scheduled to start deployment to production environments starting in October of 2019. During August and September, Microsoft Dynamics customers check out the upcoming list of updates that will be released in October.

The post Microsoft Dynamics 365 and Power Platform 2019 Release Wave 2 appeared first on Aric Levin's Digital Transformation Blog.

]]>
The Microsoft Dynamics 365 2019 Release Wave 2 is not available for early adopters. The release is scheduled to start deployment to production environments starting in October of 2019. During August and September, Microsoft Dynamics customers check out the upcoming list of updates that will be released in October.

A total of 74 new features will be released across the different Microsoft Dynamics 365 applications and the Power Platform. You can check out the full list of features by viewing the Microsoft Dynamics 2019 Release Wave 2 Documentation.

Amongst the newly released features are enhancements to the Timeline control, Softphone dialer, Business card scanner, customization of the Opportunity Close dialog box. In addition to that, the Power Platform is getting quite a few additions including the addition of AI Builder, PowerApps Portals,  UI improvements to Unified Interface, Reusable Canvas components and more.

Dynamics 365/Power Platform 2019 Release Wave 2

To view the full release plan for Dynamics 365 and the Power Platform, click on the links below:

Dynamics 365 2019 Release Wave 2

Power Platform 2019 Release Wave 2

The post Microsoft Dynamics 365 and Power Platform 2019 Release Wave 2 appeared first on Aric Levin's Digital Transformation Blog.

]]>
PowerApps Screen with Add New and Edit Mode http://aric.isite.dev/powerplatform/powerapps/post/powerapps-contact-manager-addnewform-editgallery/ Tue, 18 Jun 2019 05:04:00 +0000 https://aric.isite.dev/index.php/2019/06/18/powerapps-screen-with-add-new-and-edit-mode/ I recently ran into a requirement to do a PoC on a PowerApps to be able to add and update records in a single screen in PowerApps. In order to implement the PoC I decided to test this out on the Contact Entity in a Dynamics 365 environment. I did not make any changes to the Contact Entity, but just used some of the Out of the Box fields. In order to implement this, I wanted to get a look and feel of a form that would look the same whether entering new information or editing existing information.

The post PowerApps Screen with Add New and Edit Mode appeared first on Aric Levin's Digital Transformation Blog.

]]>
I recently ran into a requirement to do a PoC on a PowerApps to be able to add and update records in a single screen in PowerApps. In order to implement the PoC I decided to test this out on the Contact Entity in a Dynamics 365 environment. I did not make any changes to the Contact Entity, but just used some of the Out of the Box fields. In order to implement this, I wanted to get a look and feel of a form that would look the same whether entering new information or editing existing information.

We start by creating a blank Canvas up using the Tablet layout. This will open a blank screen. On the screen we see the message Add an item from the Insert tab or connect to data. We click on connect to data, and select either new connection if you don’t see your dynamics 365 connection from there, or if it is displayed click on the connection. Select the connection (and authenticate if required), select the dataset (instance) and then in the Choose a table, select the Contacts entity. Click on Connect. The image below shows you the Data sources window after you connected to the environment.

Add Data Source

The next thing that we are going to do is add the header of the application. We do this by adding a label and a few icons that will each perform an individual action. As a good practice, use actual names for the screen and controls that you add to the form. There is no logic implemented yet. We then add just labels to the top of the page that will hold the fields that we want (in our case it is First Name, Last Name, Mobile Phone, Email Address, Job Title and Department), and separate them across the form. The image below shows you the customized labels and icons that we added to the form.

Header

After adding the labels and icons, it is time to add the form and gallery. We start by adding a form. On the Insert Tab we will add a new form. We set the data source to Contacts and add the fields required by clicking the Edit fields link on the Properties window. We set the # of column to 12, Vertical Layout, and the Default Mode to New. You can customize the look and feel as needed.

By default, when adding a new form, each field will have a label associated with it. Since we want to use a single layout for Adding and Editing the fields, we will hide the fields, and just use the actual input controls for each data card. We do this by clicking on the DataCardKey label for each of the for attributes that we added, and setting the Visible property to Off and the Height to 0, so that it is not visible on the form. We then customize the form fields so they appear as a single line by modifying the size and the position of each data card. The result will look like this:

Add New Form

Finally we will add the gallery. We use a Blank Gallery layout, and set the data source to the Contacts data source. We add one field at a time as Text Input controls and associate them with the correct field and position that we added to the for the form. This will give us a look and feel that is similar to a grid containing a top row to add new data, and the rest of the rows for editing existing data.

It is not time to start adding the functionality to the icons, form and gallery. We will first add two global variables to the App. In the App OnStart function we will Set the following variables:

Set(NewDisplayMode, DisplayMode.Disabled); Set(EditDisplayMode, DisplayMode.Disabled);

This will create two new variables, once for the display mode of creation of new records, and the other for the display mode for editing existing records. This was my PoC requirements, so yours might be different.

Next, we will set the all of the fields to the display mode variables that we created, so that when new forms are created, it forces us to choose the action that we want to perform, such as New Record, Edit, Cancel or Save. We would loop through all the input controls in the Form and Gallery, and set their DisplayMode to either NewDisplayMode for the Form or EditDisplayMode for the gallery.

Display Modes

Next we will add logic to each of the icons that we added to the header (shown in the table below):

Icon

Code Logic

Add New

UpdateContext({NewDisplayMode: DisplayMode.Edit}); UpdateContext({EditDisplayMode: DisplayMode.Disabled})

Edit

UpdateContext({NewDisplayMode: DisplayMode.Disabled}); UpdateContext({EditDisplayMode: DisplayMode.Edit})

Cancel

UpdateContext({NewDisplayMode: DisplayMode.Disabled}); UpdateContext({EditDisplayMode: DisplayMode.Disabled})

Save

If (NewDisplayMode = DisplayMode.Edit,

    If (!IsBlank(LastNameField) && !IsBlank(EmailAddressField),

        SubmitForm(AddNewForm); ResetForm(AddNewForm); Refresh(Contacts),

        Notify(“Cannot create record. Missing data.”, NotificationType.Error)),

    true);

UpdateContext({NewDisplayMode: DisplayMode.Disabled}); UpdateContext({EditDisplayMode: DisplayMode.Disabled})

Reload

Refresh(Contacts)

We are now ready to test the application. The animated gifs below shows how the application runs:

Add New Record Animated Gif

Edit Record Animated Gif

You can download a copy of the solution from here. After importing the solution to your environment, you might have to make some configuration changes to your Dynamics365 environment. The purpose of the linked download is for informational and educational purposes only and not intended to be a full solution. We will post the full solution on github and a later date.

The post PowerApps Screen with Add New and Edit Mode appeared first on Aric Levin's Digital Transformation Blog.

]]>