How to Build a Power Apps Code App and Connect It to Office 365 Users & Dataverse
How to Build a Power Apps Code App and Connect It to Office 365 Users & DataverseHow to Build a Power Apps Code App and Connect It to Office 365 Users & Dataverse
A Complete Step-by-Step Professional Guide
Microsoft Power Apps has introduced a new capability called Code Apps, allowing developers to build fully customizable web applications using TypeScript, React, and Power Platform services. Code Apps combine the control of traditional web development with the power of the Dataverse and Power Platform ecosystem.
In this guide, we will walk step-by-step through:
- Creating a Power Apps Code App
- Connecting the app to Office 365 Users
- Connecting the app to Dataverse
- Running and publishing app
1. Prerequisites: Preparing Development Environment
✔ Required Tools:
- Node.js (LTS version)
- Power Platform CLI (pac)
- Git
- Visual Studio Code (recommended)
✔ Required Power Platform Setup:
- Access to a Power Platform environment
- Code Apps feature enabled
Enable Code Apps by navigating to:
Power Platform Admin Center → Environment → Settings → Features → Power Apps Code Apps
2. Create a Power Apps Code App
Step 1 — Scaffold a project
npx degit github:microsoft/PowerAppsCodeApps/templates/vite my-code-app
cd my-code-app
Step 2 — Install dependencies
npm install
Step 3 — Sign into Power Platform using CLI
pac auth create
Step 4 — Select development environment
pac env select --environment https://crmoncetraining.crm8.dynamics.com/
Step 5 — Initialize as a Code App
pac code init --displayname "My Code App"
Step 6 — Run Code App Locally
npm run dev
Step 7 — Build and Push to Power Apps
npm run build
pac code push
3. Connect Code App to Office 365 Users
Office 365 Users allows app to access:
- Name
Step 1 — Create or verify an Office 365 Users connection
Go to: Power Apps → Data → Connections → New Connection → Office 365 Users
Step 2 — Find the connector’s connection ID
pac connection list
Step 3 — Add Office 365 Users as a data source
pac code add-data-source -a shared_office365users -c <connectionId>
Example with connection:
pac code add-data-source -a shared_office365users -c c3cd32ef7d424bd78114077f9fecf865
Step 4 — Add Office 365 Users Code in src/App.tsx
import { useState, useEffect } from "react"
import "./App.css"
import { Office365UsersService } from "./generated/services/Office365UsersService"
function App() {
const [count, setCount] = useState(0)
const [userName, setUserName] = useState("")
const [userEmail, setUserEmail] = useState("")
const [loading, setLoading] = useState(true)
const [error, setError] = useState("")
useEffect(() => {
const testConnection = async () => {
try {
const response = await Office365UsersService.MyProfile()
setUserName(response.data.DisplayName ?? "Unknown")
setUserEmail(response.data.Mail ?? "Not available")
} catch (err) {
setError("Failed to connect to Office 365 Users")
} finally {
setLoading(false)
}
}
testConnection()
}, [])
return (
<div style={{ padding: "24px", maxWidth: "600px", margin: "0 auto" }}>
<h1>My First Power Apps Code App 🚀</h1>
<div>
{loading ? "Checking connection..." : error ? error : `Name: ${userName}, Email: ${userEmail}`}
</div>
<div>
<p>Button clicked: {count} times</p>
<button onClick={() => setCount(count + 1)}>Click Me</button>
</div>
</div>
)
}
export default App
4. Connect Code App to Microsoft Dataverse (CRUD)
Step 1 — Add a Dataverse table as a data source
pac code add-data-source -a dataverse -t adcrm_employee_admin
The following files are generated automatically:
- Adcrm_employee_adminsModel.ts
- Adcrm_employee_adminsService.ts
Step 2 — Add Dataverse CRUD Code in src/App.tsx
import { useState, useEffect } from "react"
import "./App.css"
import { Office365UsersService } from "./generated/services/Office365UsersService"
import { Adcrm_employee_adminsService } from "./generated/services/Adcrm_employee_adminsService"
function App() {
const [userName, setUserName] = useState("")
const [userEmail, setUserEmail] = useState("")
const [loading, setLoading] = useState(true)
const [error, setError] = useState("")
const [employees, setEmployees] = useState<any[]>([])
const [employeeName, setEmployeeName] = useState("")
const [email, setEmail] = useState("")
const [department, setDepartment] = useState("")
const [phone, setPhone] = useState("")
const [editId, setEditId] = useState<string | null>(null)
useEffect(() => {
const testConnection = async () => {
try {
const response = await Office365UsersService.MyProfile()
setUserName(response.data.DisplayName ?? "Unknown")
setUserEmail(response.data.Mail ?? "Unknown")
} catch {
setError("Failed to connect to Office 365 Users")
} finally { setLoading(false) }
}
testConnection()
loadEmployees()
}, [])
async function loadEmployees() {
const result = await Adcrm_employee_adminsService.getAll()
setEmployees(result.data ?? [])
}
async function createEmployee() {
if (!employeeName) return alert("Employee Name is required")
try {
await Adcrm_employee_adminsService.create({
adcrm_newcolumn: employeeName,
adcrm_email: email,
adcrm_department: department,
adcrm_phone: phone,
} as any)
setEmployeeName("")
setEmail("")
setDepartment("")
setPhone("")
loadEmployees()
} catch (err) {
console.error("Create failed:", err)
alert("Failed to add employee. Check console for details.")
}
}
function startEdit(emp: any) {
setEditId(emp.adcrm_employee_adminid)
setEmployeeName(emp.adcrm_newcolumn)
setEmail(emp.adcrm_email)
setDepartment(emp.adcrm_department)
setPhone(emp.adcrm_phone)
}
async function updateEmployee() {
if (!editId) return
if (!employeeName) return alert("Employee Name is required")
try {
await Adcrm_employee_adminsService.update(editId, {
adcrm_newcolumn: employeeName,
adcrm_email: email,
adcrm_department: department,
adcrm_phone: phone,
} as any)
setEditId(null)
setEmployeeName("")
setEmail("")
setDepartment("")
setPhone("")
loadEmployees()
} catch (err) {
console.error("Update failed:", err)
alert("Failed to update employee. Check console for details.")
}
}
async function deleteEmployee(id: string) {
if (!window.confirm("Are you sure you want to delete this employee?")) return
try {
await Adcrm_employee_adminsService.delete(id)
console.log("Deleted record:", id)
loadEmployees() // refresh table
} catch (err) {
console.error("Delete failed:", err)
alert("Delete failed. Check console for details.")
}
}
return (
<div style={{ padding: "24px", maxWidth: "900px", margin: "0 auto" }}>
<h1>My First Power Apps Code App 🚀</h1>
<div>
{loading ? "Checking connection..." : error ? error : `Name: ${userName}, Email: ${userEmail}`}
</div>
<div>
<h2>Dataverse Employee Admin (CRUD)</h2>
<div style={{ display: "flex", gap: "8px", marginBottom: "12px" }}>
<input placeholder="Employee Name" value={employeeName} onChange={e => setEmployeeName(e.target.value)} />
<input placeholder="Email" value={email} onChange={e => setEmail(e.target.value)} />
<input placeholder="Department" value={department} onChange={e => setDepartment(e.target.value)} />
<input placeholder="Phone" value={phone} onChange={e => setPhone(e.target.value)} />
{editId ? <button onClick={updateEmployee}>Update</button> : <button onClick={createEmployee}>Add</button>}
</div>
<table>
<thead><tr><th>Name</th><th>Email</th><th>Dept</th><th>Phone</th><th>Actions</th></tr></thead>
<tbody>
{employees.map(emp => <tr key={emp.adcrm_employee_adminid}>
<td>{emp.adcrm_newcolumn}</td>
<td>{emp.adcrm_email}</td>
<td>{emp.adcrm_department}</td>
<td>{emp.adcrm_phone}</td>
<td>
<button onClick={() => startEdit(emp)}>Edit</button>
<button onClick={() => deleteEmployee(emp.adcrm_employee_adminid)} style={{ marginLeft: "10px", color: "red" }}>Delete</button>
</td>
</tr>)}
</tbody>
</table>
</div>
</div>
)
}
export default App
5. Build and Publish Code App
Once development is complete:
Step 1 — Build production version
npm run build
Step 2 — Publish to Power Apps
pac code push