Thursday, December 19, 2024

Example of Advanced UI customization in PowerApps, using custom HTML, CSS, and JavaScript

PowerApps Canvas Apps Customization

PowerApps Canvas Apps allow limited customization directly with HTML, CSS, and JavaScript. However, you can use HTML Text Controls, integrate PowerApps Portals for advanced customization, or use Power Automate with Azure Functions for JavaScript-like logic. Here's an example of advanced UI customization using HTML web resources in a PowerApps Canvas App:

Scenario

Create a responsive and visually appealing data table with Search/Filtering Functionality using advanced HTML and CSS styling embedded in a PowerApps Canvas App.

Steps to Implement

1. Design Your HTML/CSS Web Resource

Create an HTML file with embedded CSS for a styled table. Save it as a web resource in your Dataverse environment.

Example HTML (HTML File):

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
    }

    .custom-table-container {
      margin: 20px;
      overflow-x: auto; /* Enables horizontal scrolling on smaller screens */
    }

    .search-container {
      margin: 10px 20px;
      text-align: right;
    }

    .search-input {
      width: 100%;
      max-width: 300px;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 5px;
      font-size: 16px;
    }

    .custom-table {
      width: 100%;
      border-collapse: collapse;
      margin: 20px 0;
    }

    .custom-table th,
    .custom-table td {
      border: 1px solid #ddd;
      padding: 10px;
      text-align: left;
    }

    .custom-table th {
      background-color: #0078D7;
      color: white;
    }

    .custom-table tr:nth-child(even) {
      background-color: #f2f2f2;
    }

    .custom-table tr:hover {
      background-color: #ddd;
    }

    /* Responsive Styles */
    @media (max-width: 768px) {
      .custom-table th,
      .custom-table td {
        font-size: 14px;
        padding: 8px;
      }
    }

    @media (max-width: 480px) {
      .custom-table th,
      .custom-table td {
        font-size: 12px;
        padding: 6px;
      }

      .custom-table-container {
        margin: 10px;
      }
    }

    @media (max-width: 320px) {
      .custom-table th,
      .custom-table td {
        font-size: 10px;
        padding: 4px;
      }
    }
  </style>
</head>
<body>
  <div class="search-container">
    <input
      type="text"
      id="searchInput"
      class="search-input"
      placeholder="Search the table..."
      onkeyup="filterTable()"
    />
  </div>

  <div class="custom-table-container">
    <table class="custom-table" id="dataTable">
      <thead>
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Value</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>1</td>
          <td>John Doe</td>
          <td>100</td>
        </tr>
        <tr>
          <td>2</td>
          <td>Jane Smith</td>
          <td>200</td>
        </tr>
        <tr>
          <td>3</td>
          <td>Sam Wilson</td>
          <td>150</td>
        </tr>
        <tr>
          <td>4</td>
          <td>Sara Connor</td>
          <td>180</td>
        </tr>
      </tbody>
    </table>
  </div>

  <script>
    function filterTable() {
      // Get the input field and its value
      const input = document.getElementById("searchInput");
      const filter = input.value.toUpperCase();

      // Get the table and rows
      const table = document.getElementById("dataTable");
      const rows = table.getElementsByTagName("tr");

      // Loop through all rows (skip the header row)
      for (let i = 1; i < rows.length; i++) {
        const row = rows[i];
        let isVisible = false;

        // Check each cell in the row
        const cells = row.getElementsByTagName("td");
        for (let j = 0; j < cells.length; j++) {
          const cell = cells[j];
          if (cell) {
            const text = cell.textContent || cell.innerText;
            if (text.toUpperCase().indexOf(filter) > -1) {
              isVisible = true;
              break;
            }
          }
        }

        // Show or hide the row based on the match
        row.style.display = isVisible ? "" : "none";
      }
    }
  </script>
</body>
</html>

2. Add a JavaScript File for Dynamic Data

Create a JavaScript file that injects data dynamically into the table.


function populateTable(data) {
  const tableBody = document.getElementById("data-table").querySelector("tbody");
  tableBody.innerHTML = ""; // Clear existing rows

  data.forEach(row => {
    const tr = document.createElement("tr");
    Object.values(row).forEach(value => {
      const td = document.createElement("td");
      td.textContent = value;
      tr.appendChild(td);
    });
    tableBody.appendChild(tr);
  });
}

3. Host the HTML/JS Resources

  • Upload the HTML and JavaScript files as web resources in Dataverse.
  • Copy the URLs of the hosted files.

4. Embed HTML in PowerApps

  1. Add an HTML Text Control in your Canvas App.

  2. Embed the URL of your hosted HTML file inside the control.

    Example for the HTMLText property:

    "<iframe src='https://<your-hosted-html-file-url>' width='100%' height='400px' frameborder='0'></iframe>"

5. Pass Data from PowerApps to HTML

To dynamically populate the table:

  1. Add a Power Automate Flow or use an API to pass the data to your web resource.
  2. For example, use the following pattern in your Canvas App:

    Set(dataPayload, JSON(DataSource));
    HtmlTextControl.HtmlText = 
        "<script>" & "populateTable(" & dataPayload & ");" & "</script>";

Key Features

  • Table columns dynamically.
  • Case-insensitive search.
  • Responsive layout for both the search bar and table.

Thanks for visiting!

Monday, July 13, 2020

Dynamics 365: Set Lookup Field To Current User on Selection of an OptionSet using JavaScript

Approval Type Scenario

Approval Type Automation in PowerApps

Yesterday, one of my LinkedIn connections asked me to help with a business scenario:

Business Scenario

The scenario involved two fields in a Business Process Flow:

  • Approval Type (optionset)
  • Approved By (systemuser lookup)

If Approval Type is set to "Approved," the Approved By field should automatically set its value to the current logged-in user.

Implementation in PowerApps Model-Driven App

You can achieve this functionality using a combination of JavaScript and event handlers. Here's how:

Steps to Implement:

  1. Create a JavaScript Web Resource:
    • Go to Solutions in the PowerApps Maker portal.
    • Add a JavaScript web resource to your solution.
    • Write JavaScript code to check the value of the Approval Type field and set the Approved By field to the current logged-in user.
  2. Add the Script to the Form:
    • Open the entity form where the Approval Type and Approved By fields exist.
    • Go to Form Properties.
    • Add the JavaScript web resource you created to the form.
  3. Add an Event Handler:
    • In the same Form Properties, go to the Event Handlers section.
    • Attach the setApprovedByOnApprovalTypeChange function to the OnChange event of the Approval Type field.
    • Ensure you pass the executionContext to the function.
  4. Publish Customizations:
    • After adding the event handler, save and publish the form.

Sample Code Snippet


function setApprovedByOnApprovalTypeChange(executionContext) {
    var formContext = executionContext.getFormContext();

    // Get the value of the Approval Type field
    var approvalType = formContext.getAttribute("approvaltype").getValue(); // Replace 'approvaltype' with your field's schema name

    // Check if Approval Type is "Approved" (value may vary based on your option set)
    if (approvalType === "Approved") { // Replace with the correct option value for "Approved"
        // Get the current logged-in user
        var currentUserId = Xrm.Utility.getGlobalContext().userSettings.userId;
        var currentUserName = Xrm.Utility.getGlobalContext().userSettings.userName;

        // Set the Approved By field
        formContext.getAttribute("approvedby").setValue([
            {
                id: currentUserId,
                entityType: "systemuser",
                name: currentUserName
            }
        ]);
    } else {
        // Clear the Approved By field if Approval Type is not "Approved"
        formContext.getAttribute("approvedby").setValue(null);
    }
}

        

Thursday, August 30, 2018

Top 250+ Microsoft Dynamics 365 Interview Questions ONLY

Microsoft Dynamics 365 Interview Questions

Microsoft Dynamics 365 Interview Questions

General Overview

  1. Tell me something about Dynamics CRM.
  2. Tell me something about Dynamics CRM Architecture.
  3. Tell me something about Dynamics CRM Deployment Models.
  4. Tell me the differences between Dynamics CRM – Online and On-Premises Deployment.
  5. Tell me something about Dynamics 365 On-Premises licensing.
  6. What is Multi-Tenancy in Dynamics CRM?

Authentication and Installation

  1. What is the E-mail router in Dynamics CRM?
  2. What are the User Authentication Models of Dynamics 365?
  3. On install of Dynamics CRM, what databases are created?
  4. On install of Dynamics CRM, what user groups are created in Active Directory?

Data and Entity Management

  1. What Tables are affected when a new User is created in Dynamics CRM?
  2. Certain users are complaining that they are unable to log in to CRM after organization export/import. What could be the reason?
  3. What are the types of Entities in Dynamics CRM?

Forms and Views

  1. What are Forms in Dynamics 365?
  2. What are Dynamics CRM Form Properties?
  3. What are the available JavaScript Events in Dynamics CRM?
  4. What are Turbo Forms in Dynamics CRM 2015 Online Update 1 and CRM 2016 On-Premise?
  5. What are the types of Views available in Dynamics CRM?

Development and Customization

  1. FetchXML in Dynamics 365 CRM
  2. Actions in Dynamics CRM
  3. Dialogs in Dynamics CRM
  4. When is a Dialog useful in Dynamics CRM?
  5. What is a Solution in Dynamics CRM?
  6. How to move the Main Form Only from a CRM instance to another instance?
  7. Converting Managed Solution to Unmanaged Solution in Dynamics CRM?

Web Services and APIs

  1. Dynamics CRM - Web Services
  2. Difference between CRM webservice and CRM.SDKProxy namespaces?
  3. SOAP vs. REST Endpoints Services in Dynamics CRM
  4. What is early binding and late binding? How is it used in CRM?

Troubleshooting and Best Practices

  1. Dynamics CRM Pending Send Status Emails Troubleshoot
  2. Best practices for activities and notes in Dynamics 365
  3. Dynamics CRM is down and not working. Common Causes to Check?

Security and Access

  1. Tell me something about the Security model of Dynamics CRM.
  2. What are the fundamental units of the security model of Dynamics CRM?
  3. What are some best practices for designing a security model in Dynamics CRM?
  4. How do Business Unit and Security Role define the security structure of Dynamics CRM?
  5. Access Dynamics CRM from an external application.

Entities and Fields

  1. How many ways to hide a field in a CRM form?
  2. What are Dynamics CRM Field Types and Data Types?
  3. What are Dynamics CRM Field Properties?
  4. Rollup Fields in Dynamics CRM.

Customization and Configuration

  1. How do you estimate CRM customizations?

Processes and Workflows

  1. Dynamics 365 Process Categories?
  2. How would you implement Recurring Task Activities using Workflows in Dynamics 365?
  3. How would you implement Recursive Workflows in Dynamics 365?
  4. Business Process Flow Stage Name in Dynamics 365.

Plugins and Development

  1. How many possible ways to register a Plug-in in Dynamics CRM?
  2. Plug-in Assembly Table in Dynamics CRM.
  3. How to move the Production CRM database into Development or Testing?
  4. What development tools do you use for CRM development?

Reporting and Analytics

  1. Reporting in Dynamics 365.
  2. Scheduling Reports in Dynamics CRM 2016 On-Premise.
  3. Scheduling Reports in Dynamics 365 Online.
  4. Advanced Find and Reports in Dynamics CRM.
  5. Creating an Audit Report for User Logins in Dynamics CRM.
  6. Activity Reporting gotchas in Dynamics CRM.

Data Migration and Performance

  1. Overcome CRM Slowness and Optimization of Performance in Dynamics CRM.
  2. Data Migration Testing Best Practices in Dynamics 365.

Active Directory and Customization

  1. Should my Active Directory Domain have Microsoft Exchange Server installed in it?
  2. What is Customization vs. Configuration?

Entity Management

  1. On the creation of an Entity, how many Tables are created at the backend?
  2. On the creation of an Entity, how many Forms, Fields, and Views are automatically created?
  3. After creating a new Entity, what are the things that you do? Explain as per your experience.
  4. How many fields can you create in an Entity?
  5. How to restrict any 'Entity Field' from being shown in Advanced Find?
  6. How to restrict any 'Entity Field' from being shown in Advanced Find using a Field Security Profile?
  7. How to restrict an 'Entity' from being shown in Advanced Find?

Security and Access

  1. How can you provide access level as only “None” or “Organization Level”?
  2. What is the difference between Role-Based and Object-Based Security Models?
  3. What is the difference between Business Units and Teams?
  4. Have you ever used the Hierarchical Security Model? What was the business reason?
  5. What is Field Level Security?
  6. What is the behavior of Field Level Secured Fields?
  7. What are 'Append' and 'Append To' privileges?
  8. How would you prevent a user from Activating or Deactivating a Record?

Teams and Access

  1. What is the difference between Owner Teams and Access Teams?
  2. Explain scenarios where you would use Owner Team vs. Access Team.
  3. How many types of Access Teams are available?
  4. What are the PROS and CONS of Access Teams' performance?
  5. What is the PrincipalObjectAccess table, and why is it used?

Entity Relationships

  1. What are the Entity Ownership Types?
  2. What is the Virtual Entity feature?
  3. Can you list a few limitations of Virtual Entities?
  4. What is the difference between Organization-Owned and User/Team-Owned Entities?
  5. When should you repurpose System Entities vs. creating Custom Entities?
  6. Explain Entity Relationships.
  7. What is Relationship Behavior?

Forms and Views

  1. Can you give examples of useful Data Field Types?
  2. What is a Read-Only or Read-Optimized Form?
  3. How many ways can you hide a form?

Miscellaneous Topics

  1. Files and how they are stored in Dynamics 365/CRM
  2. Where can I find the attachment files from emails in the CRM database?
  3. Multi-Select Option Set Limitations in Dynamics 365 CRM?
  4. Full Text Search (CRM On-Premises Only)
  5. Did you use any Automated Testing in Dynamics CRM Testing Strategy?
  6. Difference b/w Dynamics 365 (on-premises) and Dynamics CRM 2016 (on-premises)
  7. Dynamics CRM 2016 (On-Premise) vs Dynamics 365 CRM
  8. What tool do you use for Wireframing Dynamics 365?
  9. Do you have a few key best practices someone considering CRM can use?
  10. How do you keep up with Microsoft Dynamics CRM news?

Thursday, September 19, 2013

Capitalize First String Character of a word in Text Field of Dynamics CRM 2011

So, One of the Post in LinkedIn asking if anyone can help with a Script that can Capitalize First String Character of a word in Text Field of Dynamics CRM 2011.

For eg. If i have a custom Full Name Field or Address filed. If User enters like 1107 medowville lane,
The script should automatically converts it to Pascal Casing like, 1107 Medowville Lane.

I thought to give it a try and here is the full functional code.

function ConvertFirstCharToCaps()
{
var attribute = Xrm.Page.getAttribute("new_address"); // Change the Schema Name here

if(attribute != null)

var str = attribute.getValue();
    var pieces = str.split(" ");
    for ( var i = 0; i < pieces.length; i++ )
    {
        var j = pieces[i].charAt(0).toUpperCase();
        pieces[i] = j + pieces[i].substr(1);
    }

Xrm.Page.getAttribute("new_address").setValue(pieces.join(' '));
 
}

It can be converted to Parametrized Function, but here i am just giving an idea how this code can work on each field.

Hope this will help, Please change the Attribute name as per your Attribute Schema Name.

Thanks.

Wednesday, July 24, 2013

Prevent Users to Delete the Task if "Owner" of the Task is not the "Created by" of the Task using Plug-in in Dynamics CRM 2011

Requirement :  Prevent Users to Delete the Task if "Owner" of the Task is not the "Created by" of the Task using Plug-in in Dynamics CRM 2011.
On click of Delete button on Ribbon from anywhere Form, Subgrid, HomeGrid, if the Task "Owner" is not Same as Task "Created By" then Owner should be prevented from Deleting the Task with a User Friendly Message.
Implementation:
The Complete Code for the Plug-in to prevent an Owner to Delete the Task:

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.CSharp;
using System.Data;
using System.Runtime.Serialization;
using Microsoft.Crm.Sdk.Messages;
namespace TaskDeleteCheck
{
    public class PreventTaskDeletion : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            if (context.PrimaryEntityName == "task")
            {

                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)

                {
                    if (context.PreEntityImages.Contains("PreImage"))
                    {

                        Entity taskentity = (Entity)context.PreEntityImages["PreImage"];

                        EntityReference owneridLookup = (EntityReference)taskentity.Attributes["ownerid"];
                        EntityReference createdbyLookup = (EntityReference)taskentity.Attributes["createdby"];

                        if (owneridLookup.Id != createdbyLookup.Id)

                        {
                           throw new InvalidPluginExecutionException("This task is Created by : " + createdbyLookup.Name + " ,  User : " + owneridLookup.Name + " is not allowed to Delete the Task.");
                        }
                    }
                }
                else
                {
                    throw new InvalidPluginExecutionException("Activity should be task.");
                }

            }


        }

    }
}

The Plugin has to use Pre-Image to compare the values of the fields before transaction happens in the Database.

Now the Registration Process of Plug-in:


Open the Plugin registration Tool, Select your Organization, Log as Admin user (Or if any user has granted permission). 


1. Register New Assembly by browsing your dll.

2. You have to Register steps for the plugin on Delete step.
3. Register Pre-Image for the above step.





Once done, you are now Ok to test your business scenario,

Following are the screen shots, on Single Task and Multiple Tasks Closure Process from the CRM Landing Page (In My case Dashboard):

Single Task Selected:



Multiple Selection of Task:




Delete from the Ribbon Button the Task Form:





That's All.

Thank You for looking at my post.

Cheers!!!

Sunday, July 21, 2013

Prevent Users to Mark Complete or Close the Task if "Owner" of the Task is not the "Created by" of the Task using Plug-in in Dynamics CRM 2011

Requirement :  Prevent Users to Mark Complete or Close the Task if "Owner" of the Task is not the "Created by" of the Task using Plug-in in Dynamics CRM 2011.
On Click of Mark Complete on Ribbon button from anywhere in CRM Webpage (Form, Subgrid, HomeGrid), if the Task "Owner" is not Same as Task "Created By" then Owner should be prevented from Mark the Task Complete or Close with a User Friendly Message and and also a custom field on Task form called "Able to Mark complete" if the value of the Check box is true (Yes) then to override this requirement, i mean user can Mark Complete or Close.
Implementation:
First Create a Javascript to control the enabling and disabling of "Able to Mark complete" field on the Update form of Task. This field will be enabled for Creator of the Task on Create or Update form, but if the Owner of the Task is not the Creator of the Task then this field should be prevented to update on Update form of Task entity. Here is the JavaScript code to do so (I am avoiding the step to Add the JavaScript as web-resource and Attaching the code to Task form).
function DisableAbleToCompleteField()
{

var  formType = Xrm.Page.ui.getFormType();

   if (formType == 2)
   {
      var userid = Xrm.Page.context.getUserId();
      var creatorlookup = Xrm.Page.getAttribute("createdby");
      if (creatorlookup!= null)
      {
         var creatorlookupvalue = creatorlookup .getValue();
         if (creatorlookupvalue != null)
         {
              var creatorid = creatorlookupvalue[0].id;
          }
       }
                if (userid == creatorid) 
                  Xrm.Page.getControl("new_abletomarkcomplete").setDisabled(false);
           else       
                  Xrm.Page.getControl("new_abletomarkcomplete").setDisabled(true);
          
    }   else        
 Xrm.Page.getControl("new_abletomarkcomplete").setDisabled(false);
}

The Complete Code for the Plug-in to prevent an Owner to Mark Complete or Close the Task:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.CSharp;
using System.Data;
using System.Runtime.Serialization;
using Microsoft.Crm.Sdk.Messages;

namespace TaskClosurePermissionPlugin

{
    public class TaskClosure : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            if (context.PrimaryEntityName == "task")
            {

                if (context.InputParameters.Contains("EntityMoniker") && context.InputParameters["EntityMoniker"] is EntityReference && context.Depth < 2)

                {
                    if (context.PreEntityImages.Contains("PreImage"))
                    {

                        Entity taskentity = (Entity)context.PreEntityImages["PreImage"];

                        EntityReference owneridLookup = (EntityReference)taskentity.Attributes["ownerid"];
                        EntityReference createdbyLookup = (EntityReference)taskentity.Attributes["createdby"];
                       
                        if (owneridLookup.Id != createdbyLookup.Id)
                        {
                            if (taskentity.Contains("new_abletomarkcomplete") && !taskentity.GetAttributeValue<bool>("new_abletomarkcomplete"))
                            {
                                throw new InvalidPluginExecutionException("This Task is Created by : "+createdbyLookup.Name+" ,  User : "+owneridLookup.Name +" is not allowed to Mark Complete or Close the Task.");
                            }
                        }
                    }
                }
                else
                {
                    throw new InvalidPluginExecutionException("Activity should be Task.");
                }

            }


       }

    }
}

The Plugin has to use Pre-Image to compare the values of the fields before transaction happens in the Database.
Now the Registration Process of Plug-in:
Open the Plugin registration Tool, Select your Organization, Log as Admin user (Or if any user has granted permission). 
1. Register New Assembly by browsing your dll.
2. You have to Register steps for the plugin on SetState and SetStateDynamicEntity both steps.
3. Register Pre-Image for both Steps.


Once done, you are now Ok to test your business scenario,

Following are the screen shots, on Single Task and Multiple Tasks Closure Process from the CRM Landing Page (In My case Dashboard):

Single Task Selected:



Multiple Selection of Task:


Mark Complete from the Task Form:


That's All.

Thank You for looking at my post.

Cheers!!!



Enhancing Model-Driven App Views with Custom Column Icons

Enhancing Model-Driven App Views with Custom Column Icons A Hidden Feature That Can Make Your Views Much More User-Friendly I came acro...