Progressive Web Apps (PWAs)

As an introduction to PWAs, let’s build a mobile app the fastest, easiest way, using the Progressive Web App model. A PWA is both a mobile app and a website. Built with HTML, CSS, and javascript, the website can be viewed as either a website on your laptop or a mobile app on your phone or tablet. No need to develop a separate native app for every platform!

Creating Website with Addition of JavaScript files app will behave "app-like"

What does “App-like” mean? PWAs can work on your phone or tablet so much like a native app, it is hard to see the difference. Twitter produces both, a native app you can find in your app store, and a PWA you can “install” from browsing to Check out images of each:

Natie iPhone App vs. PWA -

A PWA can even access device hardware like the camera or microphone! They can produce push notifications and work offline. How does it do these things? It’s all in the site javascript and structure. It is the best way to build a mobile app. Let’s see how this works.

PWA Goals

To work like a native app, the PWA website has to:

  • Work offline
  • Perform fast
  • A display like a native app, responsive, with no browser UI visible
  • Startup from an icon on your home screen


Why and when would we want to create a PWA?

  • Fast deployment: Avoids submission to the app stores for review and approval
  • Quicker updates are published immediately because it is served on the web and so no need to wait for the user to download to their device
  • More discoverable: Users can find and link to it via search engines
  • Secure: They use the browser security model, so providing the security of operating within the web browser context
  • Connectivity independent: PWAs can function on very low bandwidth or no connection at all.
  • Installable: Like a mobile app, this is opened from an icon on the home screen.
  • Notifications: Can send push notifications to the device like a native app
  • Hardware access: Can use the mobile device camera, microphone, etc.


“Progressive” in the name refers to that it will work and display in all browsers to a varying degree. Because it is browser dependent, it is affected by the capability of which browser the user has, and what version. PWAs have a goal to display and function at least minimally in all browsers, regardless of version. As such they become progressively more feature-rich in newer versions.


The Progressive Web App concept was created by Google in 2015. Its roots go even further back though, to Steve Jobs’ introduction of the iPhone in 2007. He declared back then that development for the iPhone would be done in html5 and have no SDK. His vision was undermined by iPhone jailbreaking which forced Apple to retreat to having an SDK and app store. But the concept lived on and is seeing increasing life in the PWA model.

Let’s Build One

We will look at how to use a manifest and service worker to create a very simple application that provides the features of a PWA. This is exciting to see on your phone, in action!
In your development environment, create a folder in your local for your project, name it anything, and add subfolders for js and images, and an index.html file:

Application Providing Features of a PWA

This demo was edited VS Code and the site was served on IIS in Windows but any favorite editor and dev web server will be fine. Node.js http-server is another easily available web server you could use. The file index.html should look like this, to start. We’ll add more later:

<!doctype html>
<html lang="en">
  <meta charset="utf-8">
  <title>Hello My Phone</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
<body class="fullscreen">
  <div class="container">
    <h1 class="title">Hello My Phone!</h1>

Run the app now in your webserver to see how it is shaping up. So far this is just a web app. Push it to your GitHub Pages repo to see it run on the web. To add mobile app functionality, we need to add two files, a Service Worker and a manifest.

Service Worker and Manifest

These change the app from a simple web app to one that can behave like a mobile app, a Progressive Web App. The Service Worker is the middleman between the web page and content. It contains the code to determine whether to deliver static, cached content or dynamic data based on whatever criteria you want, typically whether it finds a connection to the internet or not. The manifest is a json file that provides properties to the browser such as which page to load when the app is first opened, or what is the title of the app. Both the manifest and the service worker live on the root directory for access.

Create a file named manifest.json in the root of the site, and add the following:

  "name": "My Phone App",
  "short_name": "My App",
  "icons": [{
    "src": "images/phoneapp-icon-128.png",
      "sizes": "128x128",
      "type": "image/png"
    }, {
      "src": "images/phoneapp-icon-144.png",
      "sizes": "144x144",
      "type": "image/png"
    }, {
      "src": "images/phoneapp-icon-152.png",
      "sizes": "152x152",
      "type": "image/png"
    }, {
      "src": "images/phoneapp-icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    }, {
      "src": "images/phoneapp-icon-256.png",
      "sizes": "256x256",
      "type": "image/png"
    }, {
      "src": "images/phoneapp-icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
  "description": "Sample Progressive Web App",
  "lang": "en-US",
  "start_url": "index.html",
  "display": "standalone",
  "background_color": "white",
  "orientation": "any",
  "theme_color": "white"

Link the manifest file in your index.html file, in the head section:

&lt;link rel="manifest" href="/manifest.json"&gt;

Service Worker

To add the service worker, create a file in the root folder named sw.js. Add the following to it:

var cacheName = 'phoneApp';
var filesToCache = [

/* Start the service worker and cache files in filesToCache */
self.addEventListener('install', function(e) {
  e.waitUntil( {
      return cache.addAll(filesToCache); 

/* Serve cached content when offline */
self.addEventListener('fetch', function(e) {
    caches.match(e.request).then(function(response) {
      return response || fetch(e.request);

Adding a service worker is the first step towards enabling the following progressive web app features:

  • Offline performance
  • Push notifications
  • Add icon to the home screen

Our service worker file caches specifically named pages to be able to serve them from the cache when the device is offline. The file must be placed in the app root to allow it access to all of the app’s files. Service workers only have permission to access files in their same-level directory and subfolder. In the first function of the sw.js, the first item in the variable filesToCache is “./” because that allows caching of our index.html. The cacheName variable adds the content to the browser cache to be available to be called from the javascript. The following function fetches the cached content. This file works for our demo but to properly fortify the app with error handling and to see what else the service worker can do, check out PWABuilder. It is a handy file generator for your PWA, but even if you don’t use the generator, just looking at this site sums nicely what you can define in the manifest and service worker and what they can do. For now, we’ll keep our service worker simple.

Register the Service Worker

We need one more file to call, or “register”, the service worker. Create a javascript file in your js folder named main.js. This tells the browser where to find your service worker JavaScript file. Add the following:

window.onload = () =&gt; {
‘use strict’;

if (‘serviceWorker’ in navigator) {

Link to main.js at the bottom of index.html by adding a script link before the closing body tag:

<script src="js/main.js"></script>

App Icons

We need to provide icons that various displays can use, to support the mobile app experience of having an app icon on the device. Images of varying sizes are defined in the manifest above. We will put these images in the Images folder to be available to display the home screen icon when users “install” your app. Sample images for these and for favicon.ico are included in the downloadable files (link below). The file structure looks like this now:

Production of App Icons

Add Responsive HTML

To see the best effect of your sites’ web vs mobile view, add some responsive elements and styles to index.html. This example uses the free W3 Schools templates. It links to their online w3.css stylesheet for responsive styles. A link to the W3 Schools templates is included in the links at the end of this post along with a link to download the project files.

With the addition of the html below, our site now has navigation and layout that changes based on the viewport. The HTML now looks like this:

<!doctype html>
<html lang="en">
  <meta charset="utf-8">
  <title>PWA Sample</title>
  <link rel="manifest" href="manifest.json">
  <link rel="stylesheet" href="css/style.css"> <!-- optional -->
  <link rel="stylesheet" href="">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="theme-color" content="white"/>
  <link rel="icon" href="favicon.ico" type="image/x-icon" />  
<link rel="apple-touch-icon" href="images/pwa-icon-152.jpg">   
<meta name="theme-color" content="white"/>  
<meta name="apple-mobile-web-app-capable" content="yes">  
<meta name="apple-mobile-web-app-status-bar-style" content="black"> 
<meta name="apple-mobile-web-app-title" content="Hello World"> 
<meta name="msapplication-TileImage" content="images/pwa-icon-144.jpg">  
<meta name="msapplication-TileColor" content="#FFFFFF">
<body class="fullscreen">
<!-- Sidebar/menu -->
<nav class="w3-sidebar w3-collapse w3-top w3-large w3-padding" style="z-index:3;width:300px;font-weight:bold; background-color:#ddd;" id="mySidebar">
  <a href="javascript:void(0)" onclick="w3_close()" class="w3-button w3-hide-large w3-display-topleft" style="width:100%;font-size:22px">Close Menu</a>
<div class="w3-container">
<div style="width: 120px; height:119px; background-color: #fff;">
  <img src="images/logo.jpg"</div>
<div class="w3-bar-block">
    <a href="#" onclick="w3_close()" class="w3-bar-item w3-button w3-hover-white">Home</a> 
    <a href="#sectionOne" onclick="w3_close()" class="w3-bar-item w3-button w3-hover-white">Section One</a> 
    <a href="#sectionTwo" onclick="w3_close()" class="w3-bar-item w3-button w3-hover-white">Section Two</a> 
    <a href="#simpleForm" onclick="w3_close()" class="w3-bar-item w3-button w3-hover-white">Contact</a>
<!-- Top menu on small screens -->
<header class="w3-container w3-top w3-hide-large w3-grey w3-xlarge w3-padding">
  <a href="javascript:void(0)" class="w3-button w3-grey w3-margin-right" onclick="w3_open()">☰</a>
  <span>My Mobile App</span>

<!-- Overlay effect when opening sidebar on small screens -->
<div class="w3-overlay w3-hide-large" onclick="w3_close()" style="cursor:pointer" title="close side menu" id="myOverlay"></div>
<!-- !PAGE CONTENT! -->
<div class="w3-main" style="margin-left:340px;margin-right:40px">
<!-- Header -->
  <div class="w3-container" id="showcase">
   <h1 class="w3-xxlarge">My Mobile App</h1>
   <h1 class="w3-large w3-text-gray"><b>Lorem dolor etc!</b></h1>
<!-- Photo grid (modal) -->
<div class="w3-row-padding">
<div class="w3-half">
      <img src="images/circle1.jpg" style="width:100%" onclick="onClick(this)" alt="It's a photo">
      <img src="images/circle4.jpg" style="width:100%" onclick="onClick(this)" alt="It's a photo">
<div class="w3-half">
      <img src="images/circle3.jpg" style="width:100%" onclick="onClick(this)" alt="It's a photo">
      <img src="images/circle2.jpg" style="width:100%" onclick="onClick(this)" alt="It's a photo">
  <!-- Top Section -->
<div class="w3-container" id="sectionOne">
<h1 class="w3-large w3-text-gray"><b>Section One</b></h1>
  Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
<!-- Section of Text -->
<div class="w3-container" id="sectionTwo">
<h1 class="w3-large w3-text-grey"><b>Section Two</b></h1>
 Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
<b>All The Things:</b>
  <!-- Images in Boxes -->
<div class="w3-row-padding w3-grayscale">  
  <div class="w3-col m4 w3-margin-bottom"> 
   <div class="w3-light-grey">     
     <div class="w3-container">
        <h3>Thing 1</h3>Thing 1 Phasellus eget enim eu lectus faucibus vestibulum. Suspendisse sodales pellentesque elementum.
<div class="w3-col m4 w3-margin-bottom">
  <div class="w3-light-grey">
    <div class="w3-container">
       <h3>Thing 2</h3>Thing 2 Phasellus eget enim eu lectus faucibus vestibulum. Suspendisse sodales pellentesque elementum.
<div class="w3-col m4 w3-margin-bottom">
   <div class="w3-light-grey">
     <div class="w3-container">
       <h3>Thing 3</h3>Thing 3 Phasellus eget enim eu lectus faucibus vestibulum. Suspendisse sodales pellentesque elementum.
<div class="w3-container" id="simpleForm" style="margin-top:75px">
My Form   
   <form action="/myformaction.js" target="_blank">
     <div class="w3-section">
      <input class="w3-input w3-border" type="text" name="Name" required>
     <div class="w3-section">
       <input class="w3-input w3-border" type="text" name="Email" required>
     <div class="w3-section">
       <input class="w3-input w3-border" type="text" name="Message" required>
     <button type="submit" class="w3-button w3-block w3-padding-large w3-grey w3-margin-bottom">Send Message</button>
<!-- End page content -->
// Script to open and close sidebar
function w3_open() {
  document.getElementById("mySidebar").style.display = "block";
  document.getElementById("myOverlay").style.display = "block";

function w3_close() {
  document.getElementById("mySidebar").style.display = "none";
  document.getElementById("myOverlay").style.display = "none";
<script src="js/main.js"></script>

Install On Your Phone

Upload the files to a WebHost or browse to the localhost IP address in your wifi network, to try it on your phone. On the iPhone, browse to the URL and then choose the share button.

iOS Share button

From the context menu, choose “Add to home screen”. Android devices make this even easier by displaying a default button. See links at the end of this post for options to install on Android and other devices.


Progressive Web Apps offer the best of native mobile apps combined with the advantages of web development. Over time, the increasing embrace of PWA techniques by developers could bring Steve Jobs’ vision for smartphone applications to reality: no need for phone SDKs or and native app deployments or app store constraints, and a world in which web technology can be used to create mobile apps that are faster to build with every bit of functionality equal to their native counterparts.


More about installation of a PWA on other OSs:
Data Lake has become a mainstay in data analytics architectures. By storing data in its native format, it allows organizations to defer the effort of structuring and organizing data upfront. This promotes data collection and serves as a rich platform for data analytics. Most data lakes are also backed by a distributed file system that enables massively parallel processing (MPP) and scales with even the largest of data sets. The increase of data privacy regulations and demands on governance requires a new strategy. Simple tasks such as finding, updating or deleting a record in a data lake can be difficult. It requires an understanding of the data and typically involves an inefficient process that includes re-writing the entire data set. This can lead to resource contention and interruptions in critical analytics workloads.

Apache Spark has become one of the most adopted data analytics platforms. Earlier this year, the largest contributor, Databricks, open-sourced a library called Delta Lake. Delta Lake solves the problem of resource contention and interruption by creating an optimized ACID-compliant storage repository that is fully compatible with the Spark API and sits on top of your existing data lake. Files are stored in Parquet format which makes them portable to other analytics workloads. Optimizations like partitioning, caching and data skipping are built-in so additional performance gains will be realized over native formats.

DeltaLake is not intended to replace a traditional domain modeled data warehouse. However, it is intended as an intermediate step to loosely structure and collect data. The schema can remain the same as the source system and personally identifiable data like email addresses, phone numbers, or customer IDs can easily be found and modified. Another important DeltaLake capability is Spark Structured Stream support for both ingest and data changes. This creates a unified ETL for both stream and batch while helping promote data quality.

Data Lake Lifecycle

  1. Ingest Data directly from the source or in a temporary storage location (Azure Blob Storage with Lifecycle Management)
  2. Use Spark Structured Streaming or scheduled jobs to load data into DeltaLake Table(s).
  3. Maintain data in DeltaLake table to keep data lake in compliance with data regulations.
  4. Perform analytics on files stored in data lake using DeltaLake tables in Spark or Parquet files after being put in a consistent state using the `VACCUUM` command.

Data Ingestion and Retention

The concept around data retention is to establish policies that ensure that data that cannot be retained should be automatically removed as part of the process.
By default, DeltaLake stores a change data capture history of all data modifications. There are two settings `delta.logRetentionDuration` (default interval 30 days) and `delta.deletedFileRetentionDuration` (default interval 1 week)

ALTER table_name SET TBLPROPERTIES ('delta.logRetentionDuration'='interval 240 hours', 'delta.deletedFileRetentionDuration'='interval 1 hours')

Load Data in DeltaLake

The key to DeltaLake is a SQL style `MERGE` statement that is optimized to modify only the affected files. This eliminates the need to reprocess and re-write the entire data set.

MERGE INTO customers
USING updates
ON customers.customerId = updates. customerId
      UPDATE email_address = updates.email_address
      INSERT (customerId, email_address) VALUES (updates.customerId, updates.email_address)

Maintain Data in DeltaLake

Just as data can be updated or inserted, it can be deleted as well. For example, if a list of opted_out_consumers was maintained, data from related tables can be purged.

MERGE INTO customers
USING opted_out_customers
ON opted_out_customers.customerId = customers.customerId



In summary, Databricks DeltaLake enables organizations to continue to store data in Data Lakes even if it’s subject to privacy and data regulations. With DeltaLakes performance optimizations and open parquet storage format, data can be easily modified and accessed using familiar code and tooling. For more information, Databricks DeltaLake and Python syntax references and examples see the documentation.

Implementing a cloud strategy and modernization of legacy systems are two of the core objectives of most IT organizations. Purchasing a COTS product or SaaS offering can speed up modernization and come with a lot of advantages. COTS products come with a proven track record and address specific business needs that would be difficult to justify building your own. COTS product shifts the liability of creating features to the COTS product instead of your organization. Finally, COTS products promise a shorter timeframe to implementation. Even though you’ll be purchasing a solution to 80% of your problem with the COTS product, the hardest parts of implementing a COTS product are still your responsibility. Below are some key areas you will still own.

Security and Infrastructure

Security and Infrastructure are your responsibility. Off the shelf product or Software as a Service (SaaS) product won’t address this. If this is a SaaS product, how will your Hybrid network access it and how is that access govern? You’ll need to do a risk assessment of this SaaS product which includes how you connect to it, how it stores its data, and even how it’s creating the software. If this is an off the shelf product, how will it be installed in the cloud? Ask if it can is cloud-native or does it need to run on virtual machines in the cloud. If it’s running on virtual machines are those hardened and who have access to them. Cloud virtual machines complicate networking since they need to be accessed from on-prem and they may still need to reach into the cloud or the internet. That can leave a wide surface vector you’ll need to account for. Security and Infrastructure is the biggest concern and you’ll need to own it.


One of the promises of moving to the cloud is gaining business agility. Automation is a key component for reaching that goal. SaaS product removes the burden from deploying and maintaining the application, but there may still be a necessity to automate some aspects. For example, if the SaaS product must be configured, it might have a UI and an API for doing this. It’s in your best interest to involve this SaaS Product into your normal development pipeline and consider infrastructure as code as it applies to the SaaS product. If you purchase a COTS produce be sure you can stand up an entire environment including installation of this product with a click of a button. There is no excuse for not automating everything and there are plenty of tools in the Azure DevOps pipeline for integration and automation.


COTS product provides 80% of the functionality needed, but what about the other 20%? The remaining functionality the product doesn’t provide is likely what differentiates your company from the others. There are always edge cases and custom functionalities that you’ll want, that either the vendor does not provide or it’s expensive for the vendor to implement. You’ll need to bring that work in-house or hire a system integrator to hook things together. Whether it’s a SaaS product or a COTS product, integration to applications that provide the remainder of your functionally is your responsibility as well as understanding how integration will work when purchasing the COTS product. A good COTS product will have a solid HTTP REST API. If the product you’re purchasing doesn’t have a simple API, consider a wrapper to make the integration easier. API Management is an Azure service that can do that translation for you. You might find that you want to combine COTS API to one that makes sense to the rest of the systems. Large COTS products should also support messaging of some kind. Messaging helps build loosely coupled components with high cohesion. COTS products might offer file-based and database integration. However, these should be avoided. Integration of the COTS product is your responsibility and the effort can equal the implementation effort of the COTS product itself.


COTS products can provide great benefits to your company and welcome new functionality quickly. Understand that your IT department will still have to drive the overall architecture and you are responsible for everything around the COTS product. The bulk of this work will fall under Security, Infrastructure, Automation, and Integration. Focus on these concerns and you’ll have a successful implementation.

An issue often faced when writing a client for an API, is how to best go about programmatically when interacting with it. You could write your own HttpClient calls, use a 3rd-party library like RESTSharp, or hope that someone has already produced an SDK for your target client language/framework. In this case .NET. Refit steps in to solve the problem of SDK development. Inspired by Square’s Retrofit library, Refit turns a REST API into a live interface.

In this blog post, I will walk you through creating both a basic SDK and client for a Todo Item API. This example assumes that a company has created the Todo API and SDK, while the client would be built by an external user.

Note: All example code for this post can be found at


The purpose of this post is primarily for SDK development, as opposed to API, so I will briefly go over the API being used in this example:

API use example


This project contains versioned request and response classes as well as a class to hold all our API routes. In a real-world example, this project would exist as a NuGet package. It may seem overkill to do this for a project with one controller and a handful of endpoints, when it comes time to create the SDK and client you will see how having the requests and responses in their own project, simplifies the process.


This project is a .NET Core 3.1 Web API with a SQL Server (localdb) database.


To begin, we will create an empty class library project to house our SDK. Next, remove the default Class1.cs and add in the ApiContracts project as a reference, as well as the Refit NuGet package.

Add APIcontracts

Refit NuGet package

Each controller in your API should map to an interface in your SDK. Our API only has one controller, TodosController, with the following endpoints:


Let’s create an interface for this controller. First, add a new interface named ITodoApi in the SDK project. The interface will look very similar to our controller above. For example, to create our GetAll SDK call, add the following to ITodoApi:

Todos API

The Get attribute comes from the Refit package and functions in the same manner as the HttpGet attribute in our controller. Please note, however, that for Refit, we have to supply the route as a literal string. Trying to reference the ApiRoutes class will result in an error at runtime when building the client.

GetAllAsync returns a list of TodoResponse objects wrapped in Refit’s ApiResponse class. The ApiResponse class contains the following properties:

API response class

When writing a client using our new SDK development process, our TodoResponse object will be stored in the Content property which we will look at in the next section.

To complete our interface, we add the remaining endpoints:

Add remaining end points

We now have developed a basic SDK for our Todo API. All that’s left is to create our client.

SDK Client

Create a .NET Console application and add a project reference to our new SDK:

.NET console application

In Program.cs, update the signature of Main to async since we will be making asynchronous calls to our API. The next step is to create our API client class:

Update signature

Note: You will need to find the port Visual Studio has assigned to your API when specifying the hostUrl. In this case, it is 44311.

Now that the client has been created, we can walk through creating, retrieving, updating, and deleting a todo item. You will notice that our requests and responses all follow a similar pattern.

Create a Todo

Create a Todo

Update a Todo

Update a Todo

Delete a Todo

Delete a Todo

Retrieving all Todos

Retrieving all Todos

Testing the SDK Client

To test the client first start your Web API project, and then run the console application. You can set breakpoints at each step if you like and monitor the database to see the todo item being created, updated, and deleted. Otherwise, you will see an output as such:

Testing the SDK Client

Just as an example, I have also included a project named RefitSdkDemo.PlainClient which demonstrates how a consumer of the API would have to structure a create todo item request without the benefit of our new SDK:


And since we do not have access to the SDK, the CreateTodoRequest and CreateTodoResponse classes would have to be built by the downstream consumer, and would possibly need to be updated for newer API versions.


As you can see, Refit makes it quite fast and easy to build a strongly-typed SDK for your Web API. And since Refit targets .NET Standard 2.0, you can use it almost anywhere. It is also worth mentioning, that while we did not dive into it in this blog post, Refit does support adding custom headers to requests including OAuth bearer tokens.

While personnel management is a sub-category of Human Resources (HR) that only focuses on administration, the tasks and responsibilities can outstretch the duties of an HR manager. Personnel managers hold an important role by focusing on hiring and developing employees to become more valuable to the company.  

A few of these areas of interest include: 

  • Job analyses
  • Strategic personnel planning
  • Performance appraisals
  • Benefit coordination
  • Recruitment
  • Screening
  • New employee orientation
  • Training
  • Wages
  • Dispute resolution
  • Other record-keeping duties

PowerApps and Personnel Management 

Now I bet you’re thinking how this could tie in with PowerApps. With the various areas that a personnel manager can be involved in, doesn’t it make sense to have one application where everything exists? So that this busy personnel manager can easily navigate and participate in day-to-day duties with ease, get the job done more efficiently, and have it readily available for other team members to view and analyze.

How bizarre would it be if I told you we could build this application with little to no code and have it ready to be used in less than half the time it would take for a developer to code it from scratch? Not bizarre and very doable. With PowerApps, one can quickly build custom business applications that connect to your business data stored either in the data platform, Common Data Service for Apps, or in various online and on-premise data sources like Azure, SharePoint, Excel, Office 365, Dynamics, SQL Server, and so on.  

Why PowerApps?

Apps that are built using PowerApps transform your manual business processes to digital, automated processes. Even more good news – these apps will have a responsive design and can run on any browser or your mobile device. PowerApps will potentially alleviate the need to hire expensive custom developers and this will give you the power and tools necessary to move your business forward.

Let’s Take a Closer Look

If a personnel manager is doing the following, this is how PowerApps can be integrated:

Personnel Management Duty: Posting job ads, reviewing resumes, conducting interviews and making a final decision with management.

PowerApps Solution: This can be done through the Business Process Flow. As you can see with the example below, you will be able to ensure that users enter data consistently and are taken through the same steps every time they work through this type of process.

Stages in Business Process Flow

Personnel Management Duty: Analyze salary data and reports to determine competitive compensation rates.

PowerApps Solution: Power BI, a modern data visualization tool that can spot trends in real-time and make better, more informed decisions based on your specified dataset. This example below depicts the various ways to display data using custom visualizations. Imagine the possibilities!

Sales Dashboard

Personnel Management Duty: Develop and maintain a human resources system that meets the company’s information needs.

PowerApps Solution: Using Dynamics 365, an app within PowerApps. Through the unified interface, your organization will have an application that is easy to use with the flexibility to grow.

 Personnel Management Duty

Personnel Management Duty: Continually monitor changing laws, legislation movements, arbitration decisions and collective bargaining contracts.

PowerApps Solution: Dashboard management that Dynamics 365 offers can easily check for recent changes within your system.

Sales Activity Dashboard

Personnel Management Duty: Continually deliver presentations to management and executives regarding current and future human resources policies and practices.

PowerApps Solution: Use the PowerApps Unified Interface to present detailed reports, dashboards, and forms. You’ll be able to demonstrate the versatility of the application on various devices.

 Customizing Applications

PowerApps not only gives you the capability to drive your business growth but it also eases your mind on the ability to change, update, delete, and customize your application as you see fit. Personnel management is not a simple feat but, using PowerApps can make your mission more manageable while also keeping everything in one place.

In this article, I will show you how we can create reusable custom components in canvas apps. We will work on two simple limitations on the current controls in Canvas Apps and create custom components to overcome those limitations.

1. A specific range cannot be set on the date picker control that would limit the users from selecting dates from a specific range only.

2. Power Apps currently limits the text input control to two formats i.e., text and number. We will create a custom component to support ‘regex’ as a general setting that can be applied to multiple input fields of the same format. Let’s get started. We will first create the components and then see how to use them on the canvas app.

Creating Custom Components

To create the components in the Power Apps app studio, we first have to enable ‘Components’ in the experimental features tab from the advanced settings of the app.

Creating Custom Components

Date Picker

The current date control allows you to restrict only the year while configuring the control. Using already available controls, we can design a component for the date control that enables restricting to a range of dates. The display of the date control component is based on a gallery and is explained in detail here. We will start by creating a few custom properties for the component. The idea behind this date control is to enable functionality to restrict users to select the date from a specified range. For this, I created a “start date” and an “end date” property of data-type “date and time”. I have also added properties to customize the color of the different sub-controls of the component.

Date Picker

1. This is a label that displays the date selected from the custom date picker control component. The expression used on the “Text” property of this label:
Selected Date Label

2. This is an icon (‘calendar’) to expand the date picker. The expression used on the “OnSelect” property of this control:

Icon Calendar

Explanation: The visibility of the calendar is set here based on the “CalendarVisibility” variable. “SelectedRange” is a variable that sets the context for the appropriate month to be displayed on the date picker.

3. Upon clicking this icon, the user is navigated to the previous month. The expression used on the “OnSelect” property of this control is:

Previous Month Navigation

Explanation: This evaluates the month label based on the current month on the date picker and the result is the previous month w.r.t to the current month. The expression used on the “DisplayMode” property of this control:

Display Mode

4. This is a label control and displays the selected month and year on the date picker.

5. Upon clicking this icon, the user is navigated to the next month based on the current month. The expression used on the “OnSelect” property of this control is:

On Select

Explanation: This evaluates the month label based on the current month on the date picker and the result is the next month w.r.t to the current month. The expression used on the “DisplayMode” property of this control:

Display Mode

6. This is a gallery of buttons to show days week wise in a row. The expression used on the “OnSelect” property of the button inside of the gallery is:

On Select

Explanation: The “dateselected” variable value is set by clicking this button. The expression used on the “DisplayMode” property of this button control is:

Expression used on DisplayMode

Explanation: Here is the date validation that checks if the date is within the range of the “start date” and “end date” properties and is of the currently selected month. The expression used on the “Text” property of the button control is: (This expression has been referred from this reference link.)

Date Validation

Explanation: This gets the date as per the day from the date picker. The expression used on the “Items” property of the gallery control is: (This expression has been referred from this reference link.)

Items property gallery control

Explanation: This created the 42 cells for the date picker inside of the gallery control. The expression used on the “TemplateFill” property of the gallery control is:

Template Fill Property

Explanation: This highlights the currently selected item (date) in the gallery control.

The selected date from this component can be accessed through the “SelectedDate” property. Note: The color properties defined are used in the component on all the individual controls to sync the color coordination amongst them.


The current text input control allows you to choose the input text format as a number or text only. We can design a component that allows implementing regex and based on the property (formatting required) the text input can be formatted or restrict the user to input the text in the type defined in the component. If the input text does not match the type chosen on the component, the field is reset, and a warning message is displayed to the user.


7. This is a text input control and the text format is set through the “InputFormat” custom property created on this component. The expression used on the “OnChange” property of this control is:

Setting Text Format

Explanation: The “if” statement checks the “InputFormat” custom property for the text input against the respective regex statement and resets the input if the regex is not matched. The expression used on the “Mode” property of this control is:

Expression on Mode Property

Explanation: If the “InputFormat” on this component is set to “Password” then the mode will be set to password in order to mask the user input.

8. This is a label that is used to display the warning message to the user in case of a mismatch of the input based on the “InputFormat” property.

9. This is an icon used to display the warning sign to the user in case of a mismatch of the input based on the “InputFormat property.


This is an “InputFormat” and the regex that this type of input is being compared to is:

Input Format Comparison


This is an “InputFormat” and the regex that this type of input is being compared to is:

URL Input Format


This is an “InputFormat” and the regex that this type of input is being compared to is:

Password Input Comparison

The password should include at least one or more of an upper case, lower case letters, a number, and a special character.

Number Format:

Number Format

10. This is a label that displays the converted value based on the formatting defined for the input number. The expression used on the “Text” property of this control is:

Display Converted Value based on formatting

Explanation: If the text input is not empty, then the numbers entered will be formatted as “XXX-XXXXXX”

11. This is a text input control and the user will enter the number in this control. The “Format” property of this input is set to “Number” Note: The label in 10 is positioned in a way that it overlaps the text input control in 11. That is how the user can see the input formatted as set in the label.

Using the Custom Components

Currently, Power Apps restricts the use of a component in galleries, data cards, data tables, etc. We will design a custom sign up form and use the components created above to register a user and save the information on the data source.

Custom Sign Up Form

12. This is a regular text input field that will allow users to enter simple text. The property of this control is set to “text”.

13. This is a component that we have created earlier and the property for this is set to “URL”. When users enter the URL, it is matched against the regex and if it is not in a valid URL format the field is reset.

14. This field expects the input to be in the form of an email address. The component created earlier is used for this control and the property is set to “Email”. If the input does not match against the regex for email, the field will be reset and a warning message will be displayed.

15. The property on the component for this is set to “Password”. If the input does not match as the regex set for the password (as mentioned next to the “Password” label), the field will be reset and the warning message will be displayed.

16. This input field expects the input in the form of a “Phone Number” and appends the ‘-’ to the numbers entered based on the regex configured while creating the component.

17. The custom property created for the component can be set here. For each of the above fields, the type of input (regex expression) is defined by setting this property.

Sign Up Form18. This is the date control component and allows the user to pick a date by clicking on the calendar icon.

19. The custom properties for the date control component can be set here. The start date and the end date are configured to set a range of allowable dates. As an added feature, the colors for the individual controls within the date picker can also be configured here.

20. This is a clear field button and upon clicking this all the fields are cleared and the user creates a new entry.

21. This is a submit button and the user can submit their details by filling the form and pressing this button. Upon pressing this button, the details filled by the user are patched to the respective columns in the data source.

22. This is a warning generated for an inappropriate email address format that was entered by the user. As soon as the user clicks outside of this control, the field is reset.

23. This is the expanded date picker control and the dates that can be selected by the user are based on the start and end dates range configured in the app. The dates that cannot be selected are highlighted by the strikethrough and the buttons to navigate to the next/ previous months is disabled.

In this article, we have seen how we can create custom reusable components in canvas apps with low code and no code methodology. Components can be created with already available controls to overcome certain limitations and enhance the overall application.

In this post, I will show you how DevOps practices can add value to a variety of Office 365 development scenarios. The practices we will discuss are Infrastructure as Code, Continuous Integration, and Continuous Delivery. The advances in DevOps and SharePoint Framework (SPFx) have allowed us to make advancements in the way that we develop software and have improved our efficiency.

Infrastructure as Code (IaC)

Practicing IaC means that the infrastructure your applications depend on is created and maintained by code that is source controlled, tested, and deployed to production much like software. When discussing IaC, we’re typically talking about provisioning resources to a cloud provider. In our case, the “infrastructure” is Office 365 – a SaaS product with extensive customization and configuration options.  

While you could manage your O365 tenant with PowerShell, the code-centric and template-based PnP Provisioning Framework aligns better with this practice because: 

  1. Using the frameworks declarative XML syntax, you describe what you want to exist rather than writing code to manage how it gets created.
  2. It is easier for developers to run idempotent deployments to enact the desired state of your Office 365 tenant.  

While originally developed to support SharePoint Online and on-premise deployments, you can see in its latest schema that it has expanded to support Microsoft Teams, OneDrive, and Active Directory.  

Continuous Integration (CI) 

The practice of continuously integrating first means that your team has established the habit of frequently merging small batches of changes into a central code repository. Upon that merge, we automatically build and test the code to quickly identify bugs and quality issues.  

SharePoint Framework is a commonly used tool used to extend the capabilities of SharePoint Online and on-premise Much like the Provisioning Framework, SharePoint Framework is expanding to support other Office 365 services. You can currently use it to develop for Microsoft Teams and will soon be able to use it to develop Office Add-Ins.

Azure DevOps is a one-stop-shop service that provides everything you need throughout the software development lifecycle. For example, your team can version control your projects source code in Repos. After merging changes, use Pipelines to trigger a CI process that runs the build and test tasks of your SharePoint Framework solution.  

Continuous Delivery (CD)

Continuous Delivery, the practice of running automated deployments through a sequence of environments, starts after a completed CI process. Azure DevOps Pipelines will again be the tool of choice to execute the deployment procedures against each environment.

Example Solution

A solution demonstrating how to use the technologies and practices described above is available on Applied Information ScienceGitHub account. The result is a pipeline capable of receiving frequent changes to O365 configuration and SPFx applications from 1 or many developers, verifying the quality of the change, and deploying it to a series of environments.

Dev Tenant Diagram

I encourage you to explore the source code using the following summary as a guide. You’ll find the solution organized into three areas – SPFx, Provisioning, and Pipeline.


A simple hello world web part was created using the yeoman generator. Jest was added to test the code. Npm and gulp scripts are used to build and package the source code which produces an sppkg file.


The PnP Provisioning Template XML file found here defines the desired state of the target tenant. The following is the desired state:

  1. Install the SPFx App into the tenant App Catalog.
  2. Create a site collection that will host our web parts page.
  3. Install the SPFx App to the Site Collection.
  4. Create a page that will host our web part.
  5. Add the web part to the page.

By using parameters for the tenant URL and site owner, the same template can be deployed to multiple environments. A PowerShell build script bundles the template and all required files, such as the SPFx sppkg file, into a single pnp file ready for deployment.


A multi-stage YAML pipeline defined in the Pipeline folder of the example solution runs the following process:

  1. Build, test, and package the SPFx and Provisioning Template source code.
  2. Deploy the prerequisite SharePoint infrastructure to the tenant if it does not already exist.
  3. Install and configure the SPFx web part.
  4. Repeat #2 and #3 for all environments.

Build Process Diagram

Secret variables, such as the username and password used to connect to the tenant, are only referenced in the pipeline. The values are set and encrypted in the Azure DevOps pipeline editor.

Variables Diagram with Passwords


In the not-too-distant past, it was high effort to write unit tests for a SharePoint solution, and most deployments were manual. In this post, I have shown you how advancements in the platform and tooling have changed this. The mentality, practices, and tools brought by DevOps can improve the pace and quality of any software development and infrastructure management project, including projects building upon Office 365.

Rehosting Considerations

What is Rehosting?

Rehosting is an approach to migrating business applications hosted on-premises in data center environments to the cloud by moving the application “as-is,” with little to no changes to the functionality. A common rehosting scenario is the migration of applications that were initially developed for an on-premises environment to take advantage of cloud computing benefits. These benefits may include increased availability, faster networking speeds, reduced technical debt, and a pay-per-use cost structure.

In our experience, rehosting is well suited for organizations under time-sensitive data center evacuation mandates, facing pressure from leadership to migrate, running COTS software that doesn’t support modernization, or those with business-critical applications on end-of-support technologies. These organizations often opt for a rehost then transform strategy, as reviewed in the following blog, Cloud Transformation Can Wait… Get Me to the Cloud Now!

Below we outline important considerations, benefits, and challenges associated with a rehost strategy, based on our real-world experiences moving both custom and packaged commercial on-premises applications to the cloud. We’ll also discuss steps to take when your migration initiative goes beyond rehosting, requiring the assessment of alternative migration approaches, such as re-platforming and refactoring.

Critical Considerations

When moving on-premises business-critical applications to the cloud, there are critical considerations that span technical, operational, and business domains. Below are three key components not to be overlooked when defining your cloud migration strategy:

  • Establishing a shared vision: Ensuring you have set goals and an executive sponsor.
  • Understanding your why: Why are you migrating to the cloud in the first place?
  • Defined business impact: What impact do you expect from your migration efforts and are your goals realistic based on the chosen approach?

Establishing a Shared Vision

Establish a Shared Vision with Stakeholders

The landscape of on-premises systems is often governed by many stakeholders, both business and IT, with competing goals, risk profiles, and expected outcomes from a migration effort. Having a clear vision for your rehost initiative with key roles and responsibilities defined is critical to the timeliness, investment, and overall success of your project. Finding an executive sponsor to unite the various groups, make decisions, and define the business goals and expected outcomes is vital in risk management.

As part of creating this shared vision, the executive sponsor needs to ensure:

  • Goal Alignment: Having a shared vision among various business and IT stakeholders set direction and expectations for the project. A shared vision allows all parties, including vendors and internal resources, to understand the goal(s) and the role they’ll play for the project.
  • Sufficient Budgeting and Resource Allocation: Appropriate budget and resources must be allocated for executing tasks related to this partnership, before the start of the migration effort to ensure timely project completion.
  • Proper Documentation of Existing Systems: Critical information about on-premises systems and operations is often either insufficient or missing entirely. System documentation is mandatory to migrate systems and uphold their intended purpose.
  • Product Ownership: On-premises business application suites are often acquired or internally developed. Original vendors may be out of business, so products are no longer viable. Conversely, the custom product may no longer be supported or understood due to missing source code. An owner needs to be designated to determine the future of the product.
  • Organizational Change Management: Without user adoption, your cloud migration will fail. Change management efforts enable cloud technology adoption and require proper planning and execution from the start.

The considerations outlined above should be discussed up front, and partnerships among stakeholder groups must be established to accomplish the intended goal(s) of migration under executive sponsor leadership.

Understand Your Why

Understand Why You're Moving

You’ve heard the stories about failed cloud migrations. Those stories often start with misaligned expectations and a rushed execution, which are among the top reasons cloud migrations result in a backslide to on-premises environments. Migrating to the cloud isn’t a silver bullet – not every organization will experience cost savings or even immediate functionality improvements from a rehosting project but there are many opportunities for cost avoidance and optimization of spend.

As an IT director or manager, it’s critical to ensure executive-level sponsors understand how different migration approaches align to anticipated outcomes. There’s often pressure from leadership to migrate to the cloud, and understandably with countless cloud benefits and the many challenges associated with aging on-premises solutions. However, understanding and communicating what’s realistic for your organization and how different approaches will address various business goals is crucial.

Data Center Evacuations & Unsupported Technology

Organizations migrating based on a mandated data center evacuation or the security and compliance risks associated with unsupported or end-of-support technology often look to a rehost strategy as a first step. This helps accomplish the business goal of reducing technical debt or remediating compliance concerns quickly.

Reaping the Benefits of Cloud-Native Solutions

There are many other reasons organizations look to the cloud, such as staying competitive, increasing time to value, or the ability to innovate. To fully realize the cloud outcomes that motivate these decisions – including greater flexibility, scalability, data security, built-in disaster recovery options, and improved collaboration – additional planning and refactoring of on-premises applications are often required. In these cases, sometimes we see a rehost as the first stage (as leadership wants to see quick results or has made a public commitment to migrate to the cloud), followed by more advanced modernization efforts.

To get to the root of goals and expectations, consider the following questions as you build your roadmap:

  1. What are your business objectives for cloud adoption, and how will they help further the company vision?
  2. Is there a set timeline to complete the cloud migration effort?
  3. What internal and external resources are available to support a cloud migration?
  4. How many applications are in your portfolio, and do you plan to migrate everything, or are you considering a hybrid model approach?
  5. What are the technical requirements and interdependencies of your applications? How will you assess cloud readiness?
  6. What are the necessary governance, security, and compliance considerations?
  7. Who will be responsible for moving workloads to the new cloud platform? Who will perform the migration, and manage the workloads? Will you be doing it by yourself, or will it be a shared initiative?
  8. How do you intend to use automation to reduce manual efforts and streamline provisioning and governance?

As you answer the questions above, you may find that a rehost effort is sufficient. Likewise, you may choose to explore a lead horse application approach as part of your migration strategy to better understand the value derived from various modernization tactics.

Uncovered Benefits of the Cloud

Uncover Additional Cloud Benefits

If your organization is interested in exploring cloud benefits that go beyond what a rehost effort can provide, migration options that are more involved than rehosting may be worth your consideration. Organizations looking to modernize through re-platforming or refactoring may be motivated by cloud benefits such as:

  • Faster time to market, product release cycles, and/or pace of innovation
  • Enriched customer and end-user experiences
  • Improved employee technology, collaboration, and processes
  • Better reliability and networking speeds
  • Reduced cost of labor and/or maintenance
  • Ability to leverage emerging technology
  • Built-in disaster recovery options
  • Flexibility and scalability
  • Data security
  • Cost allocation for budgeting and showback/chargeback
  • Move from Capex to Opex (or realize Capex by buying resource commitments)

If you are facing tight timelines to migrate, a rehost effort can get you one step closer to realizing the above benefits. Through an initial migration, you can look to a proof of concept to gain a further understanding of the business impact various approaches have to offer while incrementally progressing cloud transformation.



While rehosting is a faster, less resource-intensive migration approach and a great first step into the cloud, it comes with challenges and limitations.

The primary limitation of migrating certain on-premises applications to the cloud is the application’s inherent cloud compatibility. Specific applications have internal and external dependencies which limit their ability to take advantage of more advanced cloud benefits once rehosted.

While rehosting allows you to modernize the application environment, resulting in outcomes such as reduced Data Center costs, other cloud benefits aren’t fully realized. Outcomes such as elasticity and the ability to take advantage of cloud-native features are not available with a strictly rehost strategy.

While more cost-effective than on-premises hosting, sometimes it can be more costly to run applications in the cloud when rehosting, versus re-platforming or refactoring without a FinOps strategy to master the unit economics of cloud for competitive advantage. To show fast progress, rehosting is often a great transitional stage for working towards a cost-effective cloud solution, especially for organizations on a tight timeline. During this stage, managing cloud costs and realizing cloud value with a FinOps practice is key.

Feeling Stuck?

Not Sure Where to Start?

If you’re stuck in analysis paralysis, work with a consultant that’s been through various migration projects, from start to finish, and understands the common challenges and complexities of different approaches.

Whether you’re considering Azure, Office 365, Power Platform, or another cloud platform, AIS has a range of Adoption Frameworks and Assessments that can help you understand your options. With our help, create a shared vision, and align business goals to the appropriate migration approaches.


Lift n Shift Approach to Cloud Transformation

What does it mean to Rehost an application?

Rehosting is an approach to migrating business applications hosted in on-premises data center environments to the cloud by moving the application “as-is,” with little to no changes to the business functions performed by the application. It’s a faster, less resource-intensive migration approach that gets your apps into the cloud without much code modification. It is often a good first step to cloud transformation.

Organizations with applications that were initially developed for an on-premises environment commonly look to rehosting to take advantage of cloud computing benefits. These benefits may include increased availability and networking speeds, reduced technical debt, and a pay-per-usage cost structure. When defining your cloud migration strategy, it’s essential to analyze all migration approaches, such as re-platforming, refactoring, replacing, and retiring.


Read More…

SPFx Modern Web Development

SharePoint has been a widely adopted and popular content management system for many large organizations over the past two decades. From SharePoint Portal Server in 2001 to SharePoint Server 2019 and SharePoint Online, the ability to customize the user experience (UX) has evolved dramatically, keeping pace with the evolution of modern web design. SharePoint Framework (SPFx) is a page and web part model that provides full support of client-side SharePoint development with support for open sources. SPFx works in SharePoint Online, and with on-premises SharePoint 2016, and SharePoint 2019. SPFx works both in modern and classic pages. SPFx Web Parts and Extensions are the latest powerful tool we can use to deliver great UX!

Advantages of using SharePoint Framework

1. It Can’t Harm the Farm

Earlier SharePoint (SP) customization code executed on the server from compiled, server-side code is written in a language such as C#. Historically, we created web parts as full trust C# assemblies that were installed on the SharePoint servers and had access to disrupt SharePoint for all users. Because it ran with far greater permissions on the server, it could adversely impact or even crash the entire farm. Microsoft tried to solve this problem in SP 2010 by implementing Sandbox solutions, followed by the App Model, now known as Add-In model.

SPFx development is based on JavaScript running in a browser, making REST API calls to the SharePoint and Office 365 back-end workloads and does not touch the internals of SharePoint.

The SharePoint Framework is a safer, lower-risk model for SharePoint development.

2. Modern Development Tools

Building SPFx elements using JavaScript and its wealth of libraries, the UX and UI can be shaped as beautifully as any modern website. The JavaScript is embedded directly to the page, and the controls are rendered in the normal page DOM.

SharePoint Framework development is JavaScript framework-agnostic. The toolchain is based on common open-source client development tools such as npm, TypeScript, Yeoman, webpack, and gulp. It supports open-source JavaScript libraries such as Node.js, React.js, Angular.js, Handlebars, Knockout, and more. These provide a lightweight and rapid user experience.

3. Mobile-First Design

“Mobile first”, as the name suggests, means that we start the product design from the mobile end, which has more restrictions to make the content usable in the small space of a phone. Next, we can expand those features to a more luxurious space to create a tablet or desktop version.

Because SharePoint Framework customizations run in the context of the current page (and not in an IFRAME), they are responsive, lightweight, accessible, and mobile-friendly. Mobile support is built-in from the start. Content reflows across device sizes and pages are fast and fluid.

4. Simplified Deployment

There is some work to do at the beginning of a new project to set up the SPFx structure to support reading from a remote host. An App Catalog must be created, as well as generating and uploading a manifest file. If the hosted content is connected with a CDN (Content Delivery Network), that will also require setup. However, once those structural pieces are in place, deployment is simplified to updating files on the host location. It does not require traditional code deployments of server-side code, with its attendant restrictions and security review lead time.

5. Easier Integration of External Data Sources

With SPFx, calls to data from external sources may be easier since it’s web content hosted outside of SharePoint.

SPFx Constraints and Disadvantages

The SharePoint Framework is only available in SharePoint Online,  on-premises SharePoint 2016, and SharePoint 2019 at the time of this blog. SPFx cannot be added to earlier versions of SharePoint such as SharePoint 2013 and 2010.

SharePoint Framework Extensions cannot be used in on-premises SharePoint 2016 but only in SharePoint 2019 and SharePoint Online.

SPFx, like any other client-side implementation, runs in the context of the logged-in user. The permissions cannot be elevated to impersonate as an admin user like in farm solutions, CSOM (client-side object model) context, or in SharePoint Add-ins and Office 365 web applications. The SharePoint application functionality is limited to the current user’s permission level, and customization is based on that as well. To overcome this constraint, a hybrid solution implementation with SPFx to communicate with Application Programming Interfaces (APIs). APIs would be registered as SharePoint add-in, that uses the app-only context to communicate with SharePoint. For this communication between SPFx and API to work, the API would need to support CORS (Cross-Origin Resource Sharing) as the communication would be through cross-domain client-side calls.

SPFx is also not for long-running operations as it is entirely client-side implementation. The web request cannot wait longer until it gets the response from the long-running web operation. Hence for those processes, the hybrid approach with long operations can be implemented in Azure web job/function, and SPFx can get the update from those via webhook.

Developers coming from server-side will have a learning curve with entirely client-side development. But TypeScript is there for the rescue.

SPFx Comparison to Other Technologies and Models

SharePoint lists come in handy for many organizations when entering data, but customers always ask for the ability to display the data in some reporting format, such as a dashboard. Below we compare the different ways we can accomplish this and why SPFx is a good fit:

  • Classic Web Part Pages: If we do not want to use the SharePoint Framework, SharePoint 2019 still supports the classic web part pages. You can add content editor web parts and deploy any custom JavaScript/jQuery code. However, with this approach, uploading the Js files in the SP library and manually adding pages in a library become cumbersome. We may end up writing custom JSOM (JavaScript object model) code to make the deployment easier. Microsoft does not recommend this approach, and there is the possibility that this will no longer be supported in the future. Also, with this approach, if you want to render any custom tables, you need to write custom code or use a third-party table. Using SharePoint Framework, we can easily use Office UI Fabric React components like Details list.
  • Custom App: We can design custom applications to deploy in the cloud, which can read the data from SharePoint. The challenge is that each customer environment is different. It’s not always easy to connect to SharePoint from the cloud in a production environment, especially with CAC (Common Access Card) authenticated sites.
  • Power Apps/LogicApps: With newer technologies such as Power Apps, Logic Apps, and Flow, we can design custom SharePoint Forms and business logic and connect to SharePoint using the SharePoint connector. In a production environment, it is not easy to get connection approved and to connect with on-premises data. Power Apps and Flow require the purchase of licenses.

Using SPFx, we can quickly design the dashboards using Office UI Fabric components. For deployment, we do not need to write any custom utility code, SharePoint framework package can create the lists and libraries as well.

Wrapping Up

We hope this blog provided an SPFx overview and its great functionalities. Please look forward to our next blog post (Part II) in developing and deploying custom SPFx Web Parts, Extensions, and connecting to API’s/Azure in SharePoint Online and SharePoint 2019!

Additional Links to get started in SPFx