<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>How To Archives | DMC, Inc.</title>
	<atom:link href="https://static.dmcinfo.com/blog/tag/how-to/feed/index.xml" rel="self" type="application/rss+xml" />
	<link></link>
	<description></description>
	<lastBuildDate>Mon, 27 Jul 2026 15:34:36 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>

<image>
	<url>https://static.dmcinfo.com/wp-content/uploads/2025/04/site-icon-150x150.png</url>
	<title>How To Archives | DMC, Inc.</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Windows Virtual Machine PowerShell Tweaks</title>
		<link>https://static.dmcinfo.com/blog/17272/windows-virtual-machine-powershell-tweaks/</link>
		
		<dc:creator><![CDATA[Dylan Trainor]]></dc:creator>
		<pubDate>Sat, 26 Aug 2023 16:11:18 +0000</pubDate>
				<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[Virtual Machine]]></category>
		<category><![CDATA[VM]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/17272/windows-virtual-machine-powershell-tweaks/</guid>

					<description><![CDATA[<p>For companies in the software development sector, creating new Windows virtual machines for employees can become a regular task. Employees who initialize these virtual machines often follow a list of common “best practice” adjustments to rename their machine and correct any system performance issues. PowerShell is an efficient method of conducting all these common tasks [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/17272/windows-virtual-machine-powershell-tweaks/">Windows Virtual Machine PowerShell Tweaks</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">For companies in the software development sector, creating new Windows virtual machines for employees can become a regular task. Employees who initialize these virtual machines often follow a list of common “best practice” adjustments to rename their machine and correct any system performance issues.</p>



<p class="wp-block-paragraph">PowerShell is an efficient method of conducting all these common tasks in quick succession and providing a repeatable methodology that can be reused for each new virtual machine.</p>



<p class="wp-block-paragraph"><em>Note: The following commands are tested for Windows10 virtual machines using an admin-privileged PowerShell. I&nbsp;recommend creating a restore point of your virtual machine using a feature such as <strong>VMWare Workstation’s Snapshot</strong>.</em></p>



<h2 class="wp-block-heading" id="h-renaming-the-virtual-machine-pc-and-local-user-account">Renaming the Virtual Machine PC and Local User Account</h2>



<p class="wp-block-paragraph">When distributing virtual machines across many employees, it is a best practice to rename the employee’s virtual machine so that it can be easily identified when working on large collaborative projects. The computer and local usernames can both be renamed using the following PowerShell commands:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
 # Renames the computer - be sure to replace the sample name

Rename-Computer -NewName "SampleName"

# Renames the local user - be sure to replace the company and sample name

Rename-LocalUser -Name "SampleCompanyName" -NewName "SampleName"

</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #6A9955"># Renames the computer - be sure to replace the sample name</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Rename-Computer</span><span style="color: #D4D4D4"> -NewName </span><span style="color: #CE9178">&quot;SampleName&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Renames the local user - be sure to replace the company and sample name</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Rename-LocalUser</span><span style="color: #D4D4D4"> -Name </span><span style="color: #CE9178">&quot;SampleCompanyName&quot;</span><span style="color: #D4D4D4"> -NewName </span><span style="color: #CE9178">&quot;SampleName&quot;</span></span>
<span class="line"></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">If the name of the current Local User is unknown, it can be viewed by searching for <strong>Computer Management</strong> using the start menu and navigating to “Local Users and Groups &gt; Users”.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/local-user.png" alt="A screenshot of a computerDescription automatically generated"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Figure 1: Location of the Local User within Computer Management</em></p></p>



<p class="wp-block-paragraph">When changing the sample names to the appropriate fields for your needs, make sure there is no white space before or after the field. Using “ SampleName “ instead of “SampleName” may cause problems with password acceptance after a restart, locking you out of your virtual machine.</p>



<h2 class="wp-block-heading" id="h-performance-improvements"><strong>Performance Improvements</strong></h2>



<p class="wp-block-paragraph">When working with limited computing resources, performance improvements can become vital on Windows virtual machines that&nbsp;run intensive programs. Two notable PowerShell commands are setting the Power Plan to <strong>High Performance </strong>and the removal of native Windows applications, which may bloat the system.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
# Sets the Windows Power Plan setting to High Performance

powercfg.exe -SETACTIVE 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

# Removes all default Windows application packages

Get-AppxPackage -AllUsers | Remove-AppxPackage
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955"># Sets the Windows Power Plan setting to High Performance</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">powercfg.exe</span><span style="color: #D4D4D4"> -SETACTIVE 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Removes all default Windows application packages</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Get-AppxPackage</span><span style="color: #D4D4D4"> -AllUsers | </span><span style="color: #DCDCAA">Remove-AppxPackage</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">This first command will set your virtual machine’s Power Plan setting to <strong>High Performance</strong>. The second command fetches all app packages (applications with a .msix or .appx file extension) for default Windows applications and removes them. This may take a while, as it will remove all applications such as the default calculator, photo viewer, Cortana, Xbox features, and more. System-crucial programs such as the File Explorer are untouched.</p>



<p class="wp-block-paragraph">On some Windows11 and Windows10 host machines, virtual machine software such as <strong>VMWare Workstation</strong> experiences significant performance inhibitions due to the default program power throttling settings. If you experience this, you can disable power throttling for the application with the following command (executed in your host machine instead of the virtual machine):</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
# Disables power throttling for VMWare Workstation

powercfg /powerthrottling disable /path "C:\Program Files (x86)\VMware\VMware Workstation\x64\vmware-vmx.exe"</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955"># Disables power throttling for VMWare Workstation</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">powercfg /powerthrottling disable /path </span><span style="color: #CE9178">&quot;C:\Program Files (x86)\VMware\VMware Workstation\x64\vmware-vmx.exe&quot;</span></span></code></pre></div>



<h2 class="wp-block-heading" id="h-quality-of-life-improvements"><strong>Quality of Life Improvements</strong></h2>



<p class="wp-block-paragraph">For companies with many regional or international offices, employees in various time zones can quickly update the displayed time of their virtual machine by executing the following:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
# Displays the current time zone

Get-TimeZone

# Lists all available time zones

Get-TimeZone -ListAvailable

# Set the time zone to the desired time zone name – be sure to replace the name with the appropriate time zone

Set-TimeZone "Sample Time Zone"</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955"># Displays the current time zone</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Get-TimeZone</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Lists all available time zones</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Get-TimeZone</span><span style="color: #D4D4D4"> -ListAvailable</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Set the time zone to the desired time zone name – be sure to replace the name with the appropriate time zone</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Set-TimeZone</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Sample Time Zone&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">Common options for time zone names can be seen below. Replacing &#8220;Standard&#8221; with &#8220;Daylight&#8221; will correct the time to Daylight Savings Time.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
Set-TimeZone "Eastern Standard Time"

Set-TimeZone "Pacific Standard Time"

Set-TimeZone "US Mountain Standard Time"

Set-TimeZone "Central Standard Time"</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Set-TimeZone</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Eastern Standard Time&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Set-TimeZone</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Pacific Standard Time&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Set-TimeZone</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;US Mountain Standard Time&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Set-TimeZone</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Central Standard Time&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">Disabling automatic Windows updates can save a significant amount of time during virtual machine system restarts and potentially save a virtual machine from incompatibility crashes after an unwanted feature update. To do this, run the following commands:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
# Stop the automatic Windows update service

sc.exe stop wuauserv

# Disable the automatic Windows update service

sc.exe config wuauserv start=disabled
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955"># Stop the automatic Windows update service</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">sc.exe</span><span style="color: #D4D4D4"> stop wuauserv</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Disable the automatic Windows update service</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">sc.exe</span><span style="color: #D4D4D4"> config wuauserv start=disabled</span></span>
<span class="line"></span></code></pre></div>



<h2 class="wp-block-heading" id="h-single-line-execution"><strong>Single-Line Execution</strong></h2>



<p class="wp-block-paragraph">Copying each line one-by-one is inefficient, so why not run all the commands at once? You can execute all of these changes in a single line by copying and pasting the text below. Adjust the fields, such as your name and time zone, before executing. When finished, your virtual machine will restart and apply the changes to your computer name and local username.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>
# Executes all commands in a single line

Rename-Computer -NewName "SampleName"; Rename-LocalUser -Name "SampleCompanyName" -NewName "SampleName"; Get-AppxPackage -AllUsers | Remove-AppxPackage; powercfg.exe -SETACTIVE 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c; Set-TimeZone "Sample Time Zone"; sc.exe stop wuauserv; sc.exe config wuauserv start=disabled; Restart-Computer</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"></span>
<span class="line"><span style="color: #6A9955"># Executes all commands in a single line</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">Rename-Computer</span><span style="color: #D4D4D4"> -NewName </span><span style="color: #CE9178">&quot;SampleName&quot;</span><span style="color: #D4D4D4">; </span><span style="color: #DCDCAA">Rename-LocalUser</span><span style="color: #D4D4D4"> -Name </span><span style="color: #CE9178">&quot;SampleCompanyName&quot;</span><span style="color: #D4D4D4"> -NewName </span><span style="color: #CE9178">&quot;SampleName&quot;</span><span style="color: #D4D4D4">; </span><span style="color: #DCDCAA">Get-AppxPackage</span><span style="color: #D4D4D4"> -AllUsers | </span><span style="color: #DCDCAA">Remove-AppxPackage</span><span style="color: #D4D4D4">; </span><span style="color: #DCDCAA">powercfg.exe</span><span style="color: #D4D4D4"> -SETACTIVE 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c; </span><span style="color: #DCDCAA">Set-TimeZone</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Sample Time Zone&quot;</span><span style="color: #D4D4D4">; </span><span style="color: #DCDCAA">sc.exe</span><span style="color: #D4D4D4"> stop wuauserv; </span><span style="color: #DCDCAA">sc.exe</span><span style="color: #D4D4D4"> config wuauserv start=disabled; </span><span style="color: #DCDCAA">Restart-Computer</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/power-shell-example.png" alt="A screen shot of a computer screenDescription automatically generated"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Figure 2: An example virtual machine PowerShell tweak to a new DMC virtual machine</em></p></p>



<p class="wp-block-paragraph"><strong>Learn more about our <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence">Manufacturing Automation services</a>&nbsp;and <a href="https://static.dmcinfo.com/contact">contact us</a>&nbsp;for your next project.</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/17272/windows-virtual-machine-powershell-tweaks/">Windows Virtual Machine PowerShell Tweaks</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Beckhoff PLC to PLC Communication Using EAP &#8211;  A Starter Guide</title>
		<link>https://static.dmcinfo.com/blog/17760/beckhoff-plc-to-plc-communication-using-eap-a-starter-guide/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Tue, 07 Mar 2023 11:37:39 +0000</pubDate>
				<category><![CDATA[Beckhoff PLC]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Beckhoff]]></category>
		<category><![CDATA[EAP]]></category>
		<category><![CDATA[Ethernet IP]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[PLC Communication]]></category>
		<category><![CDATA[TwinCAT]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/17760/beckhoff-plc-to-plc-communication-using-eap-a-starter-guide/</guid>

					<description><![CDATA[<p>Beckhoff&#8217;s Industrial Personal Computers (IPCs) allow for easy configuration into a wide variety of PLC-to-PLC communications. Internal links between IPCs running TwinCAT XAR are the simplest and will be the first that this series of articles explore. This article demonstrates a holistic approach to establishing a connection between two&#160;Beckhoff IPCs. IPC Configuration: All PLCs mentioned [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/17760/beckhoff-plc-to-plc-communication-using-eap-a-starter-guide/">Beckhoff PLC to PLC Communication Using EAP &#8211;  A Starter Guide</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Beckhoff&rsquo;s Industrial Personal Computers (IPCs) allow for easy configuration into a wide variety of PLC-to-PLC communications. Internal links between IPCs running TwinCAT XAR are the simplest and will be the first that this series of articles explore.</p>

<p class="wp-block-paragraph">This article demonstrates a holistic approach to establishing a connection between two&nbsp;Beckhoff IPCs.</p>

<h2 class="wp-block-heading">IPC Configuration:</h2>

<p class="wp-block-paragraph">All PLCs mentioned are the BECKHOFF C6017 model.</p>

<p class="wp-block-paragraph">In order to &ldquo;discover&rdquo; another PLC, the Beckhoff IPC will need to have its network and port configured to be visible across an ethernet or network connection. In this example I will be using a PLC that is networked to an internal server with 20 to&nbsp;40 other Beckhoff IPCs.</p>

<p class="wp-block-paragraph"><strong><u>Process:</u></strong></p>

<ol class="wp-block-list">
 <li>Connect the Beckhoff IPC to a monitor and peripherals to control the system. This specific model calls for a Display Port (DP) connection and any USB integrated keyboard and mouse.</li>
</ol>

<ol class="wp-block-list" start="2">
 <li>Sign into the IPC. If no configuration has been set, this will be Beckhoff&rsquo;s default login:
 <ol class="wp-block-list" style="list-style-type:lower-alpha;">
  <li>Username: ADMINISTRATOR</li>
  <li>Password: 1</li>
 </ol>
 </li>
</ol>

<ol class="wp-block-list" start="3">
 <li>If this is your first time accessing the PLC, click&nbsp;<a href="https://static.dmcinfo.com/latest-thinking/blog/id/10162/getting-started-with-a-beckhoff-plc-part-one--setup#Install%20Software" target="_blank">HERE</a>&nbsp;for a step-by-step setup process.

 <ol class="wp-block-list" style="list-style-type:lower-alpha;">
  <li><strong>IMPORTANT</strong>: make sure to follow step 8 for the appropriate firewall settings.</li>
 </ol>
 </li>
</ol>

<ol class="wp-block-list" start="4">
 <li>Like <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10162/getting-started-with-a-beckhoff-plc-part-one--setup#Install RTE Driver">step 6</a> in the linked article, we need to install the Beckhoff Real-Time Ethernet Driver for our networked port.

 <ol class="wp-block-list" style="list-style-type:lower-alpha;">
  <li>Regardless of whether you use direct or networked ethernet communication, this driver will&nbsp;need to be installed on the appropriate ethernet port.</li>
 </ol>
 </li>
</ol>

<ol class="wp-block-list" start="5">
 <li>Navigate to&nbsp;<strong>C:\TwinCAT\3.1\System</strong>&nbsp;and run&nbsp;<strong>TcRteInstall.exe:</strong></li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><strong><img decoding="async" alt="TcRteInstall_Location" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/TCREInstall.png"  /></strong></p>

<ol class="wp-block-list" start="6">
 <li>Install the driver onto the Networked port. For a networked connection, the IPv4 properties found in <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10162/getting-started-with-a-beckhoff-plc-part-one--setup#Changing NIC Settings">step 2</a> of the linked article will need to include an appropriate IP address, subnet mask, and gateway to the local server.</li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="IPv4_Properties" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/IPv4-protocol.png"  /></p>

<p class="wp-block-paragraph" style="text-align: center;"><em>Note: if you as a user also have access to this internal network through local access or a VPN, you can program the PLC from this networked port and no longer need a physical connection to the IPC.</em></p>

<ol class="wp-block-list" start="7">
 <li>With the correct configuration of your IPv4&nbsp;network properties, you should be able to discover other devices on the server.</li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="IPC_Ping_Test" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Ping.png"  /></p>

<ol class="wp-block-list" start="8">
 <li>Next, we need to set the AMS NetId to partner with the expected service. This step will ensure that there are no conflicting communication paths between PLCs. At DMC&nbsp;these are typically set to the PLC IP address and extended with a .1.1, as seen below, to match the expected 6-byte TwinCAT network ID.</li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="AMS_NetID_set_1" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ams1.png"  /><img decoding="async" alt="AMS_NetID_set_2" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ams2.png"  /></p>

<h2 class="wp-block-heading">TwinCAT XAE&nbsp;Configuration:</h2>

<p class="wp-block-paragraph">We can now migrate to the TwinCAT XAE environment and begin&nbsp;creating EAP masters through the networked ports on the IPC, as shown above or by using the EL-6601 or EL-6614 hardware options, which extend the IPCs available ethernet ports.</p>

<p class="wp-block-paragraph" style="text-align: center;"><em>Note: the EL-6652 supports Ethernet/IP communication to other PLC platforms and will be covered in a future blog. &nbsp;&nbsp;&nbsp;</em></p>

<p class="wp-block-paragraph"><strong><u>TwinCAT XAE EtherCAT Automation Protocol (EAP) Setup:</u></strong></p>

<p class="wp-block-paragraph">For this tutorial, we will be using the EAP Master that is linked to an internal IPC network port.</p>

<ol class="wp-block-list">
 <li>Begin by right-clicking on Devices in the IO tree here:</li>
</ol>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Add_a_EAP_Master" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/EAP1.png"  /></p>

<p class="wp-block-paragraph">&nbsp; &nbsp; &nbsp; &nbsp;2. Then, select the EAP Master:</p>

<p class="wp-block-paragraph" style="margin-left: 40px; text-align: center;"><img decoding="async" alt="EAP_Master_2" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Eap2.png"  /></p>

<p class="wp-block-paragraph">Once instantiated, the box is ready to set up publishers and subscribers. Publishers can &ldquo;publish&rdquo; or send data out across an EAP connection while subscribers will&nbsp;&ldquo;subscribe&rdquo; and listen for that data. These can be instantiated by right-clicking on the EAP master and adding a new device.</p>

<p class="wp-block-paragraph"><u><strong>Publishers:</strong></u></p>

<p class="wp-block-paragraph">There are a few ways to set up the communication bridge. At DMC, the two most common are the UDP/IP Unicast and&nbsp;the RT-Ethernet Unicast with the AMS NetId. Unless you are using multicast, it will be one box per PLC to PLC connection.</p>

<ol class="wp-block-list">
 <li>To publish with UDP, specify the Unicast destination which is the Networked IP address of the desired IPC and the default gateway hosting the server traffic.</li>
</ol>

<p class="wp-block-paragraph">&nbsp;</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="UDP_Unicast" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Casting1.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">2. To publish with RT-Ethernet, set the AMS NetId of the subscriber. This requires the two networked IPCs to be on the same server and discoverable by one another.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="RT_Casting" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/RTCast2_1.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">3. Regardless of your chosen method, you can now instantiate networked variables to publish from your boxes. To do this, right click on the publisher box and select &apos;add new item&apos;. Then, configure the data you need to send.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Insert_Network_Variable" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Network-Variable.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">4.Next, link the instantiated publisher variable data to the PLC variable you wish to send out within the outputs sub-selection on the publisher box:</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Data_Link" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Linking.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">5.Continue this process for all the variables you wish to use in EAP communication, and then activate the configuration to change the memory space.</p>

<p class="wp-block-paragraph"><u><b>Subscribers:</b></u></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">1.Similar to publishers on an EAP Master, add a new item and select Network Variable Subscriber.</p>

<p class="wp-block-paragraph" style="margin-left: 40px;">2. There are a couple of options for adding subscriber variables. The easiest is to browse for computers. This requires the RT-Ethernet setup on the publisher. To do so, right click on the subscriber box and select &apos;add new item&apos;. Then, select &apos;browse for computer.&apos;</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Import_Network_Variable" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Networkvariable2.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">3. Add the appropriate dialog route for your search, and establish the connection.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Connect_to_the_PLC" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ConnectToPLC.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">4. After establishing a connection, the published variables will populate to the network variables list.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Select_A_Variable" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/SelectVariable.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">5. Select the variables you wish to subscribe to, and link them to subscriber IPC inputs to use in logic. Note that the quality tag can be used as a heartbeat monitor and that a value of 0 is a successful connection. Activate the configuration and check to see if the connection is present.</p>

<p class="wp-block-paragraph" style="text-align: center;"><img decoding="async" alt="Linked_Subscriber" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/LinkedVariable.png"  /></p>

<p class="wp-block-paragraph" style="margin-left: 40px;">6. For the UDP Unicast Publisher, set up the subscriber to receive from any publisher because the publisher is providing the IPC pointing. Then, instead of browsing&nbsp;for a computer, use &apos;create a new variable,&apos; and give it the definition the publisher is providing whether that be INT, BOOL, or any other data type.</p>

<p class="wp-block-paragraph" style="margin-left: 40px;">7. Next, in the subscribe tab of the new variable, provide the expected publisher variable ID and link like in step 5. This will also come with a quality check for the connection state.</p>

<p class="wp-block-paragraph">Now that the publisher and subscriber have achieved a connection, the networked variables and connection quality are available to the subscriber PLC to use in any desired logic.</p>

<p class="wp-block-paragraph"><strong>Learn more about DMC&apos;s <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming/beckhoff-and-twincat-3-programming">Beckhoff and TwinCAT Programming</a> expertise and <a href="https://static.dmcinfo.com/contact">contact us</a> for your next project.&nbsp;</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/17760/beckhoff-plc-to-plc-communication-using-eap-a-starter-guide/">Beckhoff PLC to PLC Communication Using EAP &#8211;  A Starter Guide</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Sending Emails with a Siemens 1200 PLC</title>
		<link>https://static.dmcinfo.com/blog/19834/sending-emails-with-a-siemens-1200-plc/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Wed, 24 Jun 2020 14:32:51 +0000</pubDate>
				<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[PLC]]></category>
		<category><![CDATA[Siemens PLC]]></category>
		<category><![CDATA[Function Blocks]]></category>
		<category><![CDATA[How To]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/19834/sending-emails-with-a-siemens-1200-plc/</guid>

					<description><![CDATA[<p>If you have not checked out our previous blog on sending emails with a Siemens 1500 PLC, be sure to read that before reading this addition. We know how difficult it can be to do something as simple as sending an email from a PLC, especially when considering all the different issues that can arise. [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/19834/sending-emails-with-a-siemens-1200-plc/">Sending Emails with a Siemens 1200 PLC</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">If you have not checked out our previous blog on <a href="/latest-thinking/blog/id/9936/sending-emails-with-a-siemens-1500-plc">sending emails with a Siemens 1500 PLC</a>, be sure to read that before reading this addition.</p>

<p class="wp-block-paragraph">We know how difficult it can be to do something as simple as sending an email from a PLC, especially when considering all the different issues that can arise. If you are having trouble sending emails, do not give up. This blog is going to fill you in on what you can do with a Siemens 1200 PLC for sending emails, and hopefully give you insight into additional troubleshooting techniques for getting them working correctly.</p>

<p class="wp-block-paragraph">Starting from the beginning, let&rsquo;s make sure that you have everything set up accordingly.</p>

<h2 class="wp-block-heading">Hardware</h2>

<p class="wp-block-paragraph">When using a PLC to send out emails you must know what type of emails you are sending out. If you are sending emails through a secure protocol (SSL or TLS), then you are going to need additional hardware for either the S7 1500 or the S7 1200 Siemens PLCs.</p>

<p class="wp-block-paragraph">These secure protocols typically communicate using ports 465, and 587. Port 465 if you are using SSL, and port 587 if you are using TLS. For the PLC to communicate through either of these ports, then you will need the addition of a communications processing module. This is typically done when trying to send emails through a public SMTP server like Gmail, or Yahoo.</p>

<p class="wp-block-paragraph">If you are looking to send emails to a local SMTP server, then you can use port 25 for SMTP relay and you do not need an additional communications processing module. Note, this must be done behind a firewall because most firewalls block any traffic on port 25. The configuration for sending emails using port 25 can be more difficult, due to the lower security protocols.</p>

<p class="wp-block-paragraph">For our example, we sent emails to a Gmail account and used a <strong>CP1243-1 communications processor (CP)</strong> with an <strong>S7 1214c PLC</strong>. The CP1243-1 can be configured to any of the S7 1200 PLCs. These are configured as follows.</p>

<p class="wp-block-paragraph">Connect the CP module to the PLC via the terminals on the side of the PLC. There is no need to connect them to each other through their ethernet ports as they can communicate through their back-plane connection. Connect the CP module to the router/modem via a short ethernet cable. Finally, connect the computer that is being used to access the PLC through one of the ports available on the PLC, and it should all be good to go.</p>

<h2 class="wp-block-heading">Hardware Troubleshooting</h2>

<p class="wp-block-paragraph">Verify that the CP module and the PLC are set up in the TIA portal with the same version that matches the physical hardware. Without doing this the CP module and PLC will not compile correctly. Typical troubleshooting for this is straight forward, and there are many different online resources available to help.</p>

<h2 class="wp-block-heading">Software</h2>

<p class="wp-block-paragraph">Refer to the previous blog (<a href="/latest-thinking/blog/id/9936/sending-emails-with-a-siemens-1500-plc">Sending Emails with a Siemens 1500 PLC</a>) for information on how to set up the TMAIL_C function block, Gmail application settings, obtain trusted certifications, and enable security clearance.</p>

<p class="wp-block-paragraph">The entire process is the same for setting up an S7 1500 PLC and an S7 1200 PLC except for the address parameter input.</p>

<p class="wp-block-paragraph">For the address parameters in the TMAIL_C function block, you will be using a <strong>TMAIL_QDN_SEC</strong> system data type instead of the <strong>TMAIL_V4_SEC</strong> system data type. The QDN stands for Qualified Domain Name, which allows you to use domain name servers instead of IP addresses. The settings for the <strong>Address_Parameters</strong> can be set up as seen below.</p>

<p class="wp-block-paragraph">It is important to note that sometimes the <strong>TMail_QDN_SEC</strong> will not autofill as you type out the data type. Typically, if you type it&nbsp;correctly, all the additional parameters will appear after pressing the enter key.</p>

<p class="wp-block-paragraph">One thing that may differ is the <strong>TLSServerCertRef</strong>. The <strong>TLSServerCertRef</strong> refers to the index at which your encryption certification resides and can be changed accordingly. In our example, we had our encryption certification in index 4.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/1-address-parameters.png"  /></figure>

<h2 class="wp-block-heading">Troubleshooting</h2>

<p class="wp-block-paragraph"><u><strong>Status Codes</strong></u></p>

<p class="wp-block-paragraph">Be sure to latch any of the status codes you have for diagnostic purposes. Here is an example of how we latched our statuses and sent them to another variable for diagnostics purposes.</p>

<p class="wp-block-paragraph"><figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/2-local-alarm.png"  /></figure><br />
<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/3-local-alarm-2.png"  /></figure></p>

<p class="wp-block-paragraph"><u><strong>Error Code #8420</strong></u></p>

<p class="wp-block-paragraph">When trying to send an email with a PLC you may get the error code #8420 (SMTP error code 420). This is a timeout connection error which typically results in there being a problem with the firewall, an issue with the PLC and CP modules onboard time, or an issue with the router or modem.</p>

<p class="wp-block-paragraph"><u><strong>Time Synchronization</strong></u></p>

<p class="wp-block-paragraph">Be sure that the time on both the CP module and the PLC are up to date. Without doing this you will likely get a timeout error. To change the time of your PLC and CP module you need to first go online with the PLC and CP module. Once online with the PLC and CP module, go to the <strong>Online and Diagnostics settings</strong> for each device. First, check that the time is in sync for the PLC, the CP module uses the PLC to update its time.</p>

<p class="wp-block-paragraph">For the PLC, go to <strong>Online and Diagnostics&gt;Functions&gt; Set time</strong>. Select the checkbox for &ldquo;Take from PG/PC&rdquo; and then hit apply. From here you can check the time on your CP module and see if it synced up or not.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/4-set-time.png"  /></figure>

<p class="wp-block-paragraph">To access the time for the CP module, go to the online and diagnostics for the CP module located at the bottom of the project tree under local modules. As you can see below, the time on the CP module did not sync up accordingly. This is common when setting the time for the first time on the PLC and will require a full power cycle of the PLC and CP while connected.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/5-time-communication.png"  /></figure>

<p class="wp-block-paragraph">Be sure to select&nbsp;<strong>&ldquo;Enable time-of-day synchronization&rdquo;</strong> if it has not already been selected for the CP module.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/6-time-of-day-sync.png"  /></figure>

<p class="wp-block-paragraph">Afterward, the CP modules time should update with a full power cycle if the CP module and PLC remain connected upon booting up.</p>

<p class="wp-block-paragraph"><u><strong>Router/Modem Configuration</strong></u></p>

<p class="wp-block-paragraph">Be sure to look through the router and modem configuration settings. Most of the time you will be able to connect to the router/modem via ethernet and access the settings by typing in the gateway IP in your web browser. Try other web browsers if the first one does not work. Verify that the IP address of the gateway in the PLC properties is consistent with that of your gateway. If your computer is on the same network as the PLC, you can determine what the IP address of your router/modem is by doing an IP configuration in your command prompt.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/7-IP-config.png"  /></figure>

<p class="wp-block-paragraph">Command prompt command <strong>ipconfig</strong> will pull up all the connections associated with your computer.</p>

<p class="wp-block-paragraph">This is an example of a default gateway that you are trying to search for in IP configuration. It is common for this IP address to be configured as 192.168.1.1, especially if the PLC you are using is operating with its own router/modem.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/8-default-gateway.png"  /></figure>

<p class="wp-block-paragraph">In our example, the gateway that my computer was using was different than the gateway of the PLC. Be sure to troubleshoot the settings in the appropriate gateway. Below is an example of accessing the settings to our router/modem.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/9-browser-IP.png"  /></figure>

<p class="wp-block-paragraph">Be sure that there are no limitations on the trusted IP or edit the limitations to allow for the IP address of your CP module. As seen here, outbound port filtering settings can be configured to limit the access of your PLC from sending emails effectively.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/10-outbound-ips.png"  /></figure>

<p class="wp-block-paragraph"><u><strong>DNS Configuration</strong></u></p>

<p class="wp-block-paragraph">Sometimes your DNS configuration may be the cause of a potential error. Especially if you are trying to use the qualified domain name for your emailing server. A typical fix for this could be to switch your DNS server to the basic google DNS server. In the CP modules, general properties adjust the DNS configuration as follows.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/11-DNS-config.png"  /></figure>

<p class="wp-block-paragraph"><u><strong>Device Configuration</strong></u></p>

<p class="wp-block-paragraph">Your device configuration needs to match your physical hardware. Double-check all the firmware as well as model numbers on every device such that they match the physical hardware. You can check this by going online with the PLC and going to <strong>Online Diagnostics&gt; Diagnostics&gt; General&gt; Firmware</strong>.</p>

<p class="wp-block-paragraph">Once you verify the version of the PLC or CP module are different you can change them accordingly in the Device View by right-clicking the PLC/CP module and selecting Change Device.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/12-device-confit.png"  /></figure>

<p class="wp-block-paragraph"><u><strong>Error Code #8530</strong></u></p>

<p class="wp-block-paragraph">Error code #8530 (SMTP error code 530) typically indicates an authentication problem. Solutions to this error code typically involve your Address Parameters. Verify that these are correct to your specific setup. Make sure you acquired the correct encryption certificate.</p>

<p class="wp-block-paragraph">Also, verify that the Email Configuration settings for the CP module match the settings in the <strong>TMAIL_C function block</strong>. These settings can be found in the<strong> Device Configuration&gt; Properties&gt; General&gt; E-mail Configuration</strong>.</p>

<figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/13-email-config.png"  /></figure>

<p class="wp-block-paragraph">Lastly, check your Gmail/email server settings. Sometimes whenever you think you have done everything correctly; you will get one last error. Be sure to check your email account settings. You will likely get a notification asking for verification about suspicious activity on your account. If you got this notification, then you should be one step away from success.</p>

<p class="wp-block-paragraph"><figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/14-google-alert.png"  /></figure><figure class="wp-block-image"><img decoding="async" alt="" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/15-google-block.png"  /></figure></p>

<p class="wp-block-paragraph">&nbsp;</p>

<h2 class="wp-block-heading">Status Code #7002</h2>

<p class="wp-block-paragraph">This is not an error, you did it! Today is a glorious day! It is time to celebrate! You successfully sent an email with a PLC and a CP module. People told you that it couldn&rsquo;t be done but you proved them wrong. Time to kick back and enjoy this moment.</p>

<p class="wp-block-paragraph"><strong>Learn more about DMC&apos;s <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/plc-programming">PLC Programming expertise</a> and <a href="/contact">contact us</a> with project inquiries or questions.</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/19834/sending-emails-with-a-siemens-1200-plc/">Sending Emails with a Siemens 1200 PLC</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Getting Started with WinCC OA: Part 10 &#8211; Panel Nesting and $-Parameters</title>
		<link>https://static.dmcinfo.com/blog/19860/getting-started-with-wincc-oa-part-10-panel-nesting-and-parameters/</link>
		
		<dc:creator><![CDATA[Nick Leisle]]></dc:creator>
		<pubDate>Mon, 22 Jun 2020 17:09:40 +0000</pubDate>
				<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[WinCC]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/19860/getting-started-with-wincc-oa-part-10-panel-nesting-and-parameters/</guid>

					<description><![CDATA[<p>Welcome back to “Getting Started with WinCC OA”! If you aren’t familiar with the series’ previous topics, it’s recommended that you read the prior installments before proceeding: Way back in Part 3 of “Getting Started with WinCC OA”, we investigated the basics of panel creation and development by adding objects and configuring their properties. In [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/19860/getting-started-with-wincc-oa-part-10-panel-nesting-and-parameters/">Getting Started with WinCC OA: Part 10 &#8211; Panel Nesting and $-Parameters</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Welcome back to “Getting Started with WinCC OA”! If you aren’t familiar with the series’ previous topics, it’s recommended that you read the prior installments before proceeding:</p>



<ul class="wp-block-list">
<li><a href="https://static.dmcinfo.com/blog/21725/getting-started-with-wincc-oa-part-1-creating-opening-a-project/">Part 1: Creating and Opening a Project</a></li>



<li><a href="https://static.dmcinfo.com/blog/21697/getting-started-with-wincc-oa-part-2-folder-structure-gedi-layout/">Part 2: Folder Structure and Gedi Layout</a></li>



<li><a href="https://static.dmcinfo.com/blog/21531/getting-started-with-wincc-oa-part-3-panels-the-basics/">Part 3: Panels | The Basics</a></li>



<li><a href="https://static.dmcinfo.com/blog/21450/getting-started-with-wincc-oa-part-4-panel-scripting-environments-and-quicktest/">Part 4: Panel Scripting Environments and QuickTest</a></li>



<li><a href="https://static.dmcinfo.com/blog/21377/getting-started-with-wincc-oa-part-5-scripting-syntax/">Part 5: Scripting Syntax</a></li>



<li><a href="https://static.dmcinfo.com/blog/21256/getting-started-with-wincc-oa-part-6-para-overview-and-datapoint-creation/">Part 6: Para Overview and Datapoint Creation</a></li>



<li><a href="https://static.dmcinfo.com/blog/21113/getting-started-with-wincc-oa-part-7-interacting-with-datapoints-via-scripting/">Part 7: Interacting with Datapoints via Scripting</a></li>



<li><a href="https://static.dmcinfo.com/blog/20658/getting-started-with-wincc-oa-part-8-libraries/">Part 8: Libraries</a></li>



<li><a href="https://static.dmcinfo.com/blog/20143/getting-started-with-wincc-oa-part-9-color-database-and-high-performance-best-practices/">Part 9: Color Database &amp; High Performance Best Practices</a></li>
</ul>



<p class="wp-block-paragraph">Way back in <a href="https://static.dmcinfo.com/blog/21531/getting-started-with-wincc-oa-part-3-panels-the-basics/">Part 3 of “Getting Started with WinCC OA”</a>, we investigated the basics of panel creation and development by adding objects and configuring their properties. In Part 10, we&#8217;ll dive back into the world of panels by looking at panel nesting and the mechanism with which we pass information from one panel to its nested counterpart: $-Parameters.</p>



<h2 class="wp-block-heading" id="h-panel-references-embedded-panels">Panel References/Embedded Panels</h2>



<p class="wp-block-paragraph">Panel references are used to insert or nest existing panels (reference panels) into other panels (parent panels). This is useful for creating commonly repeated objects like valves or motors and utilizing them in larger systems. If changes are made to the original panel, all references will similarly update within their parent panel.</p>



<p class="wp-block-paragraph">To create a panel reference, simply drag a panel from the Project View tree onto the working space of another panel.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="900" height="278" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/1-embedded-panels.png" alt="1 embedded panels" class="wp-image-19837" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/1-embedded-panels.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/1-embedded-panels-300x93.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/1-embedded-panels-768x237.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<h2 class="wp-block-heading" id="h-parameters">$-Parameters</h2>



<p class="wp-block-paragraph">Often, developers will want a reference panel to receive specific properties from its parent panel (including, but not limited to, colors, types, and text); This is done via $-Parameters(dollar parameters). <strong>$-Parameters</strong> are defined in reference panel scripting simply by placing a “$” in front of a variable name. Whenever a reference panel is added to a parent panel, a <strong>“Reference Defining”</strong> popup will appear and the user can configure $-Parameters as they choose. $-Parameters can be later changed by either:</p>



<ol class="wp-block-list">
<li>Double-clicking the panel reference to bring up the “Reference Defining” popup</li>



<li>Changing the $-Parameters directly in the panel properties</li>
</ol>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="625" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/2-motor-panel.png" alt="2 motor panel" class="wp-image-19838" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/2-motor-panel.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/2-motor-panel-300x208.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/2-motor-panel-768x533.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<h2 class="wp-block-heading" id="h-example">Example</h2>



<p class="wp-block-paragraph">To continue with our evolving example panel from prior “Getting Started with WinCC OA” installments, let’s now assume that we now have three motors that we want to use with our TestPanel. With two additional motors, we must first add additional datapoints in Para to represent the new motors’ PLC tags. Simply add two new datapoints (“myMotor2” and “myMotor3”) underneath our “myDatapointType” datapoint type.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="642" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/3-motor-datatype.png" alt="3 motor datatype" class="wp-image-19839" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/3-motor-datatype.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/3-motor-datatype-300x214.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/3-motor-datatype-768x548.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">Now that we have our additional motors configured in Para, we’ll want to create three references of TestPanel in another parent panel. However, our current TestPanel is configured to work only with the<strong> “myMotor”</strong> datapoint.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="256" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/4-motor-speed-script.png" alt="4 motor speed script" class="wp-image-19840" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/4-motor-speed-script.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/4-motor-speed-script-300x85.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/4-motor-speed-script-768x218.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">To utilize our TestPanel as a re-usable reference, we must first incorporate flexibility and allow the panel to use a variety of datapoints, not just “myMotor”. How might we do this? With $-Parameters.</p>



<p class="wp-block-paragraph">To implement a $-Parameter within our TestPanel script, we’ll assign the $-Parameter <strong>“$motorDpe”</strong> to the internal string variable <strong>“motorDpe”</strong> and then replace every occurrence of the text “myMotor” with the variable “motorDpe.” With this modification, we may pass in “myMotor”, “myMotor2”, and “myMotor3” into the TestPanel to substitute for the string “motorDpe.”</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="320" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/5-motor-dep.png" alt="5 motor dep" class="wp-image-19841" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/5-motor-dep.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/5-motor-dep-300x107.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/5-motor-dep-768x273.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">CTRL Script (WinCC OA)</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#uses "OpenLibrary/Enums/MotorStatusType"
#uses "ColorConst"

string motorDpe = $motorDpe;

//=============================== Panel initialization =========================================
initializePanel()
{
  //Whenever rSpeed or rMaxSpeed changes, call the function "onSpeedChange"
  dpConnect("onSpeedChange", motorDpe + ".rSpeed", motorDpe + ".rMaxSpeed");

  //Whenever iStatus changes, call the function "onStatusChange"
  dpConnect("onStatusChange", motorDpe + ".iStatus");

  //Set rectangle's label text to its motor dpe
  setValue("motorLabel", "text", motorDpe);
}


//=============================== Text Field Command =========================================
//Textbox is selected and user keys "Enter"
void textboxCmd()
{
  //Assign the textbox's text value to rMaxSpeed
  dpSet(motorDpe + ".rMaxSpeed", maxSpeedTextbox.text);
}


//=============================== On Speed / Max Speed Value Change =================================
void onSpeedChange(string speedDp, float speedValue, string maxSpeedDp, float maxSpeedValue)
{
  //Define the variable whose value will be assigned to iStatus
  int iStatusValue;

  //Determine what value to assign iStatusValue (and subsequently "myMotor.iStatus")
  switch (speedValue)
  {
    //If "myMotor.rSpeed" is 0, set iStatusValue to 0
    case 0:
      iStatusValue = (int)MotorStatusType::Stopped;
      break;

    //Otherwise, if "myMotor.rSpeed" > "myMotor.rMaxSpeed", set iStatusValue to Estop status int
    //           if not, set iStatusValue to Forward status int
    default:
      iStatusValue = ((speedValue >= maxSpeedValue) ? (int)MotorStatusType::Estop : (int)MotorStatusType::Forward);
      break;
  }

  //Assign iStatusValue's value to "myMotor.iStatus"
  dpSet(motorDpe + ".iStatus", iStatusValue);

  //Set the maxSpeedTextbox and speedTextbox's test to their respective values
  //NOTE: dpValToString ensures the units we assigned earlier in the series are displayed.
  //      Simply using &lt;Textbox>.text = &lt;speedValue> will work, but will not display appropriate units
  maxSpeedTextbox.text = dpValToString(motorDpe + ".rMaxSpeed", maxSpeedValue, true);
  speedTextbox.text = dpValToString(motorDpe + ".rSpeed", speedValue, true);
}

//=============================== On Status Change =========================================
void onStatusChange(string statusDp, int statusValue)
{
  //Define the variable whose value will be assigned to the rectangle's color property
  string rectangleColor;

  //Determine color to assign to rectangle based off iStatus
  if (statusValue == (int)MotorStatusType::Stopped)
  {
    rectangleColor = STOPPED_COLOR;
  }

  if (statusValue == (int)MotorStatusType::Estop)
  {
    rectangleColor = ESTOPPED_COLOR;
  }

  if (statusValue == (int)MotorStatusType::Forward)
  {
    rectangleColor = FORWARD_COLOR;
  }

  //Assign selected color to rectangle
  setValue("rectangle", "backCol", rectangleColor);
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #9CDCFE">#uses</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;OpenLibrary/Enums/MotorStatusType&quot;</span></span>
<span class="line"><span style="color: #9CDCFE">#uses</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;ColorConst&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">string motorDpe = $motorDpe;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">//=============================== Panel initialization =========================================</span></span>
<span class="line"><span style="color: #DCDCAA">initializePanel</span><span style="color: #D4D4D4">()</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #6A9955">  //Whenever rSpeed or rMaxSpeed changes, call the function &quot;onSpeedChange&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">dpConnect</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;onSpeedChange&quot;</span><span style="color: #D4D4D4">, motorDpe + </span><span style="color: #CE9178">&quot;.rSpeed&quot;</span><span style="color: #D4D4D4">, motorDpe + </span><span style="color: #CE9178">&quot;.rMaxSpeed&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">  //Whenever iStatus changes, call the function &quot;onStatusChange&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">dpConnect</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;onStatusChange&quot;</span><span style="color: #D4D4D4">, motorDpe + </span><span style="color: #CE9178">&quot;.iStatus&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">  //Set rectangle&apos;s label text to its motor dpe</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">setValue</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;motorLabel&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;text&quot;</span><span style="color: #D4D4D4">, motorDpe);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">//=============================== Text Field Command =========================================</span></span>
<span class="line"><span style="color: #6A9955">//Textbox is selected and user keys &quot;Enter&quot;</span></span>
<span class="line"><span style="color: #569CD6">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">textboxCmd</span><span style="color: #D4D4D4">()</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #6A9955">  //Assign the textbox&apos;s text value to rMaxSpeed</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">dpSet</span><span style="color: #D4D4D4">(motorDpe + </span><span style="color: #CE9178">&quot;.rMaxSpeed&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">maxSpeedTextbox</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">text</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">//=============================== On Speed / Max Speed Value Change =================================</span></span>
<span class="line"><span style="color: #569CD6">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">onSpeedChange</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">speedDp</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">float</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">speedValue</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">maxSpeedDp</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">float</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">maxSpeedValue</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #6A9955">  //Define the variable whose value will be assigned to iStatus</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">int</span><span style="color: #D4D4D4"> iStatusValue;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">  //Determine what value to assign iStatusValue (and subsequently &quot;myMotor.iStatus&quot;)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">switch</span><span style="color: #D4D4D4"> (speedValue)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #6A9955">    //If &quot;myMotor.rSpeed&quot; is 0, set iStatusValue to 0</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">case</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      iStatusValue = (</span><span style="color: #569CD6">int</span><span style="color: #D4D4D4">)</span><span style="color: #4EC9B0">MotorStatusType</span><span style="color: #D4D4D4">::Stopped;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">break</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">    //Otherwise, if &quot;myMotor.rSpeed&quot; &gt; &quot;myMotor.rMaxSpeed&quot;, set iStatusValue to Estop status int</span></span>
<span class="line"><span style="color: #6A9955">    //           if not, set iStatusValue to Forward status int</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">default</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      iStatusValue = ((speedValue &gt;= maxSpeedValue) ? (</span><span style="color: #569CD6">int</span><span style="color: #D4D4D4">)</span><span style="color: #4EC9B0">MotorStatusType</span><span style="color: #D4D4D4">::Estop : (</span><span style="color: #569CD6">int</span><span style="color: #D4D4D4">)</span><span style="color: #4EC9B0">MotorStatusType</span><span style="color: #D4D4D4">::Forward);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">break</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">  //Assign iStatusValue&apos;s value to &quot;myMotor.iStatus&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">dpSet</span><span style="color: #D4D4D4">(motorDpe + </span><span style="color: #CE9178">&quot;.iStatus&quot;</span><span style="color: #D4D4D4">, iStatusValue);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">  //Set the maxSpeedTextbox and speedTextbox&apos;s test to their respective values</span></span>
<span class="line"><span style="color: #6A9955">  //NOTE: dpValToString ensures the units we assigned earlier in the series are displayed.</span></span>
<span class="line"><span style="color: #6A9955">  //      Simply using &lt;Textbox&gt;.text = &lt;speedValue&gt; will work, but will not display appropriate units</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">maxSpeedTextbox</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">text</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">dpValToString</span><span style="color: #D4D4D4">(motorDpe + </span><span style="color: #CE9178">&quot;.rMaxSpeed&quot;</span><span style="color: #D4D4D4">, maxSpeedValue, </span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">speedTextbox</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">text</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">dpValToString</span><span style="color: #D4D4D4">(motorDpe + </span><span style="color: #CE9178">&quot;.rSpeed&quot;</span><span style="color: #D4D4D4">, speedValue, </span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">//=============================== On Status Change =========================================</span></span>
<span class="line"><span style="color: #569CD6">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">onStatusChange</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">string</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">statusDp</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">int</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">statusValue</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #6A9955">  //Define the variable whose value will be assigned to the rectangle&apos;s color property</span></span>
<span class="line"><span style="color: #D4D4D4">  string rectangleColor;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">  //Determine color to assign to rectangle based off iStatus</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (statusValue == (</span><span style="color: #569CD6">int</span><span style="color: #D4D4D4">)</span><span style="color: #4EC9B0">MotorStatusType</span><span style="color: #D4D4D4">::Stopped)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    rectangleColor = STOPPED_COLOR;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (statusValue == (</span><span style="color: #569CD6">int</span><span style="color: #D4D4D4">)</span><span style="color: #4EC9B0">MotorStatusType</span><span style="color: #D4D4D4">::Estop)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    rectangleColor = ESTOPPED_COLOR;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (statusValue == (</span><span style="color: #569CD6">int</span><span style="color: #D4D4D4">)</span><span style="color: #4EC9B0">MotorStatusType</span><span style="color: #D4D4D4">::Forward)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    rectangleColor = FORWARD_COLOR;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">  //Assign selected color to rectangle</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">setValue</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;rectangle&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;backCol&quot;</span><span style="color: #D4D4D4">, rectangleColor);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>NOTE:</strong> $-Parameters can be interspersed throughout our code; wherever a $-Parameter is referenced, the value passed in from the parent panel will take its place. DMC’s best practices, however, entail using a $-Parameter only once by assigning an internal variable to the $-Parameter and then using said variable within the panel’s script. In the case a $-Parameter needs to have its name changed, the modification only needs to be made once in the panel code.</p>



<p class="wp-block-paragraph">Now that our TestPanel is configured to accept a variety of datapoints (of type “myDatapointType”), we may now begin creating panel references.</p>



<ol class="wp-block-list">
<li>Create a parent panel called <strong>“ParentPanel.”</strong></li>



<li>Drag a <strong>“TestPanel”</strong> into the “ParentPanel” working space</li>



<li>Add the datapoint <strong>“myMotor”</strong> to the <strong>“$motorDpe”</strong> value field
<ul class="wp-block-list">
<li>This can be done in the reference panel&#8217;s &#8220;Reference defining&#8221; popup</li>



<li>Or in the reference panel&#8217;s Property editor</li>
</ul>
</li>



<li>Repeat steps 2 and 3 for the datapoints <strong>“myMotor2”</strong> and <strong>“myMotor3.”</strong></li>
</ol>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="329" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/7-parent-panel.png" alt="7 parent panel" class="wp-image-19842" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/7-parent-panel.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/7-parent-panel-300x110.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/7-parent-panel-768x281.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="has-text-align-center wp-block-paragraph"><strong>Or</strong></p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="508" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/8-property-editor.png" alt="8 property editor" class="wp-image-19843" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/8-property-editor.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/8-property-editor-300x169.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/8-property-editor-768x433.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">Congratulations! You’ve created a parent panel with three reference panels. If any changes are made to TestPanel, those changes would propagate into the parent panels’ references. Let’s test this.</p>



<p class="wp-block-paragraph">Since it’s not evident which panel reference refers to which motor, we’ll make a couple of modifications within TestPanel. We’ll first add a primitive text object over our rectangle (name ‘motorLabel’, set Foreground Color to ‘Base_White’, change the text to ‘Motor Dpe’, and center the text over the ‘rectangle’ object) to serve as a label.</p>



<p class="wp-block-paragraph">Additionally, we’ll add a <strong>setValue</strong> command to the panel initialization in Scope Lib to populate the label with the correct motor dpe.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="401" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/9-motor-test-panel.png" alt="9 motor test panel" class="wp-image-19844" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/9-motor-test-panel.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/9-motor-test-panel-300x134.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/9-motor-test-panel-768x342.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="546" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/10-test-panel-props.png" alt="10 test panel props" class="wp-image-19845" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/10-test-panel-props.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/10-test-panel-props-300x182.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/10-test-panel-props-768x466.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="609" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/11-test-panel-script.png" alt="11 test panel script" class="wp-image-19846" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/11-test-panel-script.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/11-test-panel-script-300x203.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/11-test-panel-script-768x520.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">Upon opening ParentPanel (if ParentPanel is already open, close it so that the working space’s reference panels can be updated) and running QuickTest, you’ll notice the new panel titles are now labeled “myMotor”, “myMotor2”, and “myMotor3.”</p>



<p class="wp-block-paragraph">Furthermore, you’ll notice that changing rSpeed and rMaxSpeed in each of the datapoints (myMotor, myMotor2, and myMotor3) all reflect on their appropriate panels.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="704" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/12-all-motors.png" alt="12 all motors" class="wp-image-19847" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/12-all-motors.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/12-all-motors-300x235.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/12-all-motors-768x601.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<h2 class="wp-block-heading" id="h-additional-parameter-features">Additional $-Parameter Features</h2>



<p class="wp-block-paragraph"><u><strong>Optional parameters</strong></u></p>



<p class="wp-block-paragraph">By default, $-Parameters are required to be passed down from parent panel to reference panel. When a reference panel is created, its dollar parameters will, by default, be self-defined.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="450" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/13-panel-parameter.png" alt="13 panel parameter" class="wp-image-19848" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/13-panel-parameter.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/13-panel-parameter-300x150.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/13-panel-parameter-768x384.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="670" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/14-motor-properties.png" alt="14 motor properties" class="wp-image-19849" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/14-motor-properties.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/14-motor-properties-300x223.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/14-motor-properties-768x572.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">If no alternative $-Parameter is provided, the panel in runtime will generate an error (assuming the parent panel does not become a reference panel itself).</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="151" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/15-parameter-script.png" alt="15 parameter script" class="wp-image-19850" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/15-parameter-script.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/15-parameter-script-300x50.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/15-parameter-script-768x129.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">However, if an underscore is placed directly after the “$”, the parameter then becomes optional. When a reference panel is created, its optional dollar parameters are not automatically defined.</p>



<p class="wp-block-paragraph">Optional parameters are accessible in the “Reference defining” popup under the “optional” tab or along with other $-Parameters in the Property Editor.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="400" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/16-blank-parameter.png" alt="16 blank parameter" class="wp-image-19851" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/16-blank-parameter.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/16-blank-parameter-300x133.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/16-blank-parameter-768x341.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph"><u><strong>Specifying $-Parameter Data Types</strong></u></p>



<p class="wp-block-paragraph">$-Parameters can be designated to have specific data types according to their names’ prefixes:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="584" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/17-character-types_1.png" alt="17 character types 1" class="wp-image-19852" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/17-character-types_1.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/17-character-types_1-300x195.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/17-character-types_1-768x498.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="453" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/18-data-types.png" alt="18 data types" class="wp-image-19853" srcset="https://static.dmcinfo.com/wp-content/uploads/2025/05/18-data-types.png 900w, https://static.dmcinfo.com/wp-content/uploads/2025/05/18-data-types-300x151.png 300w, https://static.dmcinfo.com/wp-content/uploads/2025/05/18-data-types-768x387.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph"><u><strong>Specifying $-Parameter Parameter Types</strong></u></p>



<p class="wp-block-paragraph">Fun Fact of the Day: Clicking the ellipsis in the reference defining panel calls a popup that assists the user in a $-Parameter selection. This is only done, however, if a $-Parameter does not adhere to a data-type-specifying convention (and is therefore labeled as “[unknown]”). From this<strong> “Menu” </strong>popup, one can choose to open the <strong>“DP-Selector”</strong>, <strong>“DPE-Selector”</strong>, <strong>“Color-Selector”</strong>, <strong>“Panel-Selector”</strong>, <strong>“Font-Selector”</strong>, or <strong>“Keyword-Selector”</strong> (if applicable).</p>



<p class="wp-block-paragraph"><strong>NOTE:</strong> The “DP-Selector” only allows the user to select the highest level of a datapoint structure while the “DPE-Selector” allows the user to select the datapoint or any of its respective elements.</p>



<p class="wp-block-paragraph"><br>
<em>Reference Defining Panel</em></p>



<p class="wp-block-paragraph"><br>
<em>DP-Selector</em></p>



<p class="wp-block-paragraph"><br>
<em>DPE-Selector</em></p>



<p class="wp-block-paragraph"><br>
<em>Color-Selector</em></p>



<p class="wp-block-paragraph"><br>
<em>Panel-Selector</em></p>



<p class="wp-block-paragraph"><br>
<em>Font-Selector</em></p>



<p class="wp-block-paragraph">Similar to how the naming convention allows $-Parameters to be defined as specific datatypes, the naming convention also allows users to specify $-Parameters’ parameter types. If a $-Parameter contains the name “dp”, “dpe”, &#8220;color”, &#8220;panel&#8221;, or “font”, the ellipses click will bypass the “Menu” panel and navigate directly to the appropriate selector.</p>



<p class="wp-block-paragraph"><strong>NOTE:</strong> If a user were to specify a data type and a parameter type for a specific $-Parameter, the parameter type would take precedence and the $-Parameter would be considered an “[unknown]” data type.</p>



<p class="wp-block-paragraph">For example, “$sMyDpe” would be considered an unknown (as opposed to a string) and open the DPE-Selector.</p>



<p class="wp-block-paragraph"><strong>NOTE 2:</strong> If a user has a lack of foresight and includes multiple parameter types in their $-Parameter name, then a selector will open in the following priority:<br>
<strong>Dpe &gt; dp &gt; panel &gt;&nbsp;color &gt; font</strong></p>



<p class="wp-block-paragraph">For example, “$myColorDpe” would open the DPE-Selector as opposed to the Color-Selector.</p>



<p class="wp-block-paragraph">Now that we’ve reviewed the wonders of panel embedding and started learning the magic of $-Parameters, it’s time to further our knowledge of panels. In the next edition of “Getting Started with WinCC OA”, we’ll dive into another form of panel references, Child Panels (i.e. Popups), and how $-Parameters are used in that context.</p>



<p class="wp-block-paragraph"><strong>Topics to look forward to in this series:&nbsp;</strong></p>



<ul class="wp-block-list">
<li><a href="https://static.dmcinfo.com/blog/19540/getting-started-with-wincc-oa-part-11-panels-child-panels-popups/">Part 11:&nbsp;Panels | Child Panels (Popups)</a></li>



<li><a href="https://static.dmcinfo.com/blog/18628/getting-started-with-wincc-oa-part-12-modules-and-embedded-modules/">Part 12: Modules &amp; Embedded Modules</a></li>
</ul>



<p class="wp-block-paragraph"><a href="https://static.dmcinfo.com/contact">Contact</a>&nbsp;DMC to get started on your next WinCC project and learn more about our&nbsp;<a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/siemens-simatic-wincc-programming">Siemens SIMATIC WinCC Programming</a>&nbsp;as well as our&nbsp;<a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/wincc-open-architecture-development">WinCC Open Architecture Development.</a></p>
<p>The post <a href="https://static.dmcinfo.com/blog/19860/getting-started-with-wincc-oa-part-10-panel-nesting-and-parameters/">Getting Started with WinCC OA: Part 10 &#8211; Panel Nesting and $-Parameters</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Sorting Multiple Columns in a Table with React</title>
		<link>https://static.dmcinfo.com/blog/19887/sorting-multiple-columns-in-a-table-with-react/</link>
		
		<dc:creator><![CDATA[Rafael Rejuso]]></dc:creator>
		<pubDate>Tue, 02 Jun 2020 14:08:49 +0000</pubDate>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[PC Application Development]]></category>
		<category><![CDATA[Web Application Development]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[React]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/19887/sorting-multiple-columns-in-a-table-with-react/</guid>

					<description><![CDATA[<p>Tables are a fast way to show a lot of valuable data. There are many guides on sorting tables by a column in React, but sorting multiple columns is something that can take some effort. At the end of this guide, you should have a sortable table where you can click multiple columns. For this [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/19887/sorting-multiple-columns-in-a-table-with-react/">Sorting Multiple Columns in a Table with React</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Tables are a fast way to show a lot of valuable data. There are many guides on sorting tables by a column in React, but sorting multiple columns is something that can take some effort. At the end of this guide, you should have a sortable table where you can click multiple columns.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/sorting-mulitple-columns-react.gif" alt="Sorting mulitple columns with React"/></figure>



<p class="wp-block-paragraph">For this tutorial, we will be leveraging the use of LINQ&nbsp;to make sorting quite painless, and optionally Material-UI for styling the table. At the very end, I will also briefly describe a way of implementing this table without using LINQ&nbsp;and only using base React.</p>



<h2 class="wp-block-heading" id="h-tools-used-in-this-blog">Tools Used in this Blog:</h2>



<ul class="wp-block-list">
<li>LINQ&nbsp;</li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10114/a-simple-guide-to-material-ui-grids">Material-UI </a><em>(Optional)</em></li>



<li>Basic React hooks</li>



<li>Functional React</li>
</ul>



<h2 class="wp-block-heading" id="h-setup">Setup</h2>



<p class="wp-block-paragraph">First, we need some data.&nbsp;For the purposes of this example, I just created some dummy data that we can sort. I also defined an interface for the data type and an enum for departments that a person can belong to.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly> const dataList=&#91;
    {name: 'Ryan H.',   hours: 30, startDate: new Date('2019-01-14'), department: Department.Marketing},
    {name: 'Ariel P.',  hours: 22, startDate: new Date('2017-03-12'), department: Department.Sales},
    {name: 'Ryan Y.',   hours: 31, startDate: new Date('2015-09-12'), department: Department.Marketing},
    {name: 'Ed T.',     hours: 22, startDate: new Date('2017-03-12'), department: Department.Engineering},
    {name: 'Matt G.',   hours: 30, startDate: new Date('2017-03-12'), department: Department.Marketing},
    {name: 'Olivia H.', hours: 32, startDate: new Date('2018-05-10'), department: Department.Engineering}&#93; as TableData[];</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">dataList</span><span style="color: #D4D4D4">=&#91;</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span><span style="color: #9CDCFE">name:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Ryan H.&apos;</span><span style="color: #D4D4D4">,   </span><span style="color: #9CDCFE">hours:</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">startDate:</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Date</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;2019-01-14&apos;</span><span style="color: #D4D4D4">), </span><span style="color: #9CDCFE">department:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Department</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Marketing</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span><span style="color: #9CDCFE">name:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Ariel P.&apos;</span><span style="color: #D4D4D4">,  </span><span style="color: #9CDCFE">hours:</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">22</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">startDate:</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Date</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;2017-03-12&apos;</span><span style="color: #D4D4D4">), </span><span style="color: #9CDCFE">department:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Department</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Sales</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span><span style="color: #9CDCFE">name:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Ryan Y.&apos;</span><span style="color: #D4D4D4">,   </span><span style="color: #9CDCFE">hours:</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">31</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">startDate:</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Date</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;2015-09-12&apos;</span><span style="color: #D4D4D4">), </span><span style="color: #9CDCFE">department:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Department</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Marketing</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span><span style="color: #9CDCFE">name:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Ed T.&apos;</span><span style="color: #D4D4D4">,     </span><span style="color: #9CDCFE">hours:</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">22</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">startDate:</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Date</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;2017-03-12&apos;</span><span style="color: #D4D4D4">), </span><span style="color: #9CDCFE">department:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Department</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Engineering</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span><span style="color: #9CDCFE">name:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Matt G.&apos;</span><span style="color: #D4D4D4">,   </span><span style="color: #9CDCFE">hours:</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">startDate:</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Date</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;2017-03-12&apos;</span><span style="color: #D4D4D4">), </span><span style="color: #9CDCFE">department:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Department</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Marketing</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span><span style="color: #9CDCFE">name:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Olivia H.&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">hours:</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">32</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">startDate:</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Date</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;2018-05-10&apos;</span><span style="color: #D4D4D4">), </span><span style="color: #9CDCFE">department:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">Department</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Engineering</span><span style="color: #D4D4D4">}&#93; </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">[];</span></span></code></pre></div>



<p class="wp-block-paragraph">Our interface is <strong>TableData.</strong>&nbsp;We have an enum called <strong>Departments</strong> which lists the available department&#8217;s people may be in:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>interface TableData{
    name: String,
    hours: number,
    startDate: Date,
    department: Department
}

enum Department{
    Marketing = 'Marketing',
    Sales = 'Sales',
    Engineering = 'Engineering',
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">interface</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">name</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">hours</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">number</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">startDate</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">Date</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">department</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">Department</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">enum</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">Department</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #4FC1FF">Marketing</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&apos;Marketing&apos;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #4FC1FF">Sales</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&apos;Sales&apos;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #4FC1FF">Engineering</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&apos;Engineering&apos;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">It’s important to note that this interface and enum is solely for structuring our table, and not for sorting. We will eventually add another interface and enum for sorting.</p>



<p class="wp-block-paragraph">For the case of simulation, I’ll be placing the data into another file and returning it from a function call called <strong>fetchData.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>export const fetchData = () => { return dataList;}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">fetchData</span><span style="color: #D4D4D4"> = () </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> { </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">;}</span></span></code></pre></div>



<p class="wp-block-paragraph">For the table, we’ll be using Material-UI, but this method will absolutely work with just a regular table. If you don’t want to use Material-UI tables, just replace the tags with the corresponding ones below. Everything but TableBody has a corresponding tag which just contains a collection of &lt;tr&gt; tags.</p>


<table style="width:100%; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; margin-bottom:40px;">
<tbody>
<tr style="text-align:center;">
<th style="border-collapse:collapse; border-style:solid; border-width:medium; border-spacing: 20px; border:1px solid black; height:100px; font-size:24px; border-right-style:solid; border-right-width:medium; border-left-style:solid; border-left-width:medium;">MaterialUI</th>
<th style="border-collapse:collapse; border-style:solid; border-width:medium; border-spacing: 20px; border:1px solid black; height:100px; font-size:24px; border-right-style:solid; border-right-width:medium; border-left-style:solid; border-left-width:medium;">HTML</th>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">TableHead</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">th</td>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">TableBody</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">&#8211;</td>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">TableRow</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">tr</td>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">TableCell</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">td</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">Now we pull our data from the other file by calling <strong>fetchData</strong>, set up the appropriate table headers, and map our data to the corresponding table cells. For the sake of keeping clean code, I moved the sortable table headers to another component, so our code should look somewhat like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import React from "react";
import {Table, TableRow, TableCell, TableBody } from '@material-ui/core';
import { fetchData, TableData } from "./fetchData";
import { SortableHeader } from "./sortableTableHeader";

export const TableExample = () => {
    const dataList = fetchData();
    return(
        &lt;div>
            &lt;Table>
                &lt;SortableHeader/>
                &lt;TableBody>
                    {dataList.map((data) => { return(
                        &lt;TableRow>
                            &lt;TableCell>
                                {data.name}
                            &lt;/TableCell>
                            &lt;TableCell>
                                {data.hours}
                            &lt;/TableCell>
                            &lt;TableCell>
                                {data.startDate.toDateString()}
                            &lt;/TableCell>
                            &lt;TableCell>
                                {data.department}
                            &lt;/TableCell>
                        &lt;/TableRow>
                        )})}
                &lt;/TableBody>
            &lt;/Table>
        &lt;/div>
    )
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">React</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;react&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> {</span><span style="color: #9CDCFE">Table</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">TableRow</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">TableBody</span><span style="color: #D4D4D4"> } </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;@material-ui/core&apos;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> { </span><span style="color: #9CDCFE">fetchData</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">TableData</span><span style="color: #D4D4D4"> } </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;./fetchData&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> { </span><span style="color: #9CDCFE">SortableHeader</span><span style="color: #D4D4D4"> } </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;./sortableTableHeader&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">TableExample</span><span style="color: #D4D4D4"> = () </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">dataList</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">fetchData</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;</span><span style="color: #4EC9B0">div</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;</span><span style="color: #4EC9B0">Table</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #9CDCFE">SortableHeader</span><span style="color: #D4D4D4">/&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableBody</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                    {</span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">map</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">data</span><span style="color: #D4D4D4">) =&gt; { </span><span style="color: #DCDCAA">return</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">                        &lt;</span><span style="color: #9CDCFE">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                                {</span><span style="color: #9CDCFE">data</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">name</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                                {</span><span style="color: #9CDCFE">data</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">hours</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                                {</span><span style="color: #9CDCFE">data</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">startDate</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">toDateString</span><span style="color: #D4D4D4">()}</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                                {</span><span style="color: #9CDCFE">data</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">department</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                        &lt;/</span><span style="color: #9CDCFE">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                        )})}</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;/</span><span style="color: #9CDCFE">TableBody</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;/</span><span style="color: #9CDCFE">Table</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;/</span><span style="color: #9CDCFE">div</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    )</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import React from "react";
import { TableHead, TableRow, TableCell } from "@material-ui/core";

export const SortableHeader = () => {
    return (
        &lt;TableHead>
            &lt;TableRow>
                &lt;TableCell>Name&lt;/TableCell>
                &lt;TableCell>Hours&lt;/TableCell>
                &lt;TableCell>Date&lt;/TableCell>
                &lt;TableCell>Department&lt;/TableCell>
            &lt;/TableRow>
        &lt;/TableHead>
    );
};</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">React</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;react&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> { </span><span style="color: #9CDCFE">TableHead</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">TableRow</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4"> } </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;@material-ui/core&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">SortableHeader</span><span style="color: #D4D4D4"> = () </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;</span><span style="color: #4EC9B0">TableHead</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;</span><span style="color: #4EC9B0">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableCell</span><span style="color: #D4D4D4">&gt;</span><span style="color: #9CDCFE">Name</span><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableCell</span><span style="color: #D4D4D4">&gt;</span><span style="color: #9CDCFE">Hours</span><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableCell</span><span style="color: #D4D4D4">&gt;</span><span style="color: #9CDCFE">Date</span><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableCell</span><span style="color: #D4D4D4">&gt;</span><span style="color: #9CDCFE">Department</span><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;/</span><span style="color: #9CDCFE">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;/</span><span style="color: #9CDCFE">TableHead</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    );</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span></code></pre></div>



<p class="wp-block-paragraph">Which outputs something like this:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/1-react-tables-bad.png" alt=""/></figure>



<h2 class="wp-block-heading" id="h-implementation">Implementation</h2>



<p class="wp-block-paragraph">Our overall goal is to create an ordered queue of sorting configurations that will apply each sorting in order through the use of LINQ&nbsp;to our data. We will then update our data list which will be re-rendered and displayed in the desired sorting configuration.</p>



<p class="wp-block-paragraph"><p style="font-size:110%"><strong>Step 1: Define a Sorting configuration</strong></p></p>



<p class="wp-block-paragraph">A sorting configuration is essentially an object that has two things. The property/column of the list that we’re trying to sort, and the sorting type such as ascending or descending. Since our rows are all the same object type: TableData, we can use keyof TableData to get all the properties/columns of our table. The only thing we’d have to do is make an enum of the different sorting types that we need, in this case we’ll stick with the standard ascending/descending.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>interface SortingConfiguration{
    propertyName: keyof TableData,
    sortType: SortingType,
}

enum SortingType{
    Ascending,
    Descending,</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">interface</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SortingConfiguration</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">SortingType</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">enum</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SortingType</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #4FC1FF">Ascending</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #4FC1FF">Descending</span><span style="color: #D4D4D4">,</span></span></code></pre></div>



<p class="wp-block-paragraph"><p style="font-size:110%"><strong>Step 2: Utilize useState to Maintain a List of our Sorting Configurations</strong></p></p>



<p class="wp-block-paragraph">If you’ve never used <strong>useState</strong>, it’s a React hook that returns an array of two things: the first being the state of an object that is being maintained. The second is basically a function/dispatch that you can call to change the state. Here we’re initializing our list of sorting configurations to be an empty list since we want to start off with an unsorted table.</p>



<p class="wp-block-paragraph">Note: If you do want a table column to be sorted by default, all you would need to do is add a <strong>SortConfiguration </strong>object in between the square brackets</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>  const &#91;sortConfig, updateSortConfig&#93; = useState&lt;SortingConfiguration[]>([]);
    //Below is an example of sorting columns by name by default.
    const &#91;initializedSortConfig, updateInitSortConfig&#93; = useState&lt;SortingConfiguration[]>(&#91;
        {propertyName: 'name', sortConfig: SortingType.Descending}
    &#93;);</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> &#91;</span><span style="color: #4FC1FF">sortConfig</span><span style="color: #D4D4D4">, </span><span style="color: #4FC1FF">updateSortConfig</span><span style="color: #D4D4D4">&#93; = </span><span style="color: #DCDCAA">useState</span><span style="color: #D4D4D4">&lt;</span><span style="color: #4EC9B0">SortingConfiguration</span><span style="color: #D4D4D4">[]&gt;([]);</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">//Below is an example of sorting columns by name by default.</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> &#91;</span><span style="color: #4FC1FF">initializedSortConfig</span><span style="color: #D4D4D4">, </span><span style="color: #4FC1FF">updateInitSortConfig</span><span style="color: #D4D4D4">&#93; = </span><span style="color: #DCDCAA">useState</span><span style="color: #D4D4D4">&lt;</span><span style="color: #4EC9B0">SortingConfiguration</span><span style="color: #D4D4D4">[]&gt;(&#91;</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">propertyName:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;name&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sortConfig:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Descending</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">    &#93;);</span></span></code></pre></div>



<p class="wp-block-paragraph"><p style="font-size:110%"><strong>Step 3: Create a Function That Adds, Modifies, and Removes Our Sorting Configurations</strong></p></p>



<p class="wp-block-paragraph">Most sortable headers are clickable headers that switch between a cycle of unsorted -&gt; descending -&gt; ascending -&gt; unsorted -&gt; etc, but there are many different orders or ways in which you may wish to set this up. You should be able to create your own custom function that edits the sorting configuration given three basic criteria:</p>



<ol class="wp-block-list">
<li>Add a sorting configuration to a column when there is not an existing configuration</li>



<li>Modify a sorting configuration when there is an existing configuration
 
 
<ul class="wp-block-list">
<li>For example, going from descending to ascending, or vice versa</li>
</ul>
</li>



<li>Provide a way to remove a sorting configuration
 
 
<ul class="wp-block-list">
<li>This can be a part of criteria #2, but it is important enough to warrant its own criteria</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">We’ll be following a cycle of unsorted -&gt; descending -&gt; ascending -&gt; unsorted -&gt; etc… for the purposes of this guide.</p>



<p class="wp-block-paragraph">We will be making a function called sortBy that will take in a key of TableData. Basically, whenever we call sortBy on a given property/column, it should automatically fulfill our three criteria: add a new configuration when we don’t have one, alter a configuration if we do, and remove a configuration when we need to. We wrap it in a <strong>useCallback </strong>because, in the next step, we will pass this function down to a prop.</p>



<p class="wp-block-paragraph">So our basic structure looks like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly> const sortBy = useCallback(
        (propertyName: keyof TableData) => {
            let pendingChange = &#91;...sortConfig&#93;;
            const index = pendingChange.findIndex((config) => 
       						config.propertyName === 	propertyName)
            if(index > -1){
                // Existing configuration
            } else {
                // No existing configuration
            }
            updateSortConfig(&#91;...pendingChange&#93;);
        },
        &#91;sortConfig&#93;
    )</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">sortBy</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useCallback</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">        (</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">let</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4"> = &#91;...</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">&#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">index</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">findIndex</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">       						</span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4"> === 	</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4"> &gt; -</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">// Existing configuration</span></span>
<span class="line"><span style="color: #D4D4D4">            } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">// No existing configuration</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #DCDCAA">updateSortConfig</span><span style="color: #D4D4D4">(&#91;...</span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">&#93;);</span></span>
<span class="line"><span style="color: #D4D4D4">        },</span></span>
<span class="line"><span style="color: #D4D4D4">        &#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">    )</span></span></code></pre></div>



<p class="wp-block-paragraph">We use the spread operator to make a copy of the <strong>sortConfiguration</strong>. Then we use <strong>findIndex </strong>to search our copied list and see if there is an existing configuration that’s in our list. We’ll be using a lot of the spread operator, so if you aren’t experienced with using it, you can see more examples in <a href="https://static.dmcinfo.com/latest-thinking/blog/id/9668/categoryid/95/5-great-uses-of-the-spread-operator-in-a-react-app">this blog by Jacob Bruce</a>. Now that we have the basic structure laid out, let’s address the first criteria. This one is relatively simple since all we’re doing is adding a sorting configuration given the propertyName that was passed in:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>  if(index > -1){
                // Existing configuration
            } else {
                pendingChange = &#91;
                    ...pendingChange,
                    { propertyName: propertyName, sortType: SortingType.Descending },
                &#93;;
            }</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4"> &gt; -</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">// Existing configuration</span></span>
<span class="line"><span style="color: #D4D4D4">            } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4"> = &#91;</span></span>
<span class="line"><span style="color: #D4D4D4">                    ...</span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                    { </span><span style="color: #9CDCFE">propertyName:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sortType:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Descending</span><span style="color: #D4D4D4"> },</span></span>
<span class="line"><span style="color: #D4D4D4">                &#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span></code></pre></div>



<p class="wp-block-paragraph">Here we use the spread operator to push a new sorting configuration to the end of the queue.</p>



<p class="wp-block-paragraph">Now we have to handle our second and third criteria which you can only do on an existing configuration. We can remove extra code if instead of modifying we save the existing sort direction, remove the current configuration and lastly, add in a new configuration if it’s necessary to ‘modify’. Technically, our modification is removing a configuration of a property and adding in the same property back, but with a different sortType, but doing it this way makes it so we don’t have to write two similar code branches.</p>



<p class="wp-block-paragraph">In short, we use our index we found to store the existing sort type. We then remove that configuration using splice. Lastly, we use our saved sorting type to determine if we needed to add a new configuration. In this example, we check if it’s Descending, and if that’s the case, we change that sortType to Ascending. Note how, if the sorting type is Ascending, we do not ‘modify’ our sorting configuration list, but rather just let the code remove the configuration.</p>



<p class="wp-block-paragraph">Put together we have:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly> const sortBy = useCallback(
        (propertyName: keyof TableData) => {
            let pendingChange = &#91;...sortConfig&#93;;
            const index = pendingChange.findIndex((config) => 
                                    config.propertyName === propertyName)
            if(index > -1){
                //Save the sortType
                var currentSortType = pendingChange&#91;index&#93;.sortType;
                //Remove existing config
                pendingChange.splice(index, 1);
                //check if the sort type we saved is descending
                if (currentSortType === SortingType.Descending) {
                    pendingChange = &#91;
                        ...pendingChange,
                        { propertyName: propertyName, sortType: SortingType.Ascending },
                    &#93;;
                }
            } else {
                pendingChange = &#91;
                    ...pendingChange,
                    { propertyName: propertyName, sortType: SortingType.Descending },
                &#93;;
            }
            updateSortConfig(&#91;...pendingChange&#93;);
        },
        &#91;sortConfig&#93;
    )</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">sortBy</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useCallback</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">        (</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">let</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4"> = &#91;...</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">&#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">index</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">findIndex</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">                                    </span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4"> &gt; -</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">//Save the sortType</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">currentSortType</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">&#93;.</span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">//Remove existing config</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">splice</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">//check if the sort type we saved is descending</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">currentSortType</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Descending</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">                    </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4"> = &#91;</span></span>
<span class="line"><span style="color: #D4D4D4">                        ...</span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                        { </span><span style="color: #9CDCFE">propertyName:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sortType:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Ascending</span><span style="color: #D4D4D4"> },</span></span>
<span class="line"><span style="color: #D4D4D4">                    &#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">                }</span></span>
<span class="line"><span style="color: #D4D4D4">            } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4"> = &#91;</span></span>
<span class="line"><span style="color: #D4D4D4">                    ...</span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                    { </span><span style="color: #9CDCFE">propertyName:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sortType:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Descending</span><span style="color: #D4D4D4"> },</span></span>
<span class="line"><span style="color: #D4D4D4">                &#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #DCDCAA">updateSortConfig</span><span style="color: #D4D4D4">(&#91;...</span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">&#93;);</span></span>
<span class="line"><span style="color: #D4D4D4">        },</span></span>
<span class="line"><span style="color: #D4D4D4">        &#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">    )</span></span></code></pre></div>



<p class="wp-block-paragraph">Now the loop of unsorted -&gt; descending -&gt; ascending -&gt; unsorted -&gt; etc… is complete.</p>



<p class="wp-block-paragraph"><p style="font-size:110%"><strong>Step 4: Attach Our Function to the Table Headers</strong></p></p>



<p class="wp-block-paragraph">Now that we created our function, we need to attach it to table headers and make them something we can click. Since we’re passing down our props to our <strong>SortableTableHeader </strong>don’t forget to export our interfaces and enums to avoid errors. We’ll need to pass two things to our SortableTableHeader the first is our newly created sortBy function, and the second is our current <strong>sortConfig </strong>which will be used for arrow indicators to show what direction we’re sorting.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;Table>
    &lt;SortableHeader 
          sortBy={sortBy} 
          sortConfig={sortConfig}
          />
      &lt;TableBody>
		………
&lt;/Table>
&lt;/TableBody>
&lt;/pre>

&lt;pre class="brush:js">
interface SortableHeaderProps{
    sortBy: (string: keyof TableData) => void;
    sortConfig: SortingConfiguration[];
}

export const SortableHeader = ({sortBy, sortConfig}:SortableHeaderProps) => {
    return (
        &lt;TableHead>
            &lt;TableRow>
                &lt;TableCell>Name&lt;/TableCell>
                &lt;TableCell>Hours&lt;/TableCell>
                &lt;TableCell>Date&lt;/TableCell>
                &lt;TableCell>Department&lt;/TableCell>
            &lt;/TableRow>
        &lt;/TableHead>
    );
};</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;</span><span style="color: #4EC9B0">Table</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;</span><span style="color: #9CDCFE">SortableHeader</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #9CDCFE">sortBy</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">sortBy</span><span style="color: #D4D4D4">} </span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">          /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;</span><span style="color: #4EC9B0">TableBody</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">		………</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">Table</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableBody</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">pre</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">&lt;</span><span style="color: #9CDCFE">pre</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">class</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;brush:js&quot;</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #569CD6">interface</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SortableHeaderProps</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">sortBy</span><span style="color: #D4D4D4">: (</span><span style="color: #9CDCFE">string</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">SortingConfiguration</span><span style="color: #D4D4D4">[];</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">SortableHeader</span><span style="color: #D4D4D4"> = ({</span><span style="color: #9CDCFE">sortBy</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">}:</span><span style="color: #4EC9B0">SortableHeaderProps</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;</span><span style="color: #4EC9B0">TableHead</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;</span><span style="color: #4EC9B0">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableCell</span><span style="color: #D4D4D4">&gt;</span><span style="color: #9CDCFE">Name</span><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableCell</span><span style="color: #D4D4D4">&gt;</span><span style="color: #9CDCFE">Hours</span><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableCell</span><span style="color: #D4D4D4">&gt;</span><span style="color: #9CDCFE">Date</span><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #4EC9B0">TableCell</span><span style="color: #D4D4D4">&gt;</span><span style="color: #9CDCFE">Department</span><span style="color: #D4D4D4">&lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;/</span><span style="color: #9CDCFE">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;/</span><span style="color: #9CDCFE">TableHead</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    );</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span></code></pre></div>



<p class="wp-block-paragraph">To keep code DRY, I’ll be making a list of the columns that we want, and the TableData property they correspond to. This way, we can map over the function without copy/pasting TableCell four times.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>const tableColumn = &#91;
        {label:'Name', property:'name'},
        {label:'Hours', property:'hours'},
        {label:'Date', property:'startDate'},
        {label:'Department', property:'department'}
        &#93; as TableColumn[];</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">tableColumn</span><span style="color: #D4D4D4"> = &#91;</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">label:</span><span style="color: #CE9178">&apos;Name&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">property:</span><span style="color: #CE9178">&apos;name&apos;</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">label:</span><span style="color: #CE9178">&apos;Hours&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">property:</span><span style="color: #CE9178">&apos;hours&apos;</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">label:</span><span style="color: #CE9178">&apos;Date&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">property:</span><span style="color: #CE9178">&apos;startDate&apos;</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">label:</span><span style="color: #CE9178">&apos;Department&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">property:</span><span style="color: #CE9178">&apos;department&apos;</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">        &#93; </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableColumn</span><span style="color: #D4D4D4">[];</span></span></code></pre></div>



<p class="wp-block-paragraph">Now, we can attach our function to the tablecell by adding the onClick prop to the <strong>TableCell</strong>, and pass in the corresponding property for the column being mapped. We can also apply our CSS stylings to the table cells at this point. Here I use Material UI’s styling solution, but the key point when doing this is setting the CSS property <em>cursor: ‘pointer’</em>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly> &lt;TableHead>
            &lt;TableRow>
                {tableColumn.map((column, index) => {
                    return(
                        &lt;TableCell key={index} 
                            className={headerCell}
                            onClick={()=>sortBy(column.property)}
                        >
                            {column.label}
                        &lt;/TableCell>
                    )
                })}
            &lt;/TableRow>
        &lt;/TableHead></textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"> &lt;</span><span style="color: #4EC9B0">TableHead</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;</span><span style="color: #4EC9B0">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                {</span><span style="color: #9CDCFE">tableColumn</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">map</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">                        &lt;</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">key</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">} </span></span>
<span class="line"><span style="color: #D4D4D4">                            </span><span style="color: #9CDCFE">className</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">headerCell</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">                            </span><span style="color: #9CDCFE">onClick</span><span style="color: #D4D4D4">={()=&gt;</span><span style="color: #DCDCAA">sortBy</span><span style="color: #D4D4D4">(column.property)}</span></span>
<span class="line"><span style="color: #D4D4D4">                        &gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                            {</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">label</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">                        &lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                    )</span></span>
<span class="line"><span style="color: #D4D4D4">                })}</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;/</span><span style="color: #9CDCFE">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;/</span><span style="color: #9CDCFE">TableHead</span><span style="color: #D4D4D4">&gt;</span></span></code></pre></div>



<p class="wp-block-paragraph">Lastly, we’ll add an indicator arrow through conditional rendering to show the current sort direction. To do this, we have two conditionals to check what we render. The first is checking if there is an existing sorting configuration, and the second is checking if the sortType is ascending/descending. To make this easier, we can write a simple function that gets us the current sortType from the sorting configuration and returns an appropriate icon.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly> const getSortDirection = (property:keyof TableData) => {
        var config = sortConfig.find((sortConfig) => sortConfig.propertyName === property)
        if(config){
            if(config.sortType === SortingType.Descending){
                return &lt;ArrowDownwardIcon/>
            }
            else {
                return &lt;ArrowUpwardIcon/>
            }
        }
        return null;
    }</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">getSortDirection</span><span style="color: #D4D4D4"> = (</span><span style="color: #9CDCFE">property</span><span style="color: #D4D4D4">:</span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">find</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">property</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Descending</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> &lt;</span><span style="color: #4EC9B0">ArrowDownwardIcon</span><span style="color: #D4D4D4">/&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">            else {</span></span>
<span class="line"><span style="color: #D4D4D4">                return &lt;</span><span style="color: #4EC9B0">ArrowUpwardIcon</span><span style="color: #D4D4D4">/&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">        return null;</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span></code></pre></div>



<p class="wp-block-paragraph">Our <strong>SortableTableHeader </strong>code should now look like this, with the appropriate CSS stylings applied in place of <strong>headerCell </strong>and <strong>sortLabel</strong>, if you aren’t using Material-UI.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>export const SortableHeader = ({sortBy, sortConfig}:SortableHeaderProps) => {

    const {headerCell, sortLabel} = useStyles();

    const tableColumn = &#91;
        {label:'Name', property:'name'},
        {label:'Hours', property:'hours'},
        {label:'Date', property:'startDate'},
        {label:'Department', property:'department'}
        &#93; as TableColumn[];

    const getSortDirection = (property:keyof TableData) => {
        var config = sortConfig.find((sortConfig) => sortConfig.propertyName === property)
        return config ?
            config.sortType === SortingType.Descending ?
                &lt;ArrowDownwardIcon/>
                :&lt;ArrowUpwardIcon/>
            :null
    }

    return (
        &lt;TableHead>
            &lt;TableRow>
                {tableColumn.map((column, index) => {
                    return(
                        &lt;TableCell key={index} 
                            className={headerCell}
                            onClick={()=>sortBy(column.property)}
                        >
                            &lt;span className={sortLabel}>
                                {column.label}
                                {getSortDirection(column.property)}
                            &lt;/span>
                        &lt;/TableCell>
                    )
                })}
            &lt;/TableRow>
        &lt;/TableHead>
    );
};</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">SortableHeader</span><span style="color: #D4D4D4"> = ({</span><span style="color: #9CDCFE">sortBy</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">}:</span><span style="color: #4EC9B0">SortableHeaderProps</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> {</span><span style="color: #4FC1FF">headerCell</span><span style="color: #D4D4D4">, </span><span style="color: #4FC1FF">sortLabel</span><span style="color: #D4D4D4">} = </span><span style="color: #DCDCAA">useStyles</span><span style="color: #D4D4D4">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">tableColumn</span><span style="color: #D4D4D4"> = &#91;</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">label:</span><span style="color: #CE9178">&apos;Name&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">property:</span><span style="color: #CE9178">&apos;name&apos;</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">label:</span><span style="color: #CE9178">&apos;Hours&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">property:</span><span style="color: #CE9178">&apos;hours&apos;</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">label:</span><span style="color: #CE9178">&apos;Date&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">property:</span><span style="color: #CE9178">&apos;startDate&apos;</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span><span style="color: #9CDCFE">label:</span><span style="color: #CE9178">&apos;Department&apos;</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">property:</span><span style="color: #CE9178">&apos;department&apos;</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">        &#93; </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableColumn</span><span style="color: #D4D4D4">[];</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">getSortDirection</span><span style="color: #D4D4D4"> = (</span><span style="color: #9CDCFE">property</span><span style="color: #D4D4D4">:</span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">find</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">property</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4"> ?</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Descending</span><span style="color: #D4D4D4"> ?</span></span>
<span class="line"><span style="color: #D4D4D4">                &lt;</span><span style="color: #9CDCFE">ArrowDownwardIcon</span><span style="color: #D4D4D4">/&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                :&lt;</span><span style="color: #4EC9B0">ArrowUpwardIcon</span><span style="color: #D4D4D4">/&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            :</span><span style="color: #569CD6">null</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;</span><span style="color: #4EC9B0">TableHead</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;</span><span style="color: #4EC9B0">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                {</span><span style="color: #9CDCFE">tableColumn</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">map</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">) =&gt; {</span></span>
<span class="line"><span style="color: #D4D4D4">                    </span><span style="color: #DCDCAA">return</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">                        &lt;</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">key</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">} </span></span>
<span class="line"><span style="color: #D4D4D4">                            </span><span style="color: #9CDCFE">className</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">headerCell</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">                            </span><span style="color: #9CDCFE">onClick</span><span style="color: #D4D4D4">={()=&gt;</span><span style="color: #DCDCAA">sortBy</span><span style="color: #D4D4D4">(column.property)}</span></span>
<span class="line"><span style="color: #D4D4D4">                        &gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;</span><span style="color: #9CDCFE">span</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">className</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">sortLabel</span><span style="color: #D4D4D4">}&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                                {</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">label</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">                                {</span><span style="color: #9CDCFE">getSortDirection</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">property</span><span style="color: #D4D4D4">)}</span></span>
<span class="line"><span style="color: #D4D4D4">                            &lt;/</span><span style="color: #9CDCFE">span</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                        &lt;/</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                    )</span></span>
<span class="line"><span style="color: #D4D4D4">                })}</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;/</span><span style="color: #9CDCFE">TableRow</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;/</span><span style="color: #9CDCFE">TableHead</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    );</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span></code></pre></div>



<p class="wp-block-paragraph">If everything went correctly, you should now see table headers with arrows showing the corresponding sort directions on them.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/2-react-tables-good.png" alt=""/></figure>



<p class="wp-block-paragraph"><p style="font-size:110%"><strong>Step 5: Applying the Sort Configuration with LINQ</strong></p></p>



<p class="wp-block-paragraph">The last step is to finally apply the sorting in order.</p>



<p class="wp-block-paragraph">We’ll be defining our variable, ‘sortedRows’ by a useMemo function, with a dependency on sortConfig and dataList, so that we re-render our sortedRows whenever our sort configuration changes, or whenever our data list changes.</p>



<p class="wp-block-paragraph">Next, we can turn our standard list of items into a LINQ list by putting it in a LINQ.from call. Now, in order to leverage LINQ&#8217;s sorting functionality, our list of values has to be an <strong>IOrderedEnumerable</strong> object. We can get this by applying a basic orderBy function to our LINQ and passing it a lambda that just returns one, which basically says sort this by the key ‘nothing’, and return ‘1’ in all cases to avoid doing any comparison. This returns us our list in an unmodified order, but as an IOrderedEnumerable type.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly> //Set up default ordering
        let sorted = linq.from(dataList).orderBy(() => 1);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"> </span><span style="color: #6A9955">//Set up default ordering</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">let</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">linq</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">from</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">orderBy</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">The reason why we want to do this is so we can apply multiple sorts on top of this which is possible by using the thenBy and <strong>thenyByDescending </strong>functions from LINQ and using those requires an IOrderedEnumerable. Now that that’s established, we can loop through each of the sorting configurations in order and check which sort type we’re applying.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>let sorted = linq.from(dataList).orderBy(() => 1);
        //Loop through the queue
        sortConfig.forEach((sortConfig) => {
            if (sortConfig.sortType === SortingType.Ascending) {
                //Ascending sorting
            } else {
                //Descending sorting
            }
        });</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">let</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">linq</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">from</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">orderBy</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Loop through the queue</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">forEach</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Ascending</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">//Ascending sorting</span></span>
<span class="line"><span style="color: #D4D4D4">            } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">//Descending sorting</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">        });</span></span></code></pre></div>



<p class="wp-block-paragraph">Our last step in sorting is to apply the thenBy conditional on the corresponding property, and LINQ will handle the complicated sorting for us, including comparing integers, strings, and dates. You can read more on LINQ functions, and even pass in your own comparable which is useful for handling sorting between more complex types, but in the case of this guide, we’ll just stick to basic sorting since we’re handling primitive types. If it’s descending, we can use <strong>thenByDescending</strong> which makes things easier.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly> if (sortConfig.sortType === SortingType.Ascending) {
                sorted = sorted
                    .thenBy((dataRow) => dataRow&#91;sortConfig.propertyName&#93;);
            } else {
                sorted = sorted
                    .thenByDescending((dataRow) => dataRow&#91;sortConfig.propertyName&#93;);
            }</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"> </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Ascending</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">sorted</span></span>
<span class="line"><span style="color: #D4D4D4">                    .</span><span style="color: #DCDCAA">thenBy</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">&#93;);</span></span>
<span class="line"><span style="color: #D4D4D4">            } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">sorted</span></span>
<span class="line"><span style="color: #D4D4D4">                    .</span><span style="color: #DCDCAA">thenByDescending</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">&#93;);</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span></code></pre></div>



<p class="wp-block-paragraph">In the code above, you see that the arguments for the lambda are an element of the <strong>sortedList. </strong>In this case, I named it <strong>dataRow</strong> because each item in the sorted is a LINQ&nbsp;from our dataList so we can think of it as one row. It then selects a corresponding key via the propertyName of our sortConfig, which as you recall is either “name”, “hours”, “startDate’, and “department”. In short, this is us targeting that specific column.</p>



<p class="wp-block-paragraph">Now, if you have null data, Javascript will run into the null comparison issue, which will mess up the sorting. A quick workaround I do is to sort all the data that is null on the bottom, but prefacing this <strong>thenBy</strong> with another thenBy that basically checks if the property is null.</p>



<p class="wp-block-paragraph">Here we return -1 when the data is null which means the object is ‘less than’ an object which does have data, and is sorted lower on the list.</p>



<p class="wp-block-paragraph">The last thing we need to do is to turn our LINQ into an array by calling <strong>.toArray()</strong>, and returning that value so that our <strong>sortedRows</strong> has an array of a sorted <strong>dataList</strong>. Putting it all together, we have this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>const sortedRows = useMemo(() => {
        //Set up default ordering
        let sorted = linq.from(dataList).orderBy(() => 1);
        //Loop through the queue
        sortConfig.forEach((sortConfig) => {
            if (sortConfig.sortType === SortingType.Ascending) {
                sorted = sorted
                    .thenBy((dataRow) => (dataRow&#91;sortConfig.propertyName&#93; === null ? -1 : 1))
                    .thenBy((dataRow) => dataRow&#91;sortConfig.propertyName&#93;);
            } else {
                sorted = sorted
                    .thenByDescending((dataRow) =>
                    dataRow&#91;sortConfig.propertyName&#93; === null ? -1 : 1
                    )
                    .thenByDescending((dataRow) => dataRow&#91;sortConfig.propertyName&#93;);
            }
        });
        return sorted.toArray();
    }, &#91;sortConfig, dataList&#93;);</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">sortedRows</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Set up default ordering</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">let</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">linq</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">from</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">orderBy</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955">//Loop through the queue</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">forEach</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Ascending</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">sorted</span></span>
<span class="line"><span style="color: #D4D4D4">                    .</span><span style="color: #DCDCAA">thenBy</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">&#93; === </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4"> ? -</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> : </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">                    .</span><span style="color: #DCDCAA">thenBy</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">&#93;);</span></span>
<span class="line"><span style="color: #D4D4D4">            } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">sorted</span></span>
<span class="line"><span style="color: #D4D4D4">                    .</span><span style="color: #DCDCAA">thenByDescending</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                    </span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">&#93; === </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4"> ? -</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> : </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4">                    )</span></span>
<span class="line"><span style="color: #D4D4D4">                    .</span><span style="color: #DCDCAA">thenByDescending</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">dataRow</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">&#93;);</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">        });</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">toArray</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">    }, &#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">&#93;);</span></span></code></pre></div>



<p class="wp-block-paragraph">You should now have a functioning table with multiple sortable headers! A key thing to note is that you can pass a comparable to the thenBy function instead of just selecting by key. If for some reason things are not sorting as they should, that should be the first point of debugging.</p>



<h2 class="wp-block-heading" id="h-bonus-sorting-without-linq">Bonus: Sorting without LINQ</h2>



<p class="wp-block-paragraph">If you’ve made it this far, or just skipped ahead to this section, we’ll be going over the basics of sorting rows based on multiple headers by just using basic comparators.</p>



<p class="wp-block-paragraph">Comparators are just functions that take in two objects and return a number depending on how they relate to one another. A zero means they’re equal, positive numbers are greater, and negative numbers are less. Now let’s work on converting our sorting function to one that doesn’t use LINQ at all.</p>



<p class="wp-block-paragraph">Sorting multiple columns may seem complex, but in practice, it’s not really that difficult. Given a list of sorting configurations in the desired order, all you have to check is if the <strong>first comparator</strong> results in an equality, use the <strong>next comparator</strong> in order. If we have a list of {a ,1 }, {a , 2}, and {b, 1}. Sorting by the first column results in the equality of a’s. All we’d need to do is check our second column’s comparator to determine what order they should go in.</p>



<p class="wp-block-paragraph">In this guide, we’ve already implemented a function that can order our sort configurations for us. All we need to do is add a comparators to our SortConfiguration so we can keep track of which compare function we need to use.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>export interface SortingConfiguration{
    propertyName: keyof TableData,
    sortType: SortingType,
    compareFunction: TableDataComparable
}

export type TableDataComparable = ((a: TableData, b:TableData) => number);</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">interface</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SortingConfiguration</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">SortingType</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">compareFunction</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableDataComparable</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableDataComparable</span><span style="color: #D4D4D4"> = ((</span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">:</span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">number</span><span style="color: #D4D4D4">);</span></span></code></pre></div>



<p class="wp-block-paragraph">Next, we add that field to our sortBy function:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>const sortBy = useCallback(
        (propertyName: keyof TableData, compareFunction: TableDataComparable) => {
            let pendingChange = &#91;...sortConfig&#93;;
            const index = pendingChange.findIndex((config) => config.propertyName === propertyName)
            if(index > -1){
                //Save the sortType
                var currentSortType = pendingChange&#91;index&#93;.sortType;
                //Remove existing config
                pendingChange.splice(index, 1);
                //check if the sort type we saved is descending
                if (currentSortType === SortingType.Descending) {
                    pendingChange = &#91;
                        ...pendingChange,
                        { propertyName: propertyName, sortType: SortingType.Ascending , compareFunction: compareFunction},
                    &#93;;
                }
            } else {
                pendingChange = &#91;
                    ...pendingChange,
                    { propertyName: propertyName, sortType: SortingType.Descending, compareFunction: compareFunction },
                &#93;;
            }
            updateSortConfig(&#91;...pendingChange&#93;);
        },
        &#91;sortConfig&#93;
    )</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">sortBy</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useCallback</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">        (</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">compareFunction</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableDataComparable</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">let</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4"> = &#91;...</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">&#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">index</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">findIndex</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4"> &gt; -</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">//Save the sortType</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">currentSortType</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">&#93;.</span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">//Remove existing config</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">splice</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #6A9955">//check if the sort type we saved is descending</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">currentSortType</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Descending</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">                    </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4"> = &#91;</span></span>
<span class="line"><span style="color: #D4D4D4">                        ...</span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                        { </span><span style="color: #9CDCFE">propertyName:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sortType:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Ascending</span><span style="color: #D4D4D4"> , </span><span style="color: #9CDCFE">compareFunction:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">compareFunction</span><span style="color: #D4D4D4">},</span></span>
<span class="line"><span style="color: #D4D4D4">                    &#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">                }</span></span>
<span class="line"><span style="color: #D4D4D4">            } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4"> = &#91;</span></span>
<span class="line"><span style="color: #D4D4D4">                    ...</span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                    { </span><span style="color: #9CDCFE">propertyName:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">propertyName</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">sortType:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Descending</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">compareFunction:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">compareFunction</span><span style="color: #D4D4D4"> },</span></span>
<span class="line"><span style="color: #D4D4D4">                &#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #DCDCAA">updateSortConfig</span><span style="color: #D4D4D4">(&#91;...</span><span style="color: #9CDCFE">pendingChange</span><span style="color: #D4D4D4">&#93;);</span></span>
<span class="line"><span style="color: #D4D4D4">        },</span></span>
<span class="line"><span style="color: #D4D4D4">        &#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">    )</span></span></code></pre></div>



<p class="wp-block-paragraph">Next, we update our interfaces and define comparators for each of our table columns.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>interface SortableHeaderProps {
    sortBy: (string: keyof TableData, compareFunction: TableDataComparable) => void;
    sortConfig: SortingConfiguration[];
}
...
const CompareByEquality = (column: keyof TableData) => (a: TableData, b: TableData) => {
        if(a&#91;column&#93; === b&#91;column&#93;){
            return 0
        } else{
            if (a&#91;column&#93; > b&#91;column&#93;){
                return 1;
            }
            return -1;
        }
    }

    const tableColumn = [
        {   label: 'Name', 
            property: 'name', 
            compareFunction: 
            (a: TableData, b: TableData) => {
                 return a&#91;'name'&#93;.localeCompare(b&#91;'name'&#93; as string) 
            } 
        },
        {
            label: 'Hours', 
            property: 'hours',
            compareFunction: CompareByEquality('hours')
        },
        {   label: 'Date', 
            property: 'startDate', 
            compareFunction: CompareByEquality('startDate') 
        },
        {   label: 'Department',
            property: 'department', 
            compareFunction: CompareByEquality('department') }
    ] as TableColumn[];</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">interface</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SortableHeaderProps</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">sortBy</span><span style="color: #D4D4D4">: (</span><span style="color: #9CDCFE">string</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">compareFunction</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableDataComparable</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">SortingConfiguration</span><span style="color: #D4D4D4">[];</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">...</span></span>
<span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">CompareByEquality</span><span style="color: #D4D4D4"> = (</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">keyof</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">&#93; === </span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">&#93;){</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">        } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">&#93; &gt; </span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">&#91;</span><span style="color: #9CDCFE">column</span><span style="color: #D4D4D4">&#93;){</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> -</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">tableColumn</span><span style="color: #D4D4D4"> = [</span></span>
<span class="line"><span style="color: #D4D4D4">        {   </span><span style="color: #9CDCFE">label:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Name&apos;</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">property:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;name&apos;</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">compareFunction:</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">            (</span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">&#91;</span><span style="color: #CE9178">&apos;name&apos;</span><span style="color: #D4D4D4">&#93;.</span><span style="color: #DCDCAA">localeCompare</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">&#91;</span><span style="color: #CE9178">&apos;name&apos;</span><span style="color: #D4D4D4">&#93; </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">string</span><span style="color: #D4D4D4">) </span></span>
<span class="line"><span style="color: #D4D4D4">            } </span></span>
<span class="line"><span style="color: #D4D4D4">        },</span></span>
<span class="line"><span style="color: #D4D4D4">        {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">label:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Hours&apos;</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">property:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;hours&apos;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">compareFunction:</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">CompareByEquality</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;hours&apos;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">        },</span></span>
<span class="line"><span style="color: #D4D4D4">        {   </span><span style="color: #9CDCFE">label:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Date&apos;</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">property:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;startDate&apos;</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">compareFunction:</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">CompareByEquality</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;startDate&apos;</span><span style="color: #D4D4D4">) </span></span>
<span class="line"><span style="color: #D4D4D4">        },</span></span>
<span class="line"><span style="color: #D4D4D4">        {   </span><span style="color: #9CDCFE">label:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;Department&apos;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">property:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&apos;department&apos;</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">compareFunction:</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">CompareByEquality</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&apos;department&apos;</span><span style="color: #D4D4D4">) }</span></span>
<span class="line"><span style="color: #D4D4D4">    ] </span><span style="color: #C586C0">as</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">TableColumn</span><span style="color: #D4D4D4">[];</span></span></code></pre></div>



<p class="wp-block-paragraph">Here, I just use equality for returning the values, but for more complex objects, you can define your own comparator function. As for the name, I used string’s localCompare as an example of an in-line lambda comparator.</p>



<p class="wp-block-paragraph">After that, we just add the compareFunction into our onClick, so that our sortBy function has all the correct parameters.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;TableCell key={index}
    		className={headerCell}
   	 	onClick={() => sortBy(column.property, column.compareFunction)}
>
&lt;TableCell key={index}
    		className={headerCell}
   	 	onClick={() => sortBy(column.property, column.compareFunction)}
></textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">key</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">    		</span><span style="color: #9CDCFE">className</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">headerCell</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">   	 	</span><span style="color: #9CDCFE">onClick</span><span style="color: #D4D4D4">={() =&gt; </span><span style="color: #DCDCAA">sortBy</span><span style="color: #D4D4D4">(column.property, column.compareFunction)}</span></span>
<span class="line"><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;</span><span style="color: #9CDCFE">TableCell</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">key</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">    		</span><span style="color: #9CDCFE">className</span><span style="color: #D4D4D4">={</span><span style="color: #9CDCFE">headerCell</span><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4">   	 	</span><span style="color: #9CDCFE">onClick</span><span style="color: #D4D4D4">={() =&gt; </span><span style="color: #DCDCAA">sortBy</span><span style="color: #D4D4D4">(column.property, column.compareFunction)}</span></span>
<span class="line"><span style="color: #D4D4D4">&gt;</span></span></code></pre></div>



<p class="wp-block-paragraph">Lastly, we need to change our definition for sortedRows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TypeScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>const sortedRows = useMemo(() => {
        if(sortConfig.length === 0){
            return &#91;...dataList&#93;;
        }
        let sorted = &#91;...dataList&#93;.sort(
            (a: TableData, b:TableData) =>{
                 for(const config of sortConfig){
                    const result = (config.compareFunction(a,b))
                    if(result !== 0){
                        if(config.sortType === SortingType.Ascending){
                            return result;
                        }
                        else{
                            return -result;
                        }
                    }
                }
                return 0;
            }
        )
        return(sorted)
    }, &#91;sortConfig, dataList&#93;);</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">sortedRows</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">length</span><span style="color: #D4D4D4"> === </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> &#91;...</span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">&#93;;</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">let</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4"> = &#91;...</span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">&#93;.</span><span style="color: #DCDCAA">sort</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">            (</span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">:</span><span style="color: #4EC9B0">TableData</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">config</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">of</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">                    </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">result</span><span style="color: #D4D4D4"> = (</span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">compareFunction</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">,</span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">                    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">result</span><span style="color: #D4D4D4"> !== </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">                        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">config</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">sortType</span><span style="color: #D4D4D4"> === </span><span style="color: #9CDCFE">SortingType</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">Ascending</span><span style="color: #D4D4D4">){</span></span>
<span class="line"><span style="color: #D4D4D4">                            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">result</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">                        }</span></span>
<span class="line"><span style="color: #D4D4D4">                        </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">                            </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> -</span><span style="color: #9CDCFE">result</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">                        }</span></span>
<span class="line"><span style="color: #D4D4D4">                    }</span></span>
<span class="line"><span style="color: #D4D4D4">                }</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">        )</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">sorted</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">    }, &#91;</span><span style="color: #9CDCFE">sortConfig</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">dataList</span><span style="color: #D4D4D4">&#93;);</span></span></code></pre></div>



<p class="wp-block-paragraph">First, we check if there’s a sort configuration and if there isn’t we want to go back to our unsorted state by returning a copy of the data list.</p>



<p class="wp-block-paragraph">If there is a sort configuration, we make a copy of dataList using the spread operator and sort with a lambda function that goes over our loop of sortConfigs. It then tests each a, and b, TableData against the compareFunction in the sortConfig. If we have an equal match, we try to and apply the subsequent sort config until we have a result that isn’t 0. Next, we check if it’s ascending or descending, and so we flip the result to its opposite value with a negative sign. Lastly, we finish going through our sort configuration and find that all matches, then we know both rows are equal.</p>



<p class="wp-block-paragraph">That about does it for sorting multiple columns in React.</p>



<p class="wp-block-paragraph"><strong>Learn more about DMC&#8217;s <a href="https://static.dmcinfo.com/services/application-development">Application Development expertise</a>.</strong></p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://static.dmcinfo.com/blog/19887/sorting-multiple-columns-in-a-table-with-react/">Sorting Multiple Columns in a Table with React</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Creating a Virtual Machine from a Physical Computer</title>
		<link>https://static.dmcinfo.com/blog/19951/creating-a-virtual-machine-from-a-physical-computer/</link>
		
		<dc:creator><![CDATA[Will Todd]]></dc:creator>
		<pubDate>Thu, 07 May 2020 15:43:22 +0000</pubDate>
				<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[Virtual Machine]]></category>
		<category><![CDATA[VM]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/19951/creating-a-virtual-machine-from-a-physical-computer/</guid>

					<description><![CDATA[<p>Many people and/or companies have computers running that they would be very upset if it were to fail. There are tons of examples where the failure of hardware or loss of software install files can be devastating to recover a computer or bigger system it is connected to. Luckily there is a way to preserve [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/19951/creating-a-virtual-machine-from-a-physical-computer/">Creating a Virtual Machine from a Physical Computer</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Many people and/or companies have computers running that they would be very upset if it were to fail. There are tons of examples where the failure of hardware or loss of software install files can be devastating to recover a computer or bigger system it is connected to.</p>



<p class="wp-block-paragraph">Luckily there is a way to preserve a computer without having to keep the physical hardware in solid running condition forever. VMware offers a free tool called <strong>VMware vCenter Converter</strong> that allows the user to take a physical machine and create a virtual version of it while it is powered on and running!</p>



<h2 id="h-virtualize-a-physical-machine" class="wp-block-heading">Virtualize a Physical Machine</h2>



<p class="wp-block-paragraph">In VMware workstation you can find an option to virtualize a physical machine:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/1-virtualize-vm.png" alt="virtualizevm"/></figure>



<p class="wp-block-paragraph">This will prompt you to download the latest version of <strong>VMware vCenter Converter Standalone.</strong></p>



<p class="wp-block-paragraph"><strong></strong></p>



<p class="wp-block-paragraph">You can create a free account and download the software on <a href="https://www.vmware.com/" type="link" id="https://www.vmware.com/">VMware&#8217;s website</a>.</p>



<p class="wp-block-paragraph">You will have to create a FREE account to do this, accept the end-user license agreement, then the software download will begin.</p>



<p class="wp-block-paragraph">When the download is complete you should have a .exe file available in your downloads folder. Run this executable and the software install will begin. For this example, I have installed the standard installation of the software on the local machine. The software can then be run on the host machine from either the shortcut created on the desktop or through the newly added program path where it was installed.</p>



<p class="wp-block-paragraph">Once the application opens you will see a <strong>Convert Machine</strong> button near the top left corner, which will prompt with a wizard to start the conversion. You can also start this from <strong>File -&gt; New -&gt; Convert Machine</strong>, or simply pressing <strong>Ctrl+M</strong>.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/3-convert-machine.png" alt=""/></figure>



<p class="wp-block-paragraph">The first page in the wizard is where you pick the source computer. In this example, we want to use the host machine to clone so we leave the drop-down as local machine and select the radio button for <strong>‘Powered On’</strong>. Click Next.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/4-powered-on.png" alt=""/></figure>



<p class="wp-block-paragraph">The next screen is <strong>Destination System</strong>. Here you can select the <strong>Destination type</strong>, which affects the other options available. For a ‘VMware Workstation or other VMware virtual Machine’, you can select which software/version you will be using after the VM is created.</p>



<p class="wp-block-paragraph">The VM details allow you to change the computer name for the VM and the destination path for where the application will save the files. Depending on the size of the host being used, this could be quite large, so make sure you have a destination that has plenty of storage.</p>



<p class="wp-block-paragraph">For instance, my local machine has several virtual machines already saved on the hard drive which can take up a very significant amount of storage, so it is recommended to save files on external drives or networks then move them back to the VM later if needed using the shared folders options in VMware Workstation.</p>



<h2 id="h-configuring-the-vm" class="wp-block-heading">Configuring The VM</h2>



<p class="wp-block-paragraph">As a better example, I will go through the process using a bare-bones Windows machine that has very little stored on the hard drive.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/5-vm-workstation.png" alt=""/></figure>



<p class="wp-block-paragraph">You can see the destination was set to use a removable disk mounted on the F drive. The next page has several options the user can choose from. These options include the size of the virtual hard drive, memory allocated for the processor, number of cores for the CPU, etc.</p>



<p class="wp-block-paragraph">The size of the hard drive has multiple options: <strong>Maintain Size</strong> (keeps the full size of the physical hard drive), <strong>Min Size</strong> (uses the minimum amount possible), or <strong>type in size</strong> (any value above the Min Size requirement). Depending on how much you plan on adding to the VM after creation, select your size accordingly. Also, the size of the hard drive will affect the size of the VM file so make sure your destination storage device can handle this.</p>



<p class="wp-block-paragraph"><strong>Memory allocation</strong> and <strong>Number of processors</strong> can be adjusted in&nbsp;the VM settings later in VMware using the <strong>VM -&gt; Settings</strong>. Then, navigate to the hardware tab and select the Memory and Processors to change their values.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/6-vm-settings.png" alt=""/></figure>



<h2 id="h-adding-the-vmware-tools-option" class="wp-block-heading">Adding the VMware Tools Option</h2>



<p class="wp-block-paragraph">A useful tool that is recommended for install is <strong>VMware Tools</strong>. This install is great for using the auto fit and adjustment for the guest operating system so it will match the screen resolution to better fit the environment it is running in. The option to install VMware Tools on the VM can be found here:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/7-vmware-tools.png" alt=""/></figure>



<p class="wp-block-paragraph">Clicking to the next page will bring you to the summary. Here you can review all the options selected from the wizard and if anything looks wrong you can navigate back to change the options.</p>



<h2 id="h-creating-the-vm" class="wp-block-heading">Creating the VM</h2>



<p class="wp-block-paragraph">Clicking finish in the bottom right corner will start the conversion process. If you choose not to do this, you can install VMware tools later in VMware Workstation through the top menu bar <strong>VM -&gt; Install VMware Tools… selection</strong>.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/8-local-machine.png" alt=""/></figure>



<p class="wp-block-paragraph">Depending on the size and specs of the host computer, the conversion process can take a while. The conversion screen will give you estimated time and total percentage complete while it is running, so you will have good feedback on where it is at in the process.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/9-feedback-process.png" alt=""/></figure>



<p class="wp-block-paragraph">Once the process is complete. You will see the status change to <strong>‘Completed’</strong> and you now have the VM file that you can start in VMware.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/10-completed-vm.png" alt=""/></figure>



<h2 id="h-opening-the-vm" class="wp-block-heading">Opening the VM</h2>



<p class="wp-block-paragraph">In the destination folder selected in the Wizard, you will find the<strong> ‘.vmx’</strong> and <strong>‘.vdmk’</strong> files created from the converter application. The ‘.vmx’ file is what you select to power up the machine in the VMware workstation. In the picture below you can see the two files generated from the conversion process.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/11-vm-files.png" alt=""/></figure>



<p class="wp-block-paragraph">Before opening the VM, it is best practice to save a copy of the files on the host machine’s hard drive. A good idea is to make a <strong>Virtual PC folder on the C:\ drive</strong> to store all the VMs. As you can see below here is the location where this example VM will be stored.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/12-vm-file-location.png" alt=""/></figure>



<p class="wp-block-paragraph">In VMware Workstation, click the<strong> ‘Open a Virtual Machine’</strong> button, and navigate to the path where the VM is saved. Select the .vmx file and click <strong>‘Open’</strong>.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/13-vm-workstation.png" alt=""/></figure>



<p class="wp-block-paragraph">Now you can run the VM by opening the .vmx file in VMware, and if the VM is backed up it can live forever, even with a failure in the VM or the host computer. Make sure to save your VM in a safe place in case of something tragic happening!</p>



<p class="wp-block-paragraph">If you chose not to install VMware tools earlier, you can still install it using VMware Workstation. It will prompt on screen how to start the installation. It may require a manual start from the start menu.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/14-install-vmware-tools.png" alt=""/></figure>



<p class="wp-block-paragraph">Once the installation is complete the VM will need to restart. Now you can run the VM with auto size adjustment for the monitor connected to the host machine, plus more seamless transitions from VM to host windows if working with multiple monitors.</p>



<p class="wp-block-paragraph">With this short procedure, you can now enjoy the same machine running in a virtual environment!</p>



<p class="wp-block-paragraph"><a href="/contact">Contact DMC</a> with any questions and learn more about our <a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence">Manufacturing Automation services.</a>&nbsp;</p>
<p>The post <a href="https://static.dmcinfo.com/blog/19951/creating-a-virtual-machine-from-a-physical-computer/">Creating a Virtual Machine from a Physical Computer</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Getting Started with WinCC OA: Part 9 &#8211; Color Database and High Performance Best Practices</title>
		<link>https://static.dmcinfo.com/blog/20143/getting-started-with-wincc-oa-part-9-color-database-and-high-performance-best-practices/</link>
		
		<dc:creator><![CDATA[Nick Leisle]]></dc:creator>
		<pubDate>Fri, 06 Mar 2020 15:31:57 +0000</pubDate>
				<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[WinCC]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/20143/getting-started-with-wincc-oa-part-9-color-database-and-high-performance-best-practices/</guid>

					<description><![CDATA[<p>Welcome back to “Getting Started with WinCC OA”! If you aren’t familiar with the series’ previous topics, it’s recommended that you read the respective installments before proceeding: In Part 9 of “Getting Started with WinCC OA,” we’ll look at the Color Database and the implementation of color-based concepts presented in “The High Performance HMI Handbook” [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/20143/getting-started-with-wincc-oa-part-9-color-database-and-high-performance-best-practices/">Getting Started with WinCC OA: Part 9 &#8211; Color Database and High Performance Best Practices</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Welcome back to “Getting Started with WinCC OA”! If you aren’t familiar with the series’ previous topics, it’s recommended that you read the respective installments before proceeding:</p>



<ul class="wp-block-list">
<li><a href="/latest-thinking/blog/id/9870/getting-started-with-wincc-oa-part-1--creating-opening-a-project">Part 1: Creating and Opening a Project</a></li>



<li><a href="/latest-thinking/blog/id/9871/getting-started-with-wincc-oa-part-2--folder-structure-gedi-layout">Part 2: Folder Structure and Gedi Layout</a></li>



<li><a href="/latest-thinking/blog/id/9884/getting-started-with-wincc-oa-part-3--panels-the-basics">Part 3: Panels | The Basics</a></li>



<li><a href="/latest-thinking/blog/id/9893/getting-started-with-wincc-oa-part-4--panel-scripting-environments-and-quicktest">Part 4: Panel Scripting Environments and QuickTest</a></li>



<li><a href="/latest-thinking/blog/id/9906/getting-started-with-wincc-oa-part-5--scripting-syntax">Part 5: Scripting Syntax</a></li>



<li><a href="/latest-thinking/blog/id/9921/getting-started-with-wincc-oa-part-6--para-overview-and-datapoint-creation">Part 6: Para Overview and Datapoint Creation</a></li>



<li><a href="/latest-thinking/blog/id/9944/getting-started-with-wincc-oa-part-7--interacting-with-datapoints-via-scripting">Part 7: Interacting with Datapoints via Scripting</a></li>



<li><a href="https://static.dmcinfo.com/blog/20658/getting-started-with-wincc-oa-part-8-libraries/">Part 8: Libraries</a></li>
</ul>



<p class="wp-block-paragraph">In Part 9 of “Getting Started with WinCC OA,” we’ll look at the Color Database and the implementation of color-based concepts presented in “The High Performance HMI Handbook” by Bill R. Hollifield, Dana Oliver, Eddie Habibi, and Ian Nimmo.</p>



<h2 id="h-what-is-a-color-database" class="wp-block-heading">What is a Color Database?</h2>



<p class="wp-block-paragraph">The color database is where project colors are defined and stored. Project colors can be separated into and organized via different databases. Recall the OA folder structure and panel view tree outlined in <a href="/latest-thinking/blog/id/9871/getting-started-with-wincc-oa-part-2--folder-structure-gedi-layout">Part 2: Folder Structure and Gedi Layout</a>,&nbsp;color databases are stored within the ColorDB folder and can be accessed in Gedi via the Color Database element in the Project View tree.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/1-colordb.png" alt="color database"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/2-projectview-color.png" alt="color project view"/></figure>



<h2 id="h-creating-a-database" class="wp-block-heading">Creating a Database</h2>



<p class="wp-block-paragraph">To create a color database, simply right click the <strong>“Color Database”</strong> Project View tree element and select<strong> “Add New Color Database.”</strong> For our example, we’ll call this color database <strong>“Project Base.”</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/3-addnew.png" alt="create database"/></figure>



<h2 id="h-creating-a-color-database-color" class="wp-block-heading">Creating a Color Database Color</h2>



<p class="wp-block-paragraph">To add a color, right-click the color database that will house said color and select <strong>“Add New Color.”</strong> For our example, we’ll create the following colors within the “Project Base” database:</p>


<table style="width:100%; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; margin-bottom:40px;">
<tbody>
<tr style="text-align:center;">
<th style="border-collapse:collapse; border-style:solid; border-width:medium; border-spacing: 20px; border:1px solid black; height:100px; font-size:24px; border-right-style:solid; border-right-width:medium; border-left-style:solid; border-left-width:medium;"><strong>Name</strong></th>
<th style="border-collapse:collapse; border-style:solid; border-width:medium; border-spacing: 20px; border:1px solid black; height:100px; font-size:24px; border-right-style:solid; border-right-width:medium; border-left-style:solid; border-left-width:medium;"><strong>RGB</strong></th>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">Base_Red</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">166, 20, 3</td>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">Base_Blue</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">46, 56, 255</td>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">Base_Green</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">82, 197, 33</td>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">Base_DarkGrey</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">93, 93, 93</td>
</tr>
<tr>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">Base_White</td>
<td style="text-align:center; vertical-align:middle; border-collapse:collapse; border:1px solid black; border-style:solid; border-width:medium; font-size:24px;">247, 247, 247</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">If following along, feel free to adjust the colors’ RGB values as you see fit.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/4-addnewcolor.png" alt="add new color"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/5-colorselector.png" alt="select color"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/6-projectbase.png" alt="project base"/></figure>



<h2 id="h-creating-color-database-aliases" class="wp-block-heading">Creating Color Database Aliases</h2>



<p class="wp-block-paragraph">Programmers use aliases to identify color database colors under different names. Using aliases helps maintain color consistency throughout a project, makes code more readable, and prevents cluttering within color databases</p>



<p class="wp-block-paragraph">DMC’s best practices involve creating a color database of base colors to serve as a project color foundation. All other color databases will consist of aliases of these base colors.</p>



<p class="wp-block-paragraph">Before creating an alias, we’ll first create a new color database called <strong>“Device Status.”</strong> Within the “Devices Status” color database, we’ll create an alias called <em><strong>DeviceStatus_Estopped</strong></em>&nbsp;and assign it <strong><em>Base_Red</em>.</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/7-alias.png" alt="color alias"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/8-9newcolor.png" alt="new color saving"/></figure>



<p class="wp-block-paragraph">In addition, we’ll create<strong> <em>DeviceStatus_Stopped</em></strong>&nbsp;as<strong> <em>Base_Blue</em></strong>&nbsp;and <strong><em>DeviceStatus_Running</em>&nbsp;</strong>as <strong><em>Base_Green</em>.</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/10-namedcolors.png" alt="nsamed colors"/></figure>



<p class="wp-block-paragraph">Now that we’ve created new device status colors let’s apply them to our example from Parts 7 and 8. In <a href="/latest-thinking/blog/id/9944/getting-started-with-wincc-oa-part-7--interacting-with-datapoints-via-scripting">Part 7 &#8211; Interacting with Datapoints via Scripting</a>, we created a simple rectangle (represents a motor device) and assigned it a “Red” background-color within its project properties. Now that we have designated status colors, let’s give it a <em><strong>DeviceStatus_Stopped</strong></em>&nbsp;default color.</p>



<p class="wp-block-paragraph">In reality, this color will only be visible while editing in Gedi as the example code automatically assigns the rectangle a new color in runtime. Regardless, we’ll still apply the color.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/11-backgroundcolor.png" alt="backgruond colors"/></figure>



<p class="wp-block-paragraph">Recall that in <a href="/latest-thinking/blog/id/10014/getting-started-with-wincc-oa-part-8--libraries">Part 08 – Libraries</a>, we created a control file that defined a variety of color constants. Instead of defining the constants as primary OA colors “red,” “blue,” and “green,” we can re-define them as our newly created aliases in the “ColorConst.ctl” file.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/12-conststring.png" alt="code"/></figure>



<h2 id="h-the-high-performance-hmi" class="wp-block-heading">The High Performance HMI</h2>



<p class="wp-block-paragraph">The High Performance HMI is a concept presented in “The High Performance HMI Handbook” by Bill R. Hollifield, Dana Oliver, Eddie Habibi, and Ian Nimmo. The book focuses on developing human-machine interfaces in a way that maximizes operators’ situational awareness and increases HMI functionality and efficiency. Though topics in the book stretch from ideal screen topology to control room distractions, I found it worthwhile to highlight some basic ideas on color selection in this blog post.</p>



<p class="wp-block-paragraph">According to “The High Performance HMI Handbook”</p>



<ul class="wp-block-list">
<li>Color should be used to draw the operators’ attention and highlight abnormal situations</li>



<li>Color blindness is a prevalent condition that must be taken into account when selecting colors. For those that are color blind, color combinations such as green + red and blue + purple are often hard to differentiate.</li>
</ul>



<p class="wp-block-paragraph">For example, consider the following color schemes in device objects in DMC’s WinCC OA Open Library:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/13-hmilevels.png" alt="hmi levels"/></figure>



<p class="wp-block-paragraph">The standard color scheme is generally what those unfamiliar with High Performance HMI concepts might consider ideal and preferable. However, note what the same layout looks like when passed through a color-blind simulator application:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/14-colorbline.png" alt=""/></figure>



<p class="wp-block-paragraph">Note that the standard<strong> “Active” </strong>and <strong>“Fault” </strong>states are nearly indistinguishable to those with deuteranopia (green-blindness). All High Performance HMI colors are easily differentiable. Also, the High Performance scheme uses color to draw an operator’s attention to a faulted state and leaves normal operation in greyscale colors.</p>



<h2 id="h-creating-alternative-color-schemes" class="wp-block-heading">Creating Alternative Color Schemes</h2>



<p class="wp-block-paragraph">Color schemes allow users to overwrite color definitions and allows for color transitioning. This can be helpful when shifting between “day” and “night” modes, for example. For the purposes of this tutorial, we’ll create a High Performance color scheme that that overwrites our <em><strong>DeviceStatus_Stopped</strong></em> and <strong><em>DeviceStatus_Forward</em></strong> aliases with alternative high performance colors.</p>



<p class="wp-block-paragraph">To create a <strong>color scheme</strong>, right-click the Color Databases element and select<strong> “Add New Color Scheme Folder.”</strong> We’ll name this color scheme, “High Performance Colors.”</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/15-add-new-scheme-folder.png" alt="new folder"/></figure>



<p class="wp-block-paragraph">Within a color scheme folder, you can define colors and their respective color databases. Within the “High Performance Colors” color scheme folder, we’ll create a color database titled <strong>“DeviceStatus”</strong> and define aliases <em><strong>DeviceStatus_Stopped</strong></em> as <em><strong>Base_DarkGrey</strong></em> and <strong><em>DeviceStatus_Forward</em> </strong>as<strong> <em>Base_White</em>.</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/16-highperformance-colors.png" alt="high performance colors"/></figure>



<p class="wp-block-paragraph">Everything under the Color Databases element and not in a color scheme folder is considered the default color/database. <strong>When a color scheme is “Active,” any conflicting colors within the color scheme folder will overwrite its default color counterpart.</strong></p>



<p class="wp-block-paragraph">Since DeviceStatus_Running and DeviceStatus_Stopped are defined within the High Performance Colors, the&nbsp;<strong><em>Base_White</em></strong> and <strong><em>Base_DarkGrey</em></strong> will represent those color aliases respectively when the “High Performance Colors” are active. <strong><em>Base_Red</em></strong> will continue to represent the <strong><em>Device_Status_Estopped</em></strong> since there is no definition within the “High Performance Colors” scheme.</p>



<h2 id="h-activating-color-schemes" class="wp-block-heading">Activating Color Schemes</h2>



<p class="wp-block-paragraph">There are several ways of activating color schemes within a project:</p>



<p class="wp-block-paragraph"><u><strong>Activate in Gedi</strong></u><br>
To activate a color scheme in Gedi, simply right click its respective folder and select “<strong>Activate Color Scheme.</strong>” To activate the default scheme, simply perform the same action but right-clicking on a default color. This is a good way of testing different color schemes during development.</p>



<p class="wp-block-paragraph"><u><strong>Activate via Scripting</strong></u><br><br>Color schemes can be altered during runtime by using the function</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Plaintext</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>colorSetActiveScheme(&lt;Color Scheme>)Show more lines</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">colorSetActiveScheme(&lt;Color Scheme&gt;)Show more lines</span></span></code></pre></div>



<p class="wp-block-paragraph">Where &lt;Color Scheme&gt; is a string of the folder name. To activate the default color scheme, simply use empty quotes. Enabling color schemes via scripting is ideal for switching between color schemes during runtime.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/17-active-color-scheme.png" alt=""/></figure>



<p class="wp-block-paragraph"><u><strong>Activate via Config File</strong></u><br><br>The config file will be covered more in-depth in subsequent “Getting Started with WinCC OA” installments. However, it’s important to note that a color scheme can be activated by implementing the following line within the [ui] section of the config file:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Plaintext</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>activeColorScheme = &lt;Color Scheme></textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">activeColorScheme = &lt;Color Scheme&gt;</span></span></code></pre></div>



<p class="wp-block-paragraph">Where &lt;Color Scheme&gt; is a string of the folder name. Like activating color schemes via scripting, the default color scheme is represented with empty quotes. With that said, it is not necessary to activate the default color scheme via the config file since, as the default, it’s already active upon startup.</p>



<p class="wp-block-paragraph">Activating color schemes via the config file is ideal if a project will use only one non-default color scheme.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/18-colorconfig.png" alt="color configurations"/></figure>



<h2 id="h-example-project-colors" class="wp-block-heading">Example Project Colors</h2>



<p class="wp-block-paragraph">Going back to the example project, we can run a quick test of our panel to view our new default colors. Since we’re working primarily in Gedi, we can activate the High Performance color scheme by right-clicking the “High Performance Colors” folder and activating the color scheme. Here’s how our rectangle’s color has changed over time:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/19-all-colors.png" alt="OA blue green and red"/></figure>



<p class="wp-block-paragraph"><strong>_dpdoesnotexist</strong></p>



<p class="wp-block-paragraph">WinCC OA comes with an array of accessible and usable colors that can be found within the base OA project. While most colors aren’t important enough to know, the “_dpdoesnotexist” color bears heavy significance in the development and debugging. In default OA objects (and ideally any other user-generated content like DMC’s WinCC OA Open Library), the “_dpdoesnotexist” color will display if the object’s user-specified datapoint or datapoint element does not exist within the project.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/20-DP-DNE.png" alt=""/></figure>



<p class="wp-block-paragraph"><br>
<span style="font-size:20px;"><span style="margin-left: 150px;">Native OA Object in GEDI</span><span style="margin-left: 90px;">Native OA Object with Invalid DPE in QuickTest</span></span></p>


<div class="clear:both">&nbsp;</div>


<p class="wp-block-paragraph">Now that we’ve covered colors and color databases, let’s jump back to panel development. In the next edition of “Getting Started with WinCC OA,” we’ll cover panel nesting and passing parameters from panel to reference panel using $-parameters.</p>



<p class="wp-block-paragraph"><strong>Topics to look forward to in this series:&nbsp;</strong></p>



<ul class="wp-block-list">
<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10138/getting-started-with-wincc-oa-part-10--panel-nesting-and-parameters">Part 10: Panels | Panel Nesting and $-Parameters</a></li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10184/getting-started-with-wincc-oa-part-11--panels-child-panels-popups">Part 11:&nbsp;Panels | Child Panels (Popups)</a></li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10313/getting-started-with-wincc-oa-part-12--modules-and-embedded-modules">Part 12: Modules &amp; Embedded Modules</a></li>
</ul>



<p class="wp-block-paragraph"><a href="https://static.dmcinfo.com/contact">Contact</a>&nbsp;DMC to get started on your next WinCC project and learn more about our&nbsp;<a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/siemens-simatic-wincc-programming">Siemens SIMATIC WinCC Programming</a>&nbsp;as well as our&nbsp;<a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/wincc-open-architecture-development">WinCC Open Architecture Development.</a></p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://static.dmcinfo.com/blog/20143/getting-started-with-wincc-oa-part-9-color-database-and-high-performance-best-practices/">Getting Started with WinCC OA: Part 9 &#8211; Color Database and High Performance Best Practices</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Digitally Signing a LabVIEW Installer</title>
		<link>https://static.dmcinfo.com/blog/20606/digitally-signing-a-labview-installer/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Mon, 04 Nov 2019 12:52:07 +0000</pubDate>
				<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<category><![CDATA[Digital Signatures]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[Security]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/20606/digitally-signing-a-labview-installer/</guid>

					<description><![CDATA[<p>A lot of work goes into creating a polished, custom application. If you’re like me, it may have never occurred to you that after all of your hard work, there still lies one hurdle: Windows Security. So how do you convince everyone else that your shiny new application isn’t actually malware? The key to this [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/20606/digitally-signing-a-labview-installer/">Digitally Signing a LabVIEW Installer</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">A lot of work goes into creating a polished, custom application. If you’re like me, it may have never occurred to you that after all of your hard work, there still lies one hurdle: <strong>Windows Security</strong>. So how do you convince everyone else that your shiny new application isn’t actually malware?</p>



<p class="wp-block-paragraph">The key to this is <strong>digital signatures</strong>. A digital signature essentially lets the user know who the developer is, but for this information to be trustworthy, it has to come from a certificate authority, such as Digicert. A certificate authority sells code signing certificates and performs identity verification before sending them out, providing 3rd party proof that you are who you are claiming to be.</p>



<p class="wp-block-paragraph">It is possible to digitally sign an application without purchasing a certificate from an authority. Though, since this signature has not been verified, it does not increase the validity of your application.</p>



<p class="wp-block-paragraph">In this post, I will go over the process of applying a digital signature to a <a href="/services/test-and-measurement-automation/labview-programming"><strong>LabVIEW application</strong>.</a></p>



<h2 id="h-step-1-purchase-a-signing-certificate" class="wp-block-heading">Step 1: Purchase a Signing Certificate</h2>



<p class="wp-block-paragraph">The first step is to purchase a signing certificate from a certificate authority. When you do, you will usually have some options. Code signing certificates can come in two formats: Extended Validation (EV) and normal.</p>



<p class="wp-block-paragraph">An EV certificate is more expensive and has a more extensive verification process, but this option comes with instant verification. The non-EV certificate does not have instant verification. So, an application signed in this manner will still have to gain a positive reputation before it passes Microsoft’s Smart Screen filters. The reputation will grow based on the number of installations of the application across the world.</p>



<p class="wp-block-paragraph">When purchasing the code signing certificate, you will likely be asked to select a Platform. We want to choose <strong><em>Microsoft Authenticode</em></strong> because that’s what LabVIEW executables use.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/select-platform.png" alt="selecting platform"/></figure>



<p class="wp-block-paragraph">This guide follows the non-EV certificate. If you purchase an EV certificate, you are mailed a USB that contains the key and further instructions.</p>



<p class="wp-block-paragraph">See here for <a href="https://www.digicert.com/code-signing/purchase-code-signing-certificate.htm" type="link" id="https://www.digicert.com/code-signing/purchase-code-signing-certificate.htm">more information</a> on this step.</p>



<h2 id="h-step-2-install-the-certificate" class="wp-block-heading">Step 2: Install the Certificate</h2>



<p class="wp-block-paragraph">Once your certificate is verified, you will receive an email with a link for installing your certificate. Install your certificate in the Personal Certificate store of the browser that you open this link in. The guides from my Certificate Authority used Internet Explorer, so I followed their example.</p>



<p class="wp-block-paragraph">Installing your certificate is a straightforward process. Here&#8217;s some <a href="https://www.digicert.com/code-signing/installing-code-signing-certificate.htm" type="link" id="https://www.digicert.com/code-signing/installing-code-signing-certificate.htm">more information</a>.</p>



<h2 id="h-step-3-extracting-the-certificate" class="wp-block-heading">Step 3: Extracting the Certificate</h2>



<p class="wp-block-paragraph">Now that you have installed the Certificate to your build machine, you must extract it to a format that LabVIEW supports. There are several different formats available; National Instruments supports the PFX format for signing LabVIEW executables, so this guide will assume you’re using that format.</p>



<p class="wp-block-paragraph">Follow <a href="https://www.digicert.com/code-signing/exporting-code-signing-certificate.htm" type="link" id="https://www.digicert.com/code-signing/exporting-code-signing-certificate.htm">this tutorial</a> to extract your certificate in the proper format. Be sure to name the certificate as something relevant to your company or application and save it to a location that is easy to find.</p>



<h2 id="h-step-4-apply-the-certificate-to-the-application" class="wp-block-heading">Step 4: Apply the Certificate to the Application</h2>



<p class="wp-block-paragraph">Now, we can apply the signature to our LabVIEW application. In the Properties for the Build Specification that you are trying to sign, navigate to the <strong><em>Windows Security</em></strong> category and check the box for <strong><em>Apply digital signature</em></strong>. You should now be able to find your digital signature in the <strong><em>Personal store certificates</em></strong> dropdown.</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Next, we need to provide a timestamp URL. The timestamp URL is the URL of the timestamp server from the certificate authority that you worked with. This URL allows the signed software to get the current date associated with it when it is downloaded. This is important to ensure that the digital signature is still valid at the time that the user is installing it. In our example, the timestamp URL was timestamp.digicert.com</p>



<p class="wp-block-paragraph">Be sure to sign both your executable and your installer, or any other build specification that you are distributing. Once we complete this step, we can check the properties of our new application and see the signature applied to it.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/timestamp-url.png" alt="timestamp url"/></figure>



<p class="wp-block-paragraph">And we’re done! The application will now gain a reputation with each install and will pass Microsoft Smart Screen soon enough.</p>



<p class="wp-block-paragraph">Learn more about DMC&#8217;s <a href="/services/test-and-measurement-automation/labview-programming">LabVIEW programming</a> expertise and <a href="/contact">contact us</a> with any project inquiries!</p>
<p>The post <a href="https://static.dmcinfo.com/blog/20606/digitally-signing-a-labview-installer/">Digitally Signing a LabVIEW Installer</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Getting Started with WinCC OA: Part 8 &#8211; Libraries</title>
		<link>https://static.dmcinfo.com/blog/20658/getting-started-with-wincc-oa-part-8-libraries/</link>
		
		<dc:creator><![CDATA[Nick Leisle]]></dc:creator>
		<pubDate>Wed, 23 Oct 2019 11:47:40 +0000</pubDate>
				<category><![CDATA[HMI and SCADA]]></category>
		<category><![CDATA[Manufacturing Automation & Intelligence]]></category>
		<category><![CDATA[Siemens PLC]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[WinCC]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/20658/getting-started-with-wincc-oa-part-8-libraries/</guid>

					<description><![CDATA[<p>Welcome back to “Getting Started with WinCC OA”! If you aren’t familiar with the series’ previous topics, I recommend that you read the respective installments before proceeding: Now that we have a basic understanding of scripting and how to interact with datapoints, we’re ready to move beyond panel scripting environments and create globally accessible code. [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/20658/getting-started-with-wincc-oa-part-8-libraries/">Getting Started with WinCC OA: Part 8 &#8211; Libraries</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Welcome back to “Getting Started with WinCC OA”! If you aren’t familiar with the series’ previous topics, I recommend that you read the respective installments before proceeding:</p>



<ul class="wp-block-list">
<li><a href="/latest-thinking/blog/id/9870/getting-started-with-wincc-oa-part-1--creating-opening-a-project">Part 1: Creating and Opening a Project</a></li>



<li><a href="/latest-thinking/blog/id/9871/getting-started-with-wincc-oa-part-2--folder-structure-gedi-layout">Part 2: Folder Structure and Gedi Layout</a></li>



<li><a href="/latest-thinking/blog/id/9884/getting-started-with-wincc-oa-part-3--panels-the-basics">Part 3: Panels | The Basics</a></li>



<li><a href="/latest-thinking/blog/id/9893/getting-started-with-wincc-oa-part-4--panel-scripting-environments-and-quicktest">Part 4: Panel Scripting Environments and QuickTest</a></li>



<li><a href="/latest-thinking/blog/id/9906/getting-started-with-wincc-oa-part-5--scripting-syntax">Part 5: Scripting Syntax</a></li>



<li><a href="/latest-thinking/blog/id/9921/getting-started-with-wincc-oa-part-6--para-overview-and-datapoint-creation">Part 6: Para Overview and Datapoint Creation</a></li>



<li><a href="/latest-thinking/blog/id/9944/getting-started-with-wincc-oa-part-7--interacting-with-datapoints-via-scripting">Part 7: Interacting with Datapoints via Scripting</a></li>
</ul>



<p class="wp-block-paragraph">Now that we have a basic understanding of scripting and how to interact with datapoints, we’re ready to move beyond panel scripting environments and create globally accessible code. In Part 8 of “Getting Started with WinCC OA,” we’ll explore how we can use libraries to create globally accessible functions, enumerations, constants, etc.</p>



<h2 class="wp-block-heading" id="h-what-are-libraries">What are Libraries?</h2>



<p class="wp-block-paragraph">Control libraries are files that hold code that may be accessed by other scripts within a project. Simply put, they hold globally usable code. One may ask, “Why would we want to use libraries?”</p>



<p class="wp-block-paragraph">Libraries prevent developers from having to rewrite or copy/paste existing code, allow changes to be made quickly and efficiently, and ensure consistency within a project. Let’s jump back quickly to the example used in “Part 7: Interacting with Datapoints via Scripting.” Say we used the same enumeration “StatusType” in several panels in addition to the one we created.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/enum-status-type.png" alt="status type"/></figure>



<p class="wp-block-paragraph">Without libraries, we’d need to copy and paste this enumeration in all of our panels’ ScopeLibs for further use. If we wanted to alter the enumeration to:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/enum-alteration.png" alt="altering enumination"/></figure>



<p class="wp-block-paragraph">We’d need to remember every instance of where this function was used, go back in the code, and modify StatusType appropriately. When the number of places we use StatusType increases, the more re-work would be needed to make the change.</p>



<h2 class="wp-block-heading" id="h-how-are-libraries-made">How are Libraries Made?</h2>



<p class="wp-block-paragraph">To create a control library, simply right click “Libraries” in the project view tree and select “Add New CTRL Library.”</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/add-new-lib.png" alt="add new library"/></figure>



<p class="wp-block-paragraph">Anything created in the resulting .ctl file can be appropriately referenced throughout the program. To continue from Part 7&#8217;s example, we’ll generate two .ctl files: one for a global<strong> StatusType</strong> and another for <strong>device colors.</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ctl-files.png" alt="ctl files"/></figure>



<p class="wp-block-paragraph"><strong>StatusType.ctl should contain:</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/statustype-ctl.png" alt="status type stl"/></figure>



<p class="wp-block-paragraph"><strong>ColorConst.ctl should have:</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/color-ctl.png" alt="color const ctl"/></figure>



<p class="wp-block-paragraph">None of these libraries do anything, however, if they’re not implemented within a program.</p>



<h2 class="wp-block-heading" id="h-how-is-library-content-implemented">How is Library Content Implemented?</h2>



<p class="wp-block-paragraph">Libraries are not initially accessible from a program’s script. The control library file must first be loaded into a project for it to be usable. To do so, you must implement the following line:</p>



<pre class="wp-block-code"><code>
	#uses &lt;.ctl file&gt;
</code></pre>



<p class="wp-block-paragraph">Once a control file is specified, a script may use any and all items within said .ctl file. To implement our control libraries within our example, we’ll modify our ScopeLib’s code as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">Python</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#uses "StatusType"
#uses "ColorConst"

//=============================== Panel initialization =========================================
initializePanel()
{
  //Whenever rSpeed or rMaxSpeed changes, call the function "onSpeedChange"
  dpConnect("onSpeedChange", "myMotor.rSpeed", "myMotor.rMaxSpeed");

  //Whenever iStatus changes, call the function "onStatusChange"
  dpConnect("onStatusChange", "myMotor.iStatus");
}


//=============================== Text Field Command =========================================
//Textbox is selected and user keys "Enter"
void textboxCmd()
{
  //Assign the textbox's text value to rMaxSpeed
  dpSet("myMotor.rMaxSpeed", maxSpeedTextbox.text);
}


//=============================== On Speed / Max Speed Value Change =================================
void onSpeedChange(string speedDp, float speedValue, string maxSpeedDp, float maxSpeedValue)
{
  //Define the variable whose value will be assigned to iStatus
  int iStatusValue;

  //Determine what value to assign iStatusValue (and subsequently "myMotor.iStatus")
  switch (speedValue)
  {
    //If "myMotor.rSpeed" is 0, set iStatusValue to 0
    case 0:
      iStatusValue = (int)StatusType::Stopped;
      break;

    //Otherwise, if "myMotor.rSpeed" > "myMotor.rMaxSpeed", set iStatusValue to Estop status int
    //           if not, set iStatusValue to Forward status int
    default:
      iStatusValue = (speedValue >= maxSpeedValue) ? (int)StatusType::Estop : (int)StatusType::Forward;
      break;
  }

  //Assign iStatusValue's value to "myMotor.iStatus"
  dpSet("myMotor.iStatus", iStatusValue);

  //Set the maxSpeedTextbox and speedTextbox's test to their respective values
  //NOTE: dpValToString ensures the units we assigned earlier in the series are displayed.
  //      Simply using &lt;Textbox>.text = &lt;speedValue> will work, but will not display appropriate units
  maxSpeedTextbox.text = dpValToString("myMotor.rMaxSpeed", maxSpeedValue, true);
  speedTextbox.text = dpValToString("myMotor.rSpeed", speedValue, true);
}

//=============================== On Status Change =========================================
void onStatusChange(string statusDp, int statusValue)
{
  //Define the variable whose value will be assigned to the rectangle's color property
  string rectangleColor;

  //Determine color to assign to rectangle based off iStatus
  if (statusValue == (int)StatusType::Stopped)
  {
    rectangleColor = STOPPED_COLOR;
  }

  if (statusValue == (int)StatusType::Estop)
  {
    rectangleColor = ESTOPPED_COLOR;
  }

  if (statusValue == (int)StatusType::Forward)
  {
    rectangleColor = FORWARD_COLOR;
  }

  //Assign selected color to rectangle
  setValue("rectangle", "backCol", rectangleColor);
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#uses &quot;StatusType&quot;</span></span>
<span class="line"><span style="color: #6A9955">#uses &quot;ColorConst&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">//=============================== Panel initialization =========================================</span></span>
<span class="line"><span style="color: #D4D4D4">initializePanel()</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  //Whenever rSpeed </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> rMaxSpeed changes, call the function </span><span style="color: #CE9178">&quot;onSpeedChange&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  dpConnect(</span><span style="color: #CE9178">&quot;onSpeedChange&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;myMotor.rSpeed&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;myMotor.rMaxSpeed&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  //Whenever iStatus changes, call the function </span><span style="color: #CE9178">&quot;onStatusChange&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  dpConnect(</span><span style="color: #CE9178">&quot;onStatusChange&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;myMotor.iStatus&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">//=============================== Text Field Command =========================================</span></span>
<span class="line"><span style="color: #D4D4D4">//Textbox </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> selected </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> user keys </span><span style="color: #CE9178">&quot;Enter&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">void textboxCmd()</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  //Assign the textbox</span><span style="color: #CE9178">&apos;s text value to rMaxSpeed</span></span>
<span class="line"><span style="color: #D4D4D4">  dpSet(</span><span style="color: #CE9178">&quot;myMotor.rMaxSpeed&quot;</span><span style="color: #D4D4D4">, maxSpeedTextbox.text);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">//=============================== On Speed / Max Speed Value Change =================================</span></span>
<span class="line"><span style="color: #D4D4D4">void onSpeedChange(string speedDp, </span><span style="color: #4EC9B0">float</span><span style="color: #D4D4D4"> speedValue, string maxSpeedDp, </span><span style="color: #4EC9B0">float</span><span style="color: #D4D4D4"> maxSpeedValue)</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  //Define the variable whose value will be assigned to iStatus</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4"> iStatusValue;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  //Determine what value to assign iStatusValue (</span><span style="color: #C586C0">and</span><span style="color: #D4D4D4"> subsequently </span><span style="color: #CE9178">&quot;myMotor.iStatus&quot;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">  switch (speedValue)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    //If </span><span style="color: #CE9178">&quot;myMotor.rSpeed&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">set</span><span style="color: #D4D4D4"> iStatusValue to </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">    case </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      iStatusValue = (</span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">)StatusType::Stopped;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">break</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    //Otherwise, </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;myMotor.rSpeed&quot;</span><span style="color: #D4D4D4"> &gt; </span><span style="color: #CE9178">&quot;myMotor.rMaxSpeed&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">set</span><span style="color: #D4D4D4"> iStatusValue to Estop status </span><span style="color: #4EC9B0">int</span></span>
<span class="line"><span style="color: #D4D4D4">    //           </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">set</span><span style="color: #D4D4D4"> iStatusValue to Forward status </span><span style="color: #4EC9B0">int</span></span>
<span class="line"><span style="color: #D4D4D4">    default:</span></span>
<span class="line"><span style="color: #D4D4D4">      iStatusValue = (speedValue &gt;= maxSpeedValue) </span><span style="color: #F44747">?</span><span style="color: #D4D4D4"> (</span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">)StatusType::Estop : (</span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">)StatusType::Forward;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">break</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  //Assign iStatusValue</span><span style="color: #CE9178">&apos;s value to &quot;myMotor.iStatus&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  dpSet(</span><span style="color: #CE9178">&quot;myMotor.iStatus&quot;</span><span style="color: #D4D4D4">, iStatusValue);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  //Set the maxSpeedTextbox </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> speedTextbox</span><span style="color: #CE9178">&apos;s test to their respective values</span></span>
<span class="line"><span style="color: #D4D4D4">  //NOTE: dpValToString ensures the units we assigned earlier </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> the series are displayed.</span></span>
<span class="line"><span style="color: #D4D4D4">  //      Simply using &lt;Textbox&gt;.text = &lt;speedValue&gt; will work, but will </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> display appropriate units</span></span>
<span class="line"><span style="color: #D4D4D4">  maxSpeedTextbox.text = dpValToString(</span><span style="color: #CE9178">&quot;myMotor.rMaxSpeed&quot;</span><span style="color: #D4D4D4">, maxSpeedValue, true);</span></span>
<span class="line"><span style="color: #D4D4D4">  speedTextbox.text = dpValToString(</span><span style="color: #CE9178">&quot;myMotor.rSpeed&quot;</span><span style="color: #D4D4D4">, speedValue, true);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">//=============================== On Status Change =========================================</span></span>
<span class="line"><span style="color: #D4D4D4">void onStatusChange(string statusDp, </span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4"> statusValue)</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  //Define the variable whose value will be assigned to the rectangle</span><span style="color: #CE9178">&apos;s color property</span></span>
<span class="line"><span style="color: #D4D4D4">  string rectangleColor;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  //Determine color to assign to rectangle based off iStatus</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (statusValue == (</span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">)StatusType::Stopped)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    rectangleColor = STOPPED_COLOR;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (statusValue == (</span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">)StatusType::Estop)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    rectangleColor = ESTOPPED_COLOR;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (statusValue == (</span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4">)StatusType::Forward)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    rectangleColor = FORWARD_COLOR;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  //Assign selected color to rectangle</span></span>
<span class="line"><span style="color: #D4D4D4">  setValue(</span><span style="color: #CE9178">&quot;rectangle&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;backCol&quot;</span><span style="color: #D4D4D4">, rectangleColor);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Note that:</strong></p>



<ul class="wp-block-list">
<li>I added the #uses prompts</li>



<li>I removed StatusType enum definition from ScopeLib (since it’s applied via library)</li>



<li>I added color constants (also applied via library)</li>
</ul>



<p class="wp-block-paragraph">With the color constants and StatusType enum defined in libraries, other panels and scripts may use them at will.</p>



<p class="wp-block-paragraph">Now that we have a solid understanding of how to make and implement control libraries, we’ll continue in our OA exploration by investigating color databases and learning how we can use them to create and use custom colors.</p>



<p class="wp-block-paragraph"><strong>Topics to look forward to in this series:&nbsp;</strong></p>



<ul class="wp-block-list">
<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10093/getting-started-with-wincc-oa-part-9--color-database-and-high-performance-best-practices">Part 9: Color Database &amp; High-Performance Best Practices</a></li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10138/getting-started-with-wincc-oa-part-10--panel-nesting-and-parameters">Part 10: Panels | Panel Nesting and $-Parameters</a></li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10184/getting-started-with-wincc-oa-part-11--panels-child-panels-popups">Part 11:&nbsp;Panels | Child Panels (Popups)</a></li>



<li><a href="https://static.dmcinfo.com/latest-thinking/blog/id/10313/getting-started-with-wincc-oa-part-12--modules-and-embedded-modules">Part 12: Modules &amp; Embedded Modules</a></li>
</ul>



<p class="wp-block-paragraph"><a href="https://static.dmcinfo.com/contact">Contact</a>&nbsp;DMC to get started on your next WinCC project and learn more about our&nbsp;<a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/siemens-simatic-wincc-programming">Siemens SIMATIC WinCC Programming</a>&nbsp;as well as our&nbsp;<a href="https://static.dmcinfo.com/services/manufacturing-automation-and-intelligence/hmi-and-scada-programming/wincc-open-architecture-development">WinCC Open Architecture Development.</a></p>
<p>The post <a href="https://static.dmcinfo.com/blog/20658/getting-started-with-wincc-oa-part-8-libraries/">Getting Started with WinCC OA: Part 8 &#8211; Libraries</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Trying Out ARM Mbed OS’s New Support for USB Device with Some Retro Hardware</title>
		<link>https://static.dmcinfo.com/blog/21018/trying-out-arm-mbed-oss-new-support-for-usb-device-with-some-retro-hardware/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Fri, 30 Aug 2019 09:24:58 +0000</pubDate>
				<category><![CDATA[Circuit Design]]></category>
		<category><![CDATA[Embedded Development & Programming]]></category>
		<category><![CDATA[How To]]></category>
		<category><![CDATA[Microcontroller Programming]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/21018/trying-out-arm-mbed-oss-new-support-for-usb-device-with-some-retro-hardware/</guid>

					<description><![CDATA[<p>Many products feature USB to facilitate communication between various devices, to transfer files easily, support hardware peripherals or add other features. While working on embedded systems, we have developed a variety of devices that utilize USB in these ways. The ease of implementation of USB largely depends on the hardware and software infrastructure that the [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/21018/trying-out-arm-mbed-oss-new-support-for-usb-device-with-some-retro-hardware/">Trying Out ARM Mbed OS’s New Support for USB Device with Some Retro Hardware</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Many products feature USB to facilitate communication between various devices, to transfer files easily, support hardware peripherals or add other features. While working on embedded systems, we have developed a variety of devices that utilize USB in these ways.</p>



<p class="wp-block-paragraph">The ease of implementation of USB largely depends on the hardware and software infrastructure that the microcontroller manufacturer provides. As of release 5.12.0, ARM Mbed OS began supporting USB device for several targets. This provides a nice layer of abstraction between the various manufacturers’ USB implementations and the USB class code. There are a variety of USB classes that are supported by default: USB MSD, USB HID, and USB Audio.</p>



<p class="wp-block-paragraph">In this blog, I’m going to try out this new USB device support and create a USB Mouse out of an old joystick.</p>



<h2 class="wp-block-heading" id="h-setting-up-the-project">Setting up the Project</h2>



<p class="wp-block-paragraph">I want to test out the USB HID class which will allow the device to interface with the PC as a USB mouse. I am going to start by creating a <strong>basic ARM Mbed OS</strong> project. If you have never done that before, take a look at <a href="/latest-thinking/blog/id/9536/nucleo-uart-tutorial-mbed-style">this guide.</a></p>



<p class="wp-block-paragraph">For this project, I am using a <strong>NUCLEO_F429ZI</strong> development board which is one of the supported targets for using mbed’s USB device. I set the target in my project by using the command <strong>“mbed target NUCLEO_F429ZI”.</strong> Make sure that your compiler is also set correctly according to the compiler that you have installed.</p>



<p class="wp-block-paragraph">For the test, I am going to copy-and-paste the example main from the file mbed/usb/device/USBHID/USBMouse.h.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C++</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "mbed.h"
#include "USBMouse.h" 

USBMouse mouse;

int main(void)
{
  while (1)
  {
      mouse.move(20, 0);
      wait(0.5);
  }
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">#include</span><span style="color: #569CD6"> </span><span style="color: #CE9178">&quot;mbed.h&quot;</span></span>
<span class="line"><span style="color: #C586C0">#include</span><span style="color: #569CD6"> </span><span style="color: #CE9178">&quot;USBMouse.h&quot;</span><span style="color: #569CD6"> </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">USBMouse mouse;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">int</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">main</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">void</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">mouse</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">move</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">wait</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">0.5</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Try and compile the project by running<strong> “mbed compile.”</strong> If you successfully build this project, then you are ready for the next steps. If not, make sure the target you are using is supported by ARM Mbed OS’s new USB device.</p>



<p class="wp-block-paragraph">Note, not all of the targets with hardware USB support Mbed’s USB device abstraction! Also, make sure you have the latest version of ARM Mbed OS in your project.</p>



<h2 class="wp-block-heading" id="h-running-a-quick-test">Running a Quick Test</h2>



<p class="wp-block-paragraph">Load the compiled program onto your target development kit. I am using a NUCLEO which has a STLINK on-board, so the development kit shows up as a drive when I plug it in. Just drag-and-drop the compiled<strong> “_your_project_name_.bin”</strong> onto the drive to program.</p>



<p class="wp-block-paragraph">To test the USB HID device, plug in the User USB port to the PC in addition to the debugging port which is needed for power. On your PC, you should see that a new USB device is detected. Once setup, your PC’s cursor should slowly move across your screen in 0.5-second steps.</p>



<p class="wp-block-paragraph">We are now ready to bring in the retro hardware to complete our USB device!</p>



<h2 class="wp-block-heading" id="h-adding-some-more-hardware">Adding Some More Hardware</h2>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/mbed-apple-joystick.jpg" alt="apple joystick"/></figure>



<p class="wp-block-paragraph">I have an old Apple Joystick IIe that I want&nbsp;to use&nbsp;as a USB joystick; so I need a custom USB adapter. The joystick electronics are very simple. There are two pushbuttons with pull-down resistors and two variable resistors, one for each axis, with one side tied to V+.</p>



<p class="wp-block-paragraph">To interface to the joystick, I connect 3.3 V on the NUCLEO to the V+, connect the GND on the NUCLEO to the joystick ground, connect the push-button outputs to digital inputs on the NUCLEO, and connect each axis output to a NUCLEO analog input with a 100 K ohm resistor to ground.</p>



<p class="wp-block-paragraph">I pulled all of this together quickly with a small prototyping board. The connector itself is just half of an RS232 serial cable.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/mbed-microcontroller.jpg" alt="microcontroler for joystick"/></figure>



<p class="wp-block-paragraph">Now, with a bit of firmware, we can get this retro joystick to operate with any modern OS.</p>



<p class="wp-block-paragraph">The code below is what I quickly put together to read the analog inputs of the joystick, read the button presses, and send corresponding USB Mouse events. When using one of the various supported USB device classes, Mbed can substantially decrease the required development time.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C++</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "mbed.h"
#include "USBMouse.h"

USBMouse mouse;

AnalogIn ainx(A0);
AnalogIn ainy(A1);

DigitalIn right_button(D6);
DigitalIn left_button(D7);

int main()
{
	float x = 0;
	float y = 0;

	bool prev_right_button = true;
	bool prev_left_button = true;
	
	const float mid_x = ainx.read() * 100.0;
	const float mid_y = ainy.read() * 100.0;
	
	while (1)
	{
		// Update the X, Y position
		y = ainy.read() * 100.0;
		x = ainx.read() * 100.0;

		float x_move = x - mid_x;
		float y_move = y - mid_y;

		if (x_move &lt; 0)
			x_move = 2 * x_move;
		if (y_move &lt; 0)
			y_move = 2 * y_move;

		if ((abs(x_move) > 4.0) || (abs(y_move) > 4.0))
		{
			mouse.move(-1 * x_move, -1 * y_move);
		}

		// Update the button presses
		bool current_right_button = right_button;
		bool current_left_button = left_button;

		if (prev_right_button != current_right_button)
		{
			if (current_right_button)
			{
				mouse.press(MOUSE_RIGHT);
			}
			else
			{
				mouse.release(MOUSE_RIGHT);
			}
			prev_right_button = current_right_button;
		}

		if (prev_left_button != current_left_button)
		{
			if (current_left_button)
			{
				mouse.press(MOUSE_LEFT);
			}
			else
			{
				mouse.release(MOUSE_LEFT);
			}
			prev_left_button = current_left_button;
		}

		wait_ms(10);
	}
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">#include</span><span style="color: #569CD6"> </span><span style="color: #CE9178">&quot;mbed.h&quot;</span></span>
<span class="line"><span style="color: #C586C0">#include</span><span style="color: #569CD6"> </span><span style="color: #CE9178">&quot;USBMouse.h&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">USBMouse mouse;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #4EC9B0">AnalogIn</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">ainx</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">A0</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #4EC9B0">AnalogIn</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">ainy</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">A1</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #4EC9B0">DigitalIn</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">right_button</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">D6</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #4EC9B0">DigitalIn</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">left_button</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">D7</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">int</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">main</span><span style="color: #D4D4D4">()</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #569CD6">float</span><span style="color: #D4D4D4"> x = </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #569CD6">float</span><span style="color: #D4D4D4"> y = </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #569CD6">bool</span><span style="color: #D4D4D4"> prev_right_button = </span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #569CD6">bool</span><span style="color: #D4D4D4"> prev_left_button = </span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">float</span><span style="color: #D4D4D4"> mid_x = </span><span style="color: #9CDCFE">ainx</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">read</span><span style="color: #D4D4D4">() * </span><span style="color: #B5CEA8">100.0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">float</span><span style="color: #D4D4D4"> mid_y = </span><span style="color: #9CDCFE">ainy</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">read</span><span style="color: #D4D4D4">() * </span><span style="color: #B5CEA8">100.0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">	</span></span>
<span class="line"><span style="color: #D4D4D4">	</span><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">	{</span></span>
<span class="line"><span style="color: #6A9955">		// Update the X, Y position</span></span>
<span class="line"><span style="color: #D4D4D4">		y = </span><span style="color: #9CDCFE">ainy</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">read</span><span style="color: #D4D4D4">() * </span><span style="color: #B5CEA8">100.0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">		x = </span><span style="color: #9CDCFE">ainx</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">read</span><span style="color: #D4D4D4">() * </span><span style="color: #B5CEA8">100.0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #569CD6">float</span><span style="color: #D4D4D4"> x_move = x - mid_x;</span></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #569CD6">float</span><span style="color: #D4D4D4"> y_move = y - mid_y;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (x_move &lt; </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">			x_move = </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4"> * x_move;</span></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (y_move &lt; </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">			y_move = </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4"> * y_move;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> ((</span><span style="color: #DCDCAA">abs</span><span style="color: #D4D4D4">(x_move) &gt; </span><span style="color: #B5CEA8">4.0</span><span style="color: #D4D4D4">) || (</span><span style="color: #DCDCAA">abs</span><span style="color: #D4D4D4">(y_move) &gt; </span><span style="color: #B5CEA8">4.0</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">		{</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #9CDCFE">mouse</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">move</span><span style="color: #D4D4D4">(-</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> * x_move, -</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> * y_move);</span></span>
<span class="line"><span style="color: #D4D4D4">		}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">		// Update the button presses</span></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #569CD6">bool</span><span style="color: #D4D4D4"> current_right_button = right_button;</span></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #569CD6">bool</span><span style="color: #D4D4D4"> current_left_button = left_button;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (prev_right_button != current_right_button)</span></span>
<span class="line"><span style="color: #D4D4D4">		{</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (current_right_button)</span></span>
<span class="line"><span style="color: #D4D4D4">			{</span></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #9CDCFE">mouse</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">press</span><span style="color: #D4D4D4">(MOUSE_RIGHT);</span></span>
<span class="line"><span style="color: #D4D4D4">			}</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">else</span></span>
<span class="line"><span style="color: #D4D4D4">			{</span></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #9CDCFE">mouse</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">release</span><span style="color: #D4D4D4">(MOUSE_RIGHT);</span></span>
<span class="line"><span style="color: #D4D4D4">			}</span></span>
<span class="line"><span style="color: #D4D4D4">			prev_right_button = current_right_button;</span></span>
<span class="line"><span style="color: #D4D4D4">		}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (prev_left_button != current_left_button)</span></span>
<span class="line"><span style="color: #D4D4D4">		{</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (current_left_button)</span></span>
<span class="line"><span style="color: #D4D4D4">			{</span></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #9CDCFE">mouse</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">press</span><span style="color: #D4D4D4">(MOUSE_LEFT);</span></span>
<span class="line"><span style="color: #D4D4D4">			}</span></span>
<span class="line"><span style="color: #D4D4D4">			</span><span style="color: #C586C0">else</span></span>
<span class="line"><span style="color: #D4D4D4">			{</span></span>
<span class="line"><span style="color: #D4D4D4">				</span><span style="color: #9CDCFE">mouse</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">release</span><span style="color: #D4D4D4">(MOUSE_LEFT);</span></span>
<span class="line"><span style="color: #D4D4D4">			}</span></span>
<span class="line"><span style="color: #D4D4D4">			prev_left_button = current_left_button;</span></span>
<span class="line"><span style="color: #D4D4D4">		}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">		</span><span style="color: #DCDCAA">wait_ms</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">	}</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<h2 class="wp-block-heading" id="h-testing-it-out">Testing it Out</h2>



<p class="wp-block-paragraph">Plug it into the PC and try out this retro joystick working with a modern machine!</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/mbed-joystick-and-controller.jpg" alt="joystick and controller"/></figure>



<p class="wp-block-paragraph">This is a great way to get a simple USB device going, but often a product will require more customization or non-supported USB class. If this is the case for you, <a href="/contact">come talk</a> to our <a href="/services/embedded-development-and-embedded-programming">embedded development and programming group</a> to see what solution makes sense for you!</p>
<p>The post <a href="https://static.dmcinfo.com/blog/21018/trying-out-arm-mbed-oss-new-support-for-usb-device-with-some-retro-hardware/">Trying Out ARM Mbed OS’s New Support for USB Device with Some Retro Hardware</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
