<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maik Michel</title>
    <description>The latest articles on DEV Community by Maik Michel (@maikmichel).</description>
    <link>https://dev.to/maikmichel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F310147%2F510230bf-3c00-443e-9854-22952f04825f.png</url>
      <title>DEV Community: Maik Michel</title>
      <link>https://dev.to/maikmichel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maikmichel"/>
    <language>en</language>
    <item>
      <title>React on RDS PagChange</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Sun, 19 Jan 2025 20:11:49 +0000</pubDate>
      <link>https://dev.to/maikmichel/react-on-rds-pagchange-2j2</link>
      <guid>https://dev.to/maikmichel/react-on-rds-pagchange-2j2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmicodify.de%2Fmedia%2Fposts%2F58%2FDALLE-2025-01-19-21.08.10-A-user-interface-of-a-modern-web-application-featuring-a-region-with-multiple-tabs-in-a-horizontal-layout.-Each-tab-is-clearly-labeled-such-as-Dashb.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmicodify.de%2Fmedia%2Fposts%2F58%2FDALLE-2025-01-19-21.08.10-A-user-interface-of-a-modern-web-application-featuring-a-region-with-multiple-tabs-in-a-horizontal-layout.-Each-tab-is-clearly-labeled-such-as-Dashb.webp" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the RDS and the region template tab container, APEX offers two options for grouping regions in such a way that they can be stacked on top of each other to save space. The RDS also has the option of showing all contained regions at once. I like to make use of both options. In the article (here) I had already described how to react to the activation of the individual tabs. This article will now focus on how to react to the change of tabs in an RDS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9izheogs8067t99t9ul8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9izheogs8067t99t9ul8.gif" alt="Recording default behavior of a RDS" width="1166" height="1154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlike with tab containers, the titles of the respective tabs are always displayed in an RDS, or are always hidden. Sounds strange. What I mean is, if I decide to show the special tab &lt;strong&gt;ShowAll&lt;/strong&gt; , I want the regions to show all their titles. But as soon as I click on a "normal" tab, I don't want the title to be displayed. Why? Well, from a UI point of view, the title of the region would now be displayed twice. Once on the tab and once as a region title. I think that's a bit of a duplicate and doesn't look good either.&lt;/p&gt;

&lt;p&gt;If you look at the DOM and define hard in APEX that a region header should be hidden, you will find the class &lt;code&gt;t-Region--hideHeader&lt;/code&gt; in the div of the region. This means that whenever this class is present, the title is not visible. In addition, we find the ID of the first list element in the DOM. This is &lt;code&gt;SHOW_ALL_tab&lt;/code&gt;. Each time this is activated, the element has the class &lt;code&gt;apex-rds-selected&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;We have to check whether the class &lt;code&gt;apex-rds-selected&lt;/code&gt; is present in the element &lt;code&gt;#SHOW_ALL_tab&lt;/code&gt; on the change event or not and use the class &lt;code&gt;t-Region--hideHeader&lt;/code&gt; to hide the titles of the regions. For this I use a bit of Knockout.js and jQuery&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// this will hold the model
var viewModel = {};

// check if given element is using the class given
function hasClass(elemID, className) {
  return (' ' + document.getElementById(elemID).className + ' ').indexOf(' ' + className+ ' ') &amp;gt; -1;
}

function initPage () {
  // whenever the RDS is clicked, we check whether the region title should be visible
  // this has the binding defined in the custom attributes: data-bind="class: hideRegionHeader”
  apex.jQuery('.apex-rds').data('onRegionChange', function(mode, activeTab) {
    viewModel.hideRegionHeader(hasClass("SHOW_ALL_tab", 'apex-rds-selected') ? "" : "t-Region--hideHeader");
  });

  // define the model
  viewModel = {
    hideRegionHeader: ko.observable(hasClass("SHOW_ALL_tab", 'apex-rds-selected') ? "" : "t-Region--hideHeader")
  }

  // activate binding with knockout
  ko.applyBindings(viewModel, document.querySelector("html"));
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define a model and create the hideRegionHeader property. This contains the class name &lt;code&gt;t-Region--hideHeader&lt;/code&gt; or nothing. The property itself should always be calculated when the TabPage is changed. For this we use the event &lt;code&gt;onRegionChange&lt;/code&gt; and bind it via JQuery. Whenever the event is triggered, the function hasClass is used to check whether the class is contained in the specified selector and thus the value of the property is recalculated using knockoutjs.   &lt;/p&gt;

&lt;p&gt;To make this working, you have to reference knockoutjs &lt;code&gt;#JET_BASE_DIRECTORY#js/libs/knockout/knockout-3.5.1.js&lt;/code&gt; and call then initPage method on PageLoad.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwocwkj64tyqzlxmqryd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwocwkj64tyqzlxmqryd4.png" alt="Screenshot of page properties showing JavaScript" width="713" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We bind the property itself to all regions that are displayed by the RDS. &lt;code&gt;data-bind="class: hideRegionHeader"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdc818vyd8r2bqrhfiwc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdc818vyd8r2bqrhfiwc.png" alt="Screenhot showing custom attributes data binding" width="716" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcl33xgsn0aa59fe6oa3p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcl33xgsn0aa59fe6oa3p.gif" alt="Screenrecording of a customized RDS" width="1166" height="1154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As usual, you can find a demo here: &lt;a href="https://apex.oracle.com/pls/apex/r/die21/demos/rdspage" rel="noopener noreferrer"&gt;https://apex.oracle.com/pls/apex/r/die21/demos/rdspage&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>apex</category>
    </item>
    <item>
      <title>New Plugin - Run Accessibility Tests - Streamline Accessibility Checks in APEX </title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Wed, 20 Nov 2024 17:07:36 +0000</pubDate>
      <link>https://dev.to/maikmichel/new-plugin-run-accessibility-tests-streamline-accessibility-checks-in-apex-7fd</link>
      <guid>https://dev.to/maikmichel/new-plugin-run-accessibility-tests-streamline-accessibility-checks-in-apex-7fd</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstjw4jzzadpqlgltasen.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstjw4jzzadpqlgltasen.jpg" alt="Glass showing brailtext" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am thrilled to introduce my very first APEX plugin! The inspiration for this idea came to me shortly before the last APEX Connect, and it has been a source of excitement and motivation ever since. This plugin allows you to evaluate your pages or entire applications for accessibility, an essential consideration for fostering an inclusive user experience. It leverages the powerful open-source library &lt;strong&gt;&lt;a href="https://github.com/dequelabs/axe-core" rel="noopener noreferrer"&gt;axe-core&lt;/a&gt;&lt;/strong&gt; from &lt;a href="https://www.deque.com" rel="noopener noreferrer"&gt;Deque&lt;/a&gt;, a tool that Deque itself uses in its comprehensive accessibility solutions.  &lt;/p&gt;

&lt;p&gt;The plugin is designed as a dynamic action, offering flexible integration into your applications. You can add it to specific pages or, for maximum utility, integrate it on page 0 to make it available across your entire application. For instance, you can activate the plugin via a key combination or by triggering a button, ensuring seamless usability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgrolnfee5q6g8foq762.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgrolnfee5q6g8foq762.png" alt="Properties of plugin the filter by tags and toggle storing" width="597" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, the plugin includes two configurable parameters:   &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run with Tags&lt;/strong&gt; : This attribute allows you to specify the types of tests to be executed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store Results&lt;/strong&gt; : This attribute serves as a toggle to decide whether the test results should be saved in a dedicated table.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The table is installed along with the accompanying app, &lt;strong&gt;A11Y-View&lt;/strong&gt; , where you can review the results in detail. A link in the console provides direct access to the test results, enhancing the plugin's ease of use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyq8y0kh4jxmj02sebye0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyq8y0kh4jxmj02sebye0.gif" alt="APEX App as companion to the plugin" width="1279" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I still have many more ideas for the app and the plugin. I will put a bit more energy into this over the next few weeks. I have already collected the following ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Floating button or message to open the app directly after a test&lt;/li&gt;
&lt;li&gt;Tracking of violations to exclude them for later tests if necessary, so that you are only informed of newer violations&lt;/li&gt;
&lt;li&gt;Improve the display&lt;/li&gt;
&lt;li&gt;If applicable, you can also integrate the playwright reporter
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can try out a demo at &lt;a href="https://apex.oracle.com/pls/apex/r/die21/tasks" rel="noopener noreferrer"&gt;https://apex.oracle.com/pls/apex/r/die21/tasks&lt;/a&gt;. And if you have any other ideas for improvement, let me know.&lt;/p&gt;

</description>
      <category>apex</category>
    </item>
    <item>
      <title>dbFlux now finally supports APEX plugins</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Sat, 29 Jun 2024 15:07:10 +0000</pubDate>
      <link>https://dev.to/maikmichel/dbflux-now-finally-supports-apex-plugins-3jk3</link>
      <guid>https://dev.to/maikmichel/dbflux-now-finally-supports-apex-plugins-3jk3</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86zyjg7qzo53offsw84c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86zyjg7qzo53offsw84c.jpg" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi guys, finally the time has come. I am happy to announce that I have released the latest version of &lt;strong&gt;dbFlux&lt;/strong&gt; this week. For those who don't know &lt;strong&gt;dbFlux&lt;/strong&gt; yet: &lt;strong&gt;dbFlux&lt;/strong&gt; is an extension for VSCode that supports you as a developer in your daily work within the development of Oracle database applications, and here mainly for APEX applications. &lt;strong&gt;dbFlux&lt;/strong&gt; compiles SQL, PL/SQL, JavaScript, CSS for you and uploads your binary files into your APEX application. It can export your applications, compile multiple schemas, run unit tests, export REST modules and so on... As you can see, &lt;strong&gt;dbFlux&lt;/strong&gt; is the Swiss army knife for APEX application development.&lt;/p&gt;

&lt;p&gt;But now to the actual topic. &lt;strong&gt;dbFlux&lt;/strong&gt; can now support you in the development of APEX plugins. After you have created the actual plugin within your application, you need to add it to your &lt;strong&gt;dbFlux&lt;/strong&gt; workspace. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1wccbfcl8asjmm13usg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1wccbfcl8asjmm13usg.png" alt="Screenshot showing the plugin editor inside APEX" width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;APEX Plugin&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By executing the command "dbFlux: Add APEX Plugin", &lt;strong&gt;dbFlux&lt;/strong&gt; prompts you under which application the plugin can be found. You then have to enter the internal name of the plugin as a static identifier. &lt;strong&gt;dbFlux&lt;/strong&gt; will now create empty folders for this plugin. These can be found for example under: &lt;code&gt;./plugin/f101/DE.DIE21.APEX.A11Y/src&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft096hdp4tzdwh888ie0f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft096hdp4tzdwh888ie0f.gif" alt="Recording of adding a APEX Plugin with dbFlux" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Add APEX Plugin&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The basic structure is now in place. Now we just need to export the plugin from APEX. We do this by executing the command: "dbFlux: Export APEX Plugin". Here we are asked again for the plugin to be exported. The whole process takes a short moment and then we find the corresponding SQL file in the &lt;code&gt;src&lt;/code&gt;directory of the plugin. This can now be deployed. Additionally you are able to create a &lt;em&gt;apexplugin.json&lt;/em&gt; file in order to publish it to apex.world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61swk2luziksha5o9f1t.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61swk2luziksha5o9f1t.gif" alt="Recording showing the export of a APEX Plugin" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Export Plugin&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The real advantage of using VSCode and &lt;strong&gt;dbFlux&lt;/strong&gt; is, of course, that you can use your favorite editor for development. And that includes, for example, editing the JavaScript files contained in such a plugin. With the command "dbFlux: Export Plugin Files" the static files of the plugin are downloaded and unpacked into the plugin directory. You can then simply edit the files accordingly and then compile them with &lt;code&gt;Ctrl+Alt+B&lt;/code&gt;, minify them and upload them to the actual plugin in the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9tvh5dvtydoykzch44v.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9tvh5dvtydoykzch44v.gif" alt="Recording of exporting a Static Plugin File and compile to upload it again" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Export Static Plugin File and compile to upload it&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now you can edit the JavaScript or CSS files of the plugin directly in VS Code. This saves a lot of time. No annoying navigation to the plugin, then to the files and then to editing... Simply change and press &lt;code&gt;Ctrl+Alt+B&lt;/code&gt; ⇒ Done.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>apex</category>
    </item>
    <item>
      <title>Optimal amount of columns in a card report</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Fri, 29 Mar 2024 13:41:01 +0000</pubDate>
      <link>https://dev.to/maikmichel/optimal-amount-of-columns-in-a-card-report-2643</link>
      <guid>https://dev.to/maikmichel/optimal-amount-of-columns-in-a-card-report-2643</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flec9oyci3yyex2v3e10k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flec9oyci3yyex2v3e10k.jpg" alt="3 sticky note on a table with a pen below" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I often create card reports in my projects. These reports are about showing the data on cards. Depending on the use case, it doesn't always make sense to show this data in tabular form. That's what cards are for. Especially in a mobile environment, i.e. on a mobile phone or tablet, it makes sense to display the cards.  &lt;/p&gt;

&lt;p&gt;However, it can sometimes happen that there are so few data records that the display on the monitor or tablet is not fully utilized. For example, if you define that there are always 4 columns in a card report, and you unfortunately only have two or three cards in the display. This makes the layout of the page asymmetrical and often looks strange.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vgomxm91b9h5rrnrs9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vgomxm91b9h5rrnrs9o.png" alt="Report showing 3 cards with example data. The space inside the report region is not used optimally." width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wouldn't it be practical to utilize the full width in such a case?  &lt;/p&gt;

&lt;p&gt;With a little CSS hack, this is easily possible. In the example above, the report is designed to have 4 columns.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzmdcjwu8hg9t0p8oqmi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzmdcjwu8hg9t0p8oqmi.png" alt="Screenshot of APEX template options, pointing the user to the property which will define the amount of columns in a card report." width="793" height="768"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This leads to the following CSS rule being used in the Universal Theme:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ajt6ns1neijleblqagp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ajt6ns1neijleblqagp.png" alt="Screenshot showing the CSS-Rule of a 4 column card report." width="800" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This rule must therefore be overwritten. For example, if you define the number of columns in such a way that it fits optimally. You can divide the number of records by 4, 3 or 2. If there is no remaining number, this would be the optimum number of columns. If there is a remainder, the number with the largest residual value could win.  &lt;/p&gt;

&lt;p&gt;If you have this value, you overwrite the above rule using &lt;code&gt;apex_css.add&lt;/code&gt; and placing this call as a page process to be executed before headers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apex_css.add (
    p_css =&amp;gt; '@media (min-width: 768px) {
                .t-Cards--4cols {
                  grid-template-columns: repeat('||:P10_MAX_CARDS_PER_ROW||', 1fr) !important; 
                }
              }',
    p_key =&amp;gt; 't-Cards--4cols' );
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then you can make sure that the rows of cards are optimally filled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F580wux6z5qrwifrb7o9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F580wux6z5qrwifrb7o9c.png" alt="Screenshot showing the same report as above, Now the 3 columns are using the whole space of the region." width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find a demo here: &lt;a href="https://apex.oracle.com/pls/apex/r/die21/demos/variable-cards" rel="noopener noreferrer"&gt;https://apex.oracle.com/pls/apex/r/die21/demos/variable-cards&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Featured Image by &lt;a href="https://unsplash.com/@kellysikkema?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Kelly Sikkema&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/blue-sharpie-beside-yellow-sticky-notes-BoAbPMRKLS0?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>apex</category>
    </item>
    <item>
      <title>Improve reusability in Oracle APEX and PL/SQL projects</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Sat, 30 Dec 2023 19:03:11 +0000</pubDate>
      <link>https://dev.to/maikmichel/improve-reusability-in-oracle-apex-and-plsql-projects-4e93</link>
      <guid>https://dev.to/maikmichel/improve-reusability-in-oracle-apex-and-plsql-projects-4e93</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4finnh08uipgem0mqtx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4finnh08uipgem0mqtx.jpg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In most of the projects I manage, I often have to reimplement a lot of functionalities from other projects. Especially in the consulting sector, I can't switch off my knowledge. And that's not something you want. Rather, all customers unconsciously benefit from each other. Solutions that I design for one customer may be used in a similar way by another customer.  &lt;/p&gt;

&lt;p&gt;Copying code snippets is also not really good or useful here. What we are missing in the database world around Oracle is a kind of package manager similar to NPM or Maven. And due to the dependency on the database and the associated restrictions, it is also difficult to implement. Let's imagine that the use of a package requires the existence of a certain table. A table that may not be there or has yet to be created. Surely such a package could be written completely with dynamic code. The disadvantage of such an implementation would be that any errors would only appear at runtime and not during compilation.  &lt;/p&gt;

&lt;p&gt;Personally, I find it better if such a package is directly invalid on the DB and does not throw a specific error at runtime, which I then have to painstakingly debug later.&lt;/p&gt;

&lt;h2&gt;
  
  
  So how can you provide a package, for example?
&lt;/h2&gt;

&lt;p&gt;The following approach has already proven itself in many projects. An atomic package is developed. This means that this package has no dependencies on objects that need to be brought along to install the package. Sometimes it happens that such a package has to make use of some configuration. I recommend a simple package header for this. This header only contains the variables that are customized by the developer who is responsible for the actual implementation in the target system. Here it makes sense to standardize the naming of such a Configuration-PackageHeader. I always use the suffix &lt;code&gt;_config&lt;/code&gt; for this.  &lt;/p&gt;

&lt;p&gt;For a package that contains, for example, unit tests for compliance with various standards in an APEX application, there could therefore be a generic package that looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create or replace package test_apex_application_quality is

...

end;

/

create or replace package body test_apex_application_quality is

...

  cursor cur_app_items is (select ...

                            from apex_application_items

                           where apex_application = test_apex_application_quality_config.C_APP_ID );

...

end;

/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just an example, but you can clearly see how the configuration package is used to restrict the items of the application to be tested.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create or replace package test_apex_application_quality_config is

  C_APP_ID constant number := 1000;

end;

/ 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that the 3 files could be delivered initially. If the test package is now extended to perform other tests on the application, it is sufficient to update the actual package.&lt;/p&gt;

&lt;p&gt;Cool, is there any way to update this?&lt;/p&gt;

&lt;h2&gt;
  
  
  Yes, you can. With dbFlux
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=MaikMichel.dbflow" rel="noopener noreferrer"&gt;dbFlux&lt;/a&gt;&lt;/strong&gt;is a VSCode extension and offers a command for exactly this purpose. Here it is called &lt;code&gt;Add FeatureSet as SubModule&lt;/code&gt;. Such a FeatureSet is available for exactly this scenario. Simply enter the GitURL that points to such a FeatureSet. &lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=MaikMichel.dbflow" rel="noopener noreferrer"&gt;dbFlux&lt;/a&gt;&lt;/strong&gt; will create / clone this repository as a Git-Submodule in the existing project folder. Such a FeatureSet must contain a &lt;em&gt;manifest.json&lt;/em&gt; file. This file contains the information required to copy the corresponding files of the FeatureSet into the current project.&lt;br&gt;&lt;br&gt;
The developer of the FeatureSet can provide the files with the flag &lt;code&gt;"initial": true&lt;/code&gt;. This is then only copied during initial creation and is no longer overwritten. In addition, the &lt;em&gt;manifest.json&lt;/em&gt; file contains the version number of the FeatureSet. If this changes, &lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=MaikMichel.dbflow" rel="noopener noreferrer"&gt;dbFlux&lt;/a&gt;&lt;/strong&gt;will ask whether these changes should be transferred to the current project. &lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=MaikMichel.dbflow" rel="noopener noreferrer"&gt;dbFlux&lt;/a&gt;&lt;/strong&gt;will not install anything on its own, but only copy the files. These can then be installed in the development database by the developer. And with the support of &lt;strong&gt;&lt;a href="https://github.com/MaikMichel/dbFlow" rel="noopener noreferrer"&gt;dbFlow&lt;/a&gt;&lt;/strong&gt;, those files will be shipped and install as usual with your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdrem9q9dj67dcjirulwl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdrem9q9dj67dcjirulwl.gif" alt="screen recording using dbFlux to add a reusable FeatureSet" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;screen recording using dbFlux to add a reusable FeatureSet&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>plsql</category>
      <category>apex</category>
    </item>
    <item>
      <title>Using Authenticator Based MFA in Oracle APEX #JoelKallmanDay</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Wed, 11 Oct 2023 10:58:56 +0000</pubDate>
      <link>https://dev.to/maikmichel/using-authenticator-based-mfa-in-oracle-apex-joelkallmanday-fpd</link>
      <guid>https://dev.to/maikmichel/using-authenticator-based-mfa-in-oracle-apex-joelkallmanday-fpd</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjryhikyd2zad2j2mlad.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjryhikyd2zad2j2mlad.jpg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many of you are certainly familiar with multifactor authentication, or MFA for short. With MFA, another factor is requested in addition to the user name and password, which basically represents the first factor. An additional one-time password is generated, sent and requested by the application or service to which you want to log in. Usually, an SMS or email is sent to a previously configured account or mobile phone. This contains a small password or a token that must be entered in the corresponding application.  &lt;/p&gt;

&lt;p&gt;Another possibility for MFA is the use of an authenticator application. There are various applications for the most common mobile phone operating systems. In my company, for example, we use the Microsoft Authenticator. Such an authenticator app supports several authentication methods. Among others also the TOTP method. See: &lt;a href="https://de.wikipedia.org/wiki/Time-based%5C_One-time%5C_Password%5C_Algorithmus" rel="noopener noreferrer"&gt;https://de.wikipedia.org/wiki/Time-based\_One-time\_Password\_Algorithmus&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;In general, an encrypted secret is exchanged and the validity is calculated with an algorithm. The calculated token changes every 30 seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to implement such an MFA in APEX?
&lt;/h3&gt;

&lt;p&gt;A few years ago, someone on the Oracle forum posted the actual code for the generation. See: &lt;a href="https://forums.oracle.com/ords/apexds/post/google-authenticator-totp-0920" rel="noopener noreferrer"&gt;https://forums.oracle.com/ords/apexds/post/google-authenticator-totp-0920&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We use this code as the basis for calculating a token that is based on a secret assigned to the user. We wrap the code from the forum in its own method and return the determined token here. We have to compare this with the user's input at the appropriate locations.  &lt;/p&gt;

&lt;p&gt;Please understand that I cannot show the whole code here. Unfortunately, I cannot host a demo application on &lt;a href="https://apex.oracle.com" rel="noopener noreferrer"&gt;https://apex.oracle.com&lt;/a&gt; because the package &lt;strong&gt;dbms_crypto&lt;/strong&gt; is not available there.  &lt;/p&gt;

&lt;p&gt;So to set up the second factor, we create a secret and then store it with the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C_BASE32_CHARS constant varchar2(32) := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';

function generate_random_base32_string(length number) return varchar2 is
  l_random_string varchar2(32767);
begin
  for i in 1..length loop
    l_random_string := l_random_string || 
                       substr(C_BASE32_CHARS, 1 + floor(dbms_random.value(0, 32)), 1);
  end loop;

  return l_random_string;
end;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to make the whole process as simple as possible for the user, we offer him &lt;strong&gt;(1)&lt;/strong&gt; a corresponding Authenticator App directly for installation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7bbcnn0hpwj12b6l26o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7bbcnn0hpwj12b6l26o.png" alt="Configuring a MFA" width="737" height="1752"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Configuring a MFA&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The user can then enter the generated secret &lt;strong&gt;(2)&lt;/strong&gt; manually into the application or simply scan the QR code &lt;strong&gt;(3)&lt;/strong&gt;. This has a special structure (see code excerpt).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C_OTP_AUTH_LINK constant varchar2(1000) := 'otpauth://totp/%0?secret=%1&amp;amp;issuer=%2&amp;amp;algorithm=SHA1&amp;amp;digits=6&amp;amp;period=30';

function get_otpauth_link(p_secret in varchar2,
                          p_name in varchar2,
                          p_issuer in varchar2,
                          p_prefix in varchar2 default null)
                          return varchar2 is
  l_otp_auth_link varchar2(4000);
begin
  l_otp_auth_link := apex_string.format(p_message =&amp;gt; C_OTP_AUTH_LINK,
                                        p0 =&amp;gt; p_name,
                                        p1 =&amp;gt; p_secret,
                                        p2 =&amp;gt; p_issuer);

  return p_prefix || case when p_prefix is null then l_otp_auth_link 
                                         else apex_util.url_encode(l_otp_auth_link) end;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The image, in my case an SVG image, of the QR code is created here with the package ZT_QR from the repo: &lt;a href="https://github.com/zorantica/plsql-qr-code" rel="noopener noreferrer"&gt;https://github.com/zorantica/plsql-qr-code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As soon as the user has scanned the QR code, a new entry for authentication is displayed in his Authenticator app. With the code displayed there, they can then confirm directly in the application &lt;strong&gt;(4)&lt;/strong&gt; that the authentication works using the additional factor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fju9lpyxkb2p47lxki5i7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fju9lpyxkb2p47lxki5i7.gif" alt="Recording of config MFA service using 2FAS Application" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Recording of config MFA service using 2FAS Application&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here you can see what the process might look like.&lt;/p&gt;

&lt;p&gt;The next step is then only to implement the additional factor in the login screen of the actual application. Here, the user name and the password must first be validated. Then the input fields for the token are displayed. Only after validation of this input does the actual login to the application become valid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxt14e5bqp6fbypy4ig7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxt14e5bqp6fbypy4ig7.png" alt="Screenshot with enter Token to Sign In process" width="708" height="801"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Enter Token to Sign In&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I don't know Joel personally. I have seen him at some conferences and in videos. I think that with Oracle's commitment to APEX as the Cloud Application Development Platform, it's certainly a very big dream of Joel's come true. I hope we all do as you have wished.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;small&gt;Image by Mahesh Patel from Pixabay&lt;/small&gt;&lt;/p&gt;

</description>
      <category>plsql</category>
      <category>apex</category>
    </item>
    <item>
      <title>Use APEX API to display version infos in your apps</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Fri, 06 Oct 2023 14:46:12 +0000</pubDate>
      <link>https://dev.to/maikmichel/use-apex-api-to-display-version-infos-in-your-apps-15c9</link>
      <guid>https://dev.to/maikmichel/use-apex-api-to-display-version-infos-in-your-apps-15c9</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fgcuf00853xrtvwujx8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fgcuf00853xrtvwujx8.jpg" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many projects require the current version of the application. Oracle APEX applications have a version identifier stored in the application settings by default. This is usually "Release 1.0". In the past, I have stored a version information in semantic form and a log from the commits, matching this version, with the release. To do this, I wrote the version information in a release table during deployment and stored a global application process that reads this information when the application or session is started and writes it to an application item that then displays the corresponding version in the settings at runtime using substitution notation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e6392mc1p7taesp48uw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e6392mc1p7taesp48uw.png" alt="application properties showing substitution variable in version field" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For some applications, this is quite an overhead.&lt;/p&gt;

&lt;p&gt;Since version 23.1, APEX also offers a solution for this. It is now possible to set the version via API. Setting the workspace and actually calling the API is sufficient here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;begin
  apex_application_install.set_workspace (p_workspace =&amp;gt; 'DEMO' );
  apex_application_admin.set_application_version ( p_application_id =&amp;gt; 1000,
                                                   p_version =&amp;gt; 'Release 1.0');
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actually quite simple.&lt;/p&gt;

&lt;p&gt;The whole thing makes even more sense if you include this call in your CI/CD pipeline. If you use &lt;a href="https://github.com/MaikMichel/dbFlow" rel="noopener noreferrer"&gt;&lt;strong&gt;dbFlow&lt;/strong&gt;&lt;/a&gt;, for example, you could simply write a global hook script that calls this API directly at the end of a deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxuu81hppztrmlqekz54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxuu81hppztrmlqekz54.png" alt="VS Code Treeview with a post hook file selected" width="423" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This script is called by &lt;a href="https://github.com/MaikMichel/dbFlow" rel="noopener noreferrer"&gt;&lt;strong&gt;dbFlow&lt;/strong&gt;&lt;/a&gt;at the end (post) of the main installation. The project here is called TAYRA and the schema used to import the applications is TAYRA_APP. This is a multi-schema setup that maps to a classic 3-tier model. &lt;a href="https://github.com/MaikMichel/dbFlow" rel="noopener noreferrer"&gt;&lt;strong&gt;dbFlow&lt;/strong&gt;&lt;/a&gt;always calls these scripts with the parameters for the version and the import mode. Therefore, such a script can look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set define '^'
set concat on
set concat .
set verify off
set serveroutput on
set linesize 2000
set wrap off
SET TERMOUT OFF
COLUMN 1 NEW_VALUE 1
COLUMN 2 NEW_VALUE 2

SELECT '' "1" FROM dual WHERE ROWNUM = 0;
SELECT '' "2" FROM dual WHERE ROWNUM = 0;

-- Set params to internal vars
DEFINE _parameter_01 = ^1 "0.0.0"
DEFINE _parameter_02 = ^2 "undefined"

define VERSION = ^_parameter_01
define MODE = ^_parameter_02

SET TERMOUT ON
PROMPT ********************************************************************
PROMPT * VERSION &amp;lt;^VERSION&amp;gt;
PROMPT * MODE &amp;lt;^MODE&amp;gt;
PROMPT ********************************************************************

set timing on;
prompt ............................................................................
prompt ............................................................................
prompt .. ..
prompt .. Setting Versioninfos ..
prompt .. ..
prompt ............................................................................
prompt ............................................................................
begin
  apex_application_install.set_workspace (p_workspace =&amp;gt; 'TAYRA' );
  for apps in (select column_value
                 from table(apex_string.split_numbers('1000:2000:3000', ':')))
  loop
    apex_application_admin.set_application_version(p_application_id =&amp;gt; apps.column_value,
                                                   p_version =&amp;gt; 'Release ^VERSION ('||to_char(sysdate, 'DD.MM.YYYY HH24:MI')||')');
  end loop;
end;
/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing, the corresponding applications show the appropriate version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6eibl1qesr3x4jg8gxx8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6eibl1qesr3x4jg8gxx8.png" alt="APEX default footer showing version number" width="623" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I tend to always display a version identifier to give a context to screenshot which shows a part or the app.&lt;/p&gt;

</description>
      <category>plsql</category>
      <category>apex</category>
    </item>
    <item>
      <title>Maximizing Application Insights with Column Prefixes</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Mon, 07 Aug 2023 19:30:24 +0000</pubDate>
      <link>https://dev.to/maikmichel/maximizing-application-insights-with-column-prefixes-2h2h</link>
      <guid>https://dev.to/maikmichel/maximizing-application-insights-with-column-prefixes-2h2h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdftiqmthlpeu2y2cj1v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdftiqmthlpeu2y2cj1v.jpg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In many projects, I keep encountering negative opinions towards column prefixes. Just recently I started a small poll on Twitter about this topic. And also there the opinion was 75% against column prefixes.&lt;/p&gt;

&lt;center&gt;
&lt;blockquote&gt;
&lt;p&gt;Column names with or without prefix? Leave a comment why you prefer the one over the other. &lt;a href="https://twitter.com/hashtag/orclAPEX?src=hash&amp;amp;ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;#orclAPEX&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/oracle?src=hash&amp;amp;ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;#oracle&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/Database?src=hash&amp;amp;ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;#Database&lt;/a&gt;&lt;/p&gt;— Maik Michel (@Maik__Michel) &lt;a href="https://twitter.com/Maik__Michel/status/1672663551209611267?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;June 24, 2023&lt;/a&gt;
&lt;/blockquote&gt; 
&lt;/center&gt;

&lt;p&gt;I can't even say exactly where this comes from. But I suspect more from the &lt;em&gt;non-SQL /PLSQL&lt;/em&gt; side. In other languages like Java the use of prefixes makes no sense at all and yes, if you have an object relational mapper that generates code that is prefixed, it's pretty ugly.  &lt;/p&gt;

&lt;p&gt;Here in my example it is primarily about &lt;strong&gt;Oracle SQL/PLSQL&lt;/strong&gt; and also &lt;strong&gt;APEX&lt;/strong&gt; applications. I think we agree that there should be some rules regarding the naming convention, meaning the notation of columns and objects within the database. From many projects I know the following rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No prefixes&lt;/li&gt;
&lt;li&gt;Columns with PrimaryKey are name by tablename_ID&lt;/li&gt;
&lt;li&gt;Columns which are linked by a ForeignKey relation are named by their own PrimaryKey column&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is an example with the tables PROJECTS and TASKS, which are related to each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create table projects (
  projects_id number not null, -- primary key
  name varchar2(250 char) not null,
  start_date date,
  end_date date,
  created_at date not null,
  created_by varchar2(250 char) not null,
  modified_at date not null,
  modified_by varchar2(250 char) not null
);

create table tasks (
  tasks_id number not null, -- primary key
  name varchar2(250 char) not null,
  hours_estimates number(5),
  projects_id number not null, -- foreign key
  created_at date not null,
  created_by varchar2(250 char) not null,
  modified_at date not null,
  modified_by varchar2(250 char) not null
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this principle it is noticeable that we must take in a select statement, which works with a join, definitely an alias per table, since here the ID columns are never unique. In addition, the audit columns are also named identically, which makes the simple joining of two tables much more complicated.  &lt;/p&gt;

&lt;p&gt;Another impact, and in my opinion a big one, is the maintainability of the database PL/SQL code that results from such naming. So let's imagine a project where there are a lot of packages and additionally a lot of APEX pages where the corresponding information is displayed or edited. And now we have to change the logic concerning the column "name" of the Tasks table. We have to check all places in the code where this column is used.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That is really annoying&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now how about a naming convention that provides column prefixes?  &lt;/p&gt;

&lt;p&gt;The following rule has worked well in all my projects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Each column of a table gets assigned a prefix that is unique per table. (The naming / glossary becomes part of the source code and is directly visible to all developers)&lt;/li&gt;
&lt;li&gt;Columns with PrimaryKey get the prefix and ID (xyz_id)&lt;/li&gt;
&lt;li&gt;Columns which are linked by a ForeignKey relation are named like their PrimaryKey column but with Prefix.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thus each column is unique&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create table projects (
  prj_id number not null, -- primary key
  prj_name varchar2(250 char) not null,
  prj_start date,
  prj_end date,
  prj_created_at date not null,
  prj_created_by varchar2(250 char) not null,
  prj_modified_at date not null,
  prj_modified_by varchar2(250 char) not null
);

create table tasks (
  tsk_id number not null, -- primary key
  tsk_name varchar2(250 char) not null,
  tsk_hours_estimates number(5),
  tsk_prj_id number not null, -- foreign key
  tsk_created_at date not null,
  tsk_created_by varchar2(250 char) not null,
  tsk_modified_at date not null,
  tsk_modified_by varchar2(250 char) not null
);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Which prefixes are chosen and whether they are 3, 4 or 5 digits must be made dependent on the project size. Important is a kind of glosar, in which the mapping can be looked up.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Besides the actual advantage for the impact analysis, there is also the advantage in the naming to exclude certain words as column names. I cannot name a column &lt;u&gt;end&lt;/u&gt; in SQL. I would have to surround this column with double quotation marks or name it something else.&lt;/p&gt;

&lt;p&gt;And now we can look for our Impact:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqztg1e0zio425v3lip0h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqztg1e0zio425v3lip0h.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Impact analysis - Find in Files / Database Objects the use of a specific columns&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bam, in just 1 second I see the impact
&lt;/h3&gt;

</description>
      <category>sql</category>
      <category>oracle</category>
      <category>database</category>
      <category>apex</category>
    </item>
    <item>
      <title>Optimize Your Project Organization with VSCode's File Nesting Feature!</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Tue, 18 Jul 2023 18:24:56 +0000</pubDate>
      <link>https://dev.to/maikmichel/optimize-your-project-organization-with-vscodes-file-nesting-feature-11ka</link>
      <guid>https://dev.to/maikmichel/optimize-your-project-organization-with-vscodes-file-nesting-feature-11ka</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uvbjb2vs4e69ibz9uxd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uvbjb2vs4e69ibz9uxd.jpg" width="800" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Greetings, fellow developers! Have you ever found yourself wrestling with a growing number of components in your project? Tables, packages, and files galore! Keeping everything organized can be quite a task. But fear not, because I have an exciting solution to share with you: VSCode's File Nesting feature.  &lt;/p&gt;

&lt;p&gt;Let me paint a serene picture for you. Picture yourself in the tranquil realm of your coding environment, where order reigns supreme. With File Nesting, you have the power to create a virtual folder beneath your main file, providing a dedicated space for related files. It's like having a personal assistant that effortlessly organizes your project structure.  &lt;/p&gt;

&lt;p&gt;Using File Nesting is a breeze. Just create a file within the folder you wish to organize. It could be any file type, but I personally find Markdown to be elegantly simple. To give it prominence, prefix its filename with an underscore. This clever trick ensures it appears at the top of the directory, catching your eye immediately.  &lt;/p&gt;

&lt;p&gt;Now, let's unlock the full potential of File Nesting. Open up your VSCode settings and prepare to customize your organization magic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
  "_common.md": "app_defaults.pk*, apx_app_util.pk*, apx_ui_util.pk*, generic_templates.pk*",
}
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enabling &lt;code&gt;explorer.fileNesting.enabled&lt;/code&gt; sets the stage for a beautifully organized coding experience. But there's more! With &lt;code&gt;explorer.fileNesting.patterns&lt;/code&gt;, you can define your own rules to tailor the nesting behavior. This is where you can exercise your creativity and create a structure that aligns with your project's needs.  &lt;/p&gt;

&lt;p&gt;Imagine the sheer joy of effortlessly locating the files you need, with a logical structure that simplifies your workflow. No more endless scrolling or searching for that elusive file buried deep within the hierarchy. With File Nesting, harmony and efficiency become your trusted companions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsw237kj0r13kef2rrfmi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsw237kj0r13kef2rrfmi.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, my friends, it's time to embrace the elegance of File Nesting. Let VSCode be your partner as you conquer the challenges of managing large-scale projects. Enjoy the serenity of a clutter-free workspace, and let your creativity flourish.  &lt;/p&gt;

&lt;p&gt;Happy coding, my fellow seekers of order!&lt;/p&gt;

</description>
      <category>vscode</category>
    </item>
    <item>
      <title>Highlight current row</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Sun, 09 Jul 2023 19:50:52 +0000</pubDate>
      <link>https://dev.to/maikmichel/highlight-current-row-17f0</link>
      <guid>https://dev.to/maikmichel/highlight-current-row-17f0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojwb6bv84b8pg6i8csth.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojwb6bv84b8pg6i8csth.jpg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In many applications I build, I use modal dialogs for the actual transaction. This is how the actual data records are processed. The user himself usually opens the dialog with a link. This is often found as a link in a classic report. As soon as the user clicks on this link, he can edit the corresponding content. From a UI/UX perspective, the reference to the clicked content is lost. Due to the shift in focus, it is usually difficult or even impossible to see to which data set the opened dialog actually belongs.  &lt;/p&gt;

&lt;p&gt;For this reason I mark the corresponding line with the focus. The event &lt;code&gt;onfocus&lt;/code&gt; is triggered by the actual click on the button/link or by using the keyboard.  &lt;/p&gt;

&lt;p&gt;So first we need the function that marks the line for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function highlightRow(link) {  
  // remove old highlighted rows
  document.querySelectorAll("table tr.highlighted-row").forEach((elem) =&amp;gt; {
    elem.classList.remove('highlighted-row');
  });

  // add class to tr
  link.parentNode.parentNode.classList.add('highlighted-row');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afterwards, we build them into the attribute field of the actual link in the Classic Report:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzye50nsh93owvfyw351g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzye50nsh93owvfyw351g.png" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So that the clicked record also colors itself, we define here still another brighter version of the primary color and a class, which uses this as background color as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqqzwgjlwgta7yelu5j2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqqzwgjlwgta7yelu5j2.png" width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done, now as soon as the link is clicked, the corresponding line is highlighted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32m43avp9bc6zyr1hsme.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32m43avp9bc6zyr1hsme.gif" width="1520" height="858"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a look at the &lt;a href="https://apex.oracle.com/pls/apex/r/die21/demos/mixed-primary-color" rel="noopener noreferrer"&gt;demo application&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
      <category>apex</category>
    </item>
    <item>
      <title>Use multiple variations of your primary color</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Sun, 09 Jul 2023 19:48:47 +0000</pubDate>
      <link>https://dev.to/maikmichel/use-multiple-variations-of-your-primary-color-97f</link>
      <guid>https://dev.to/maikmichel/use-multiple-variations-of-your-primary-color-97f</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fmlu0ty8hgnut7trg0y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fmlu0ty8hgnut7trg0y.jpg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes it happens that you want to apply a color to certain elements in your application. Now you could just take any color. But you can't, because the color has to match your application. It could also be that your application runs with different themes. So you can't just take any blue or any red. The whole thing has to be variable.  &lt;/p&gt;

&lt;p&gt;Fortunately CSS offers help here. There is a CSS function called color-mix. We can use this to mix one color to another color. The whole thing is best done with white or black, to stay with the main color of the theme. And so we manage to define different variations of our primary color.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8hkleqj5b2pjymnusti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8hkleqj5b2pjymnusti.png" width="792" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you have declared your color values, you can easily use them in different classes. For example, to color a row in a Classic Report.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://micodify.de/media/posts/47/gallery/css-declare-vars.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuf4txnftimc4wyi3gj3.png" width="768" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://micodify.de/media/posts/47/gallery/css-define-background-color.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc12iqfl0hr4mn1odsl6g.png" width="768" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can take a look at the &lt;a href="https://apex.oracle.com/pls/apex/r/die21/demos/mixed-primary-color" rel="noopener noreferrer"&gt;demo application&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
      <category>apex</category>
    </item>
    <item>
      <title>Better UX - Display changes without reloading a page</title>
      <dc:creator>Maik Michel</dc:creator>
      <pubDate>Thu, 08 Jun 2023 13:24:05 +0000</pubDate>
      <link>https://dev.to/maikmichel/better-ux-display-changes-without-reloading-a-page-1g7o</link>
      <guid>https://dev.to/maikmichel/better-ux-display-changes-without-reloading-a-page-1g7o</guid>
      <description>&lt;p&gt;Often it happens that data on an application page changes. This can happen through the user himself, for example, when he changes a data record through a modal dialog, or through other users or events on the same system. Let's imagine we are on an application that deals with campaigns. On this page you can see all the dependent data. The campaign itself can be edited through a modal dialog. And just in this dialog we can change the title of the campaign.  &lt;/p&gt;

&lt;p&gt;If we close this dialog now, we are still on a campaign with the "old" name. In the standard APEX world, it is now considered that this page needs to be reloaded, and thus one would rather choose a branch to the parent page here, instead of just closing the dialog.  &lt;/p&gt;

&lt;p&gt;I admit, changing the name of a campaign and then updating it is relatively trivial and easy to implement with JavaScript means. But the principle here is applicable to anything. A large part of APEX regions can already be updated. Actually, this is true for almost all regions that are based on a query of some kind.  &lt;/p&gt;

&lt;p&gt;Here, however, the region titles unfortunately do not belong. So this article is about how you can integrate this reactivity into your applications with simple means and by using Knockoutjs.  &lt;/p&gt;

&lt;p&gt;As already announced I use Kockout.js for this. Knockout is a free open source library, which is always included in the Oracle Jet part of APEX. Therefore it is easy to include this library in our site or application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#JET_BASE_DIRECTORY#js/libs/knockout/knockout-3.5.1.js    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Knockout is mainly about databinding and reactivity. For this Knockout uses the MVMV principle. Data from the model is stored in a ViewModel and bound to a view by data binding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzvn8e8uy9a63iyerona.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzvn8e8uy9a63iyerona.png" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Knockout then takes care of updating the data in the ViewModel and in the view. And if we imagine the whole thing dynamically in our APEX world, it might look something like this. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7fekwsia4dscb21vuhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7fekwsia4dscb21vuhb.png" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Data is returned here via a query as JSON. This query is part of an AJAX callback, which is stored as a process on the respective page, for example. The data is requested in a JavaScript context, e.g. Dynamics Action, and then manifested in the ViewModel. Through the data binding in the view, Knockout takes care of and the corresponding update of the respective Html element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wf1pkc0r2o2p7x4egj8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5wf1pkc0r2o2p7x4egj8.gif" width="1901" height="961"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the example according to the ScreenShot (Gif), an AJAX callback is called via JavaScript when the dialog is closed, which returns the campaign title packaged as JSON and writes it to the ViewModel. Knockout then takes care of updating the region title, since the binding in the model was referenced here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o6v10bm119es55phpve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o6v10bm119es55phpve.png" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8di71hbo1m06zdipkrvs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8di71hbo1m06zdipkrvs.png" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The content of the AJAX callback can then look like this, for example. The end result is that the campaign name is returned as JSON.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0zpbfksv55w83wtzgsb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0zpbfksv55w83wtzgsb.png" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now to update the campaign name in the page by knockout, it is enough to bind it to the text property of a span-element inside the region header.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmicodify.de%2Fmedia%2Fposts%2F46%2Fpagebuilder-bindspan.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmicodify.de%2Fmedia%2Fposts%2F46%2Fpagebuilder-bindspan.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I said, for the example updating only one value. Knockout is probably a bit overkill. But let's imagine that there is more than one element to be updated. In this moment the use of Knockout makes sense, because here only the minimal additions are necessary.  &lt;/p&gt;

&lt;p&gt;Who has the will, just have a look at the Knockout page. &lt;a href="https://knockoutjs.com/" rel="noopener noreferrer"&gt;https://knockoutjs.com&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
