Friday, 31 May 2024

UI Coding Standards and Best Practices for OJET

 HTML

Note below guidelines when we write HTML.

  • Use lowercase letters within element names, attributes, and values
  • Indent nested elements
  • Strictly use double quotes, not single or completely omitted quotes.
  • Add IDs to the HTML elements wherever possible this will help to access specific element easily, it also makes automation simpler.
  • ID and Class values need to be practical, relating to the content itself, not the style of the content.
  • Use the HTML5 structural elements where suitable.


  <div class="container">  

 <div class="article">    

 <div class="headline">Headlines Across the World</div>

    </div>  

   </div>


(tick)   <div class="container">

    <article>

    <h1>Headlines Across the World</h1>

    </article>

     </div>

VPAT Support

Make sure OJET components must support accessibilty standards. Add following attributes to the elements for accessibity support.

  • aria-label 
  • aria-labelledby
  • title e.t.c

MLS Support

  • All the strings must be get from translation bundle files. Avoid hardcoded strings.
  • New composites reference should be there in ngaa_configmanager.wptg file for translations return
  • Need to create MLS infrastructure support for new composites

data-bind syntax

Remove the data-bind syntax and move to the new ojet standard syntax for development.

https://www.oracle.com/webfolder/technetwork/jet/jsdocs/BindingOverview.html

css

Redwood Icons

Use below url to access all the available redwood icons and use respective classes.

https://static.oracle.com/cdn/fnd/gallery/2104.4.0/images/preview/index.html

Convert Images To Base64

The advantage lies in not having to open another connection and make a HTTP request to the server for the image. This benefit is lost very quickly so there's only an advantage for large numbers of very tiny individual images.

https://www.base64-image.de/

Upload image-->Convert to Base64→Use base64 code as css background-image

Example:

.image{
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAC0AAAAReCAYAAABE27ddfffsdfsdfsd');
}

Always avoid inline styling

Using inline styling show the HTML code messy. The following issues there when we use inline styling

  • Lack of reusability
  • Difficulty in code readability
  • Lack of writing media queries
  • Maintenance problem


<div style="float:left">
<img src="images/logo.gif" alt="" />
</div>

(tick) <div class="left">
       <img src="images/logo.gif" alt="" />
        </div>

     .left{

      float:left

    }

Shorthand CSS

One feature of CSS is the ability to use shorthand properties and values.

.container {
margin-top: 5px;
margin-right: 10px;
margin-bottom: 5px;
margin-left: 10px;
}

(tick)   .container {

       margin:5px 10px;

       }

Combine Elements

Elements in a stylesheet sometimes share properties. Instead of rewriting previous code, why not just combine them? For example, your h1h2, and h3 elements might all share the same font and color:

h1, h2, h3 {font-family: Open Sans UI, color: #333}

We could add unique characteristics to each of these header styles if we wanted (i.e. h1 {font-size: 20px}) later in the stylesheet.

Make Use of Generic Classes

Identify the generic usages and create generic classes for the elements.

For example, I find myself using float:right and float:left over and over in my designs. So I simply add the classes .left and .right to my stylesheet, and reference it in the elements.

.left-container {float:left}
.right-container {float:right}
<div class="left-container">Left Section</div>

Avoid the !Important Tag

Another best practice to implement into your CSS work routine is to avoid overusing the !important tag as much as you can.

Comment Your CSS

 it's a great idea to comment your code in sections. To add a comment, simply add /* behind the comment, and */ to close it, like so:

* Here's how you comment CSS */

Jet Recommended Standards for Component/Syntax Usage

oj-bind-text, oj-bind-if, oj-bind-for-each

  Better to use following JET recommended standards,

  • <oj-bind-text> for strings instead of text binding for components.
  • <oj-bind-if> for conditions checking

  • <oj-bind-for-each> for looping instead of foreach bindings

  <span data-bind="text:i18n.common.copyrightlabel"></span>

  <!-- ko if: cell.row.isStatusRejected -->
<div>Rendered Component</div>
<!--/ko-->
<div data-bind="foreach:footerLinks">
<span data-bind="text:$data"></span>
</div>

(tick)   <span><oj-bind-text value="[[i18n.common.copyrightlabel]]"></oj-bind-text></span>

    <oj-bind-if test="[[cell.row.isStatusRejected]]">
<div>Rendered Component</div>
</oj-bind-if>
   <oj-bind-for-each data="[[footerLinks]]">
<template>
<oj-bind-text value="[[$data]]"></oj-bind-text>
</template>
</oj-bind-for-each>

Class Binding

Use :class binding for adding dynamic style classes to the HTML elements instead of css bindings.

 <li data-bind="css: {'oj-disabled': menuOption.disabled}"></li>

(tick)   <li:class='[[menuOption.disabled?"oj-disabled'":""]]'></li>

https://jet.oraclecorp.com/jetCookbook.html?component=binding&demo=class

Style Binding

Use :style binding for adding css styles for the components instead of knockout style bindings.

 <li data-bind="css: {display: isEnabled?'block':'none'}"></li>

(tick)   <li :style.display=''[[isEnabled?"block":"none"]]></li>

https://jet.oraclecorp.com/jetCookbook.html?component=binding&demo=style

JavaScript

Exception Handling

We must deal with thrown exceptions without interrupting program execution. Usually, a script “dies” (immediately stops) in case of an error, printing it to console.

But there’s a syntax construct try...catch that allows us to “catch” errors so the script can, instead of dying, do something more reasonable

Example:

The best way to catch invalid JSON parsing errors is to put the calls to JSON.parse() to a try/catch block.

function parseJSONFromResponse(data) {
        return JSON.parse(data);
}

In above code, If any issues with parsing script dies and block the other code execution,

 (tick)   function parseJSONFromResponse(data) {
    try {
        return JSON.parse(data);
    } catch (e) {
        console.err(e);
        // Return a default object, or null based on use case.
        return {}
    }
}

Don’t trust any data

Basically, if we access REST API data to perform some operations on the UI. Make sure to check what type of data getting.

JavaScript, it is very important to test the type of parameters sent to your functions (using the typeof keyword).

The following would be an error if dataSetColumns is not an Array (for example dataSetColumns coming as null). 

function getDataSetColumns(dataSetColumns){

let name=dataSetColumns[0].name;

}

//script “dies” (immediately stops) in case of an error, printing it to console.

Always write defensive coding. 

 (tick)   function getDataSetColumns(dataSetColumns) {

    if (typeof members === 'object' &&
        typeof members.slice === 'function') {
        if (dataSetColumns.length > 0) {
            let name = dataSetColumns[0].name ? dataSetColumns[0].name : '';
        }

    }

}

Naming Convention for Variables

The most recommended way to declare JavaScript variables is with camel case variable names. 

let datasource="Fusion"

let DataSource="Fusion"

let DATASOURCE="Fusion"

let src="Fusion

let d="Fusion"

The names of variables should be self-explanatory and describe the stored value.

 (tick)   let dataSource="Fusion"

Naming Convention for Functions

The most recommended way to declare JavaScript function has is with camel case. Should use descriptive nouns and verbs as prefixes.

function datasourcename(dsName) { 
  return dsName;
}

 (tick)   function getDatasourceName(dsName) {
    return dsName;
}

Naming Convention for Constants

JavaScript constants should be written in uppercase because they are non changing variables.

const voAutoExpiryDays = 7;

 (tick)   const VO_AUTO_EXPIRY_DAYS 7;

Be efficient with DOM manipulations

Accessing the DOM is essential for getting the most out of your program, but doing so repeatedly causes visual clutter and will slow down the program.

Instead, access it once and cache it for later use in a variable. From then on, you can access that variable instead of the DOM directly. This process is visually cleaner and more efficient.

function getFormDetails() {
    let userName = $("#form").find(".userName").val();
  let tenantId = $("#form"").find(".tenantId ").val();
    }
// Contents cached to variable "form"
 (tick) function accountInfo(){
    let $form = $("#form");
    let userName = $form .find(".userName").val();
    let tenantId = $form .find(".tenantId").val();
}

Ternary Operator

 Ternary operator can be used to replace a short if-else statement. Multiple small if else  statements when replaced with ternary operators achieves the same and also limits the lines of code.

let result; 
if
(a > b) result = a; else if (a < b) result = b;

  This can be replaced with a single line of code using  ternary operators            

 (tick) let result = a > b ? a : b

Composite(CCA) Common Mistakes

  • Properties passed into the a composite component are defined as camelCase in the component.json, but are passed in with dash-case the html component.
  • If properties that are passed into the html component are not showing up, check to see if it is defined in "properties" in component.json, it is required.


 //component.json
"properties": {
   "configDetails": { "type""string",
 "description""my property",
 "value""""writeback"true }
 }

// Not work: "configDetails" will be undefined within the component
<my-component id="my-component"
 configDetails="{{config}}"></my-component>
 (tick) //component.json
"properties": {
   "configDetails": { "type""string",
 "description""my property"
"value""""writeback"true }
 }
// Works
<my-component id="my-component"
config-details="{{config}}"></my-component>