Chidi Okwudire IT Professional. ERP Enthusiast. NetSuite Certified (Administrator, SuiteCloud Developer II, and ERP Consultant). Celigo Certified (Level 4+). Passionate About Empowerment Through Knowledge Sharing. Always Eager to Learn.

How To Implement Prominent Custom State Labels on NetSuite Records

3 min read

This article explains a quick “hack” to implement custom state labels on NetSuite native and custom records as illustrated below.

Custom state label

Background

Some NetSuite transactions types have a native state machine. For convenience, NetSuite display the state prominently at the top of the page. This is very handy.

Native transaction state label

However, there are situations where NetSuite’s native state machine does not suffice to capture the business process being implemented. For example, in a recent integration with Amazon Seller Central, I modelled sending inventory to Amazon using a transfer order. After analyzing the Seller Central APIs and mapping out the calls to be made including error handling, I ended up with more than 20 distinct states for the item fulfillment record (yes, the process is quite complex!).

As you may know, with the requisite features enabled, NetSuite natively supports only 3 item fulfillment states, namely: Picked, Packed, or Shipped. Thus, we needed a custom state machine. As per common NetSuite design patterns, I implemented a custom record/field to model and expose the state machine. However, for a better user experience, I though it would be great to see the Amazon transfer state next to the native state at the top of the item fulfillment page where users are accustomed to seeing record states. It turned out to be quite easy!


Solution

Below is a code snippet to accomplish the desired result, It injects the status in the beforeLoad event of a user event script deployed to the target record type. Note that because NetSuite does not offer any API for this kind of operation, I resorted to using jQuery to inject the HTML element (more on that shortly).

/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */
define([], 
    () => {
        /**
         * An enumeration of state colors per NetSuite house style
         */
        const NsLabelColor = {
            BLUE:   '#d5e0ec',
            YELLOW: '#fcf9cf',
            GREEN:  '#d7fccf',
            RED:    '#fccfcf'
        }
       
        const beforeLoad = (scriptContext) => {
            try {
                let stateTxt = 'TODO: Implement';
                let errState = false;
                
                // TODO: Implement logic to determine state text/color
                let bgColor = NsLabelColor.YELLOW;
                if (errState) {
                    bgColor = NsLabelColor.RED;
                }

                scriptContext.form.addField({
                    id: 'custpage_nsi_status',
                    label: 'Custom State',
                    type: 'inlinehtml'
                }).defaultValue = `<script>jQuery(function($){
                    require([], function() {
                        /* $(".uir-page-title-secondline").find("div.uir-record-status").remove(); // Uncomment to remove native state */
                        $(".uir-page-title-secondline").append('<div class="uir-record-status" id="pri-amz-status" style="background-color: ${bgColor}">${stateTxt}</div>');
                    });
                })</script>`;
            } catch (e) {
                // Deliberately suppress any errors as this non-critical function should not block the record from loading
                log.error('Error', `Suppressing error encountered while attempting to set the custom state: ${e}`)
            }
        }

        return {beforeLoad}
    });

Depending on your use case, it might make sense to hide the native status completely by uncommenting line 34 above.

You can also implement color coding to distinguish different states. For your convenience, I’ve provided the hex color codes that match NetSuite’s house style. The blue matches the native state background color; the other colors match the Native page notification message types – green (confirmation), yellow (warning), and red (error).

To illustrate color coding for a successful transfer

Observations

1. DOM Manipulation is Not Officially Supported

NetSuite discourages DOM operations like the one above (in simpler terms, that means you’re on your own if you decide to play with the HTML of NetSuite pages outside of the provided APIs). Thus, this solution is effectively a hack that may break if NetSuite changes the internal HTML logic.

Nevertheless, this use case falls within my scope of reasonable hacks because:

  1. The functionality is not business critical; and
  2. Thanks to the try/catch wrapper around the code, the system will gracefully fall back to native behavior if injecting the status fails.

The interested reader is welcome to review my more elaborate assessment on when it is reasonably safe to perform DOM manipulations.

2. This Approach is Not Limited to Transaction Record Types

I deployed the same solution to a custom record and it worked without issues as demonstrated below.

Custom state label on custom record

3. NetSuite’s “New” UI Requires Different Handling

Records that use the “new” NetSuite UI (e.g. Invoice Groups) have different HTML class names. Thus, the above code will need to be adapted accordingly.

Based on quick HTML inspection, replacing uir-page-title-secondline with n-f-title-second-row and uir-record-class with n-f-title-recordstatus in the provided code snippet should do the trick. Which leads me to my next point for those wondering how to discover these HTML elements.

In principle, you should be able to can combine the logic for the current and new NetSuite UI in a single implementation as jQuery should fail gracefully if the target class is not found.

4. Here’s How to Easily Discover HTML Elements

The following snippet shows how to easily inspect the HTML of a page and find the target elements using Google Chrome. Pressing F12 will reveal the developer tools area from which you can select the target element, inspect and even modify the HTML to validate your ideas.

Click the image if it does not play automatically

Conclusion

This article illustrates a quality-of-life enhancement that produces a better user experience. I hope you found it insightful. Often, these little features add up and make an already good solution, better.

Although I illustrated the approach in the context of a NetSuite integration with Amazon Seller Central, there are more common scenarios where I assess that this functionality would be very welcome by users. Take transaction approval workflows for instance. Custom approval workflow typically introduce additional states which may confuse users. It is common to have an “Open” state to indicate that a transaction (e.g. invoice, vendor bill or journal entry) has not yet been submitted for approval. In such a case, it would be helpful to replace the default native “Pending Approval” state label at the top with the custom “Open” state so that users can easily distinguish records have been submitted for approval (Pending Approval) from those that are not yet in the queue (Open). I am sure there are a bunch of other use cases you can come up with.

Finally, if you are looking to integrate NetSuite with Amazon Seller Central for inbound fulfillment or other operations supported by the APIs, you’re in great company. Reach out and let’s discuss your use case.


NetSuite Insights is on a mission to raise the standards around NetSuite practices, one insight at a time. If that resonates with you, learn how you can become an author/collaborator here.

Don’t miss a beat – subscribe to our no-nonsense email list to have these game-changing insights hit your inbox as soon as they’re published. Ignorance? Nah, you’ve got a smarter option. Choose wisdom, choose insights!

Related Posts

Chidi Okwudire IT Professional. ERP Enthusiast. NetSuite Certified (Administrator, SuiteCloud Developer II, and ERP Consultant). Celigo Certified (Level 4+). Passionate About Empowerment Through Knowledge Sharing. Always Eager to Learn.

8 Replies to “How To Implement Prominent Custom State Labels on NetSuite Records”

  1. Had the same issue, what fix it was that instead of appending the data on multiple lin breaks in the editor, put it all in one line, so instead of

    .append(‘${stateTxt}
    ‘);

    put it like

    .append(‘${stateTxt}’);

  2. [continued], find code is cut, so here use &lt and &gt to to replace ”, as that are not allowed to input

    scriptContext.form.addField({
    id: ‘custpage_nsi_status’,
    label: ‘Custom State’,
    type: ‘inlinehtml’
    }).defaultValue = = `&lt script src=”https://code.jquery.com/jquery-3.7.0.min.js” &gt…&lt/script&gt

    1. Hi there,

      NS already loads jQuery so you don’t need to add it yourself. Beyond that, I don’t see anything strange. Confirm that the script is deployed, etc. Please open the developer console and refresh the employee page to see if any errors will be logged in the console.

      1. Thank you to check it. I collate the JQuery section code into one line and delete `//` , then it works on my end 🙂

  3. Thank you for this idea. I tried to add it in employee record type, but I can’t find any change on the page. I add this code in UE script’s beforeLoad function like following, any idea?
    const beforeLoad = (scriptContext) => {
    try {

    log.error(‘Error’, `test`)

    let stateTxt = ‘TODO: Implement’;
    let errState = false;

    // TODO: Implement logic to determine state text/color
    let bgColor = NsLabelColor.YELLOW;
    if (errState) {
    bgColor = NsLabelColor.RED;
    }

    scriptContext.form.addField({
    id: ‘custpage_nsi_status’,
    label: ‘Custom State’,
    type: ‘inlinehtml’
    }).defaultValue = `jQuery(function($){
    require([], function() {
    $(“div .uir-page-title-secondline”).find(“div.uir-record-status”).remove(); // Uncomment to remove native state
    $(“div .uir-page-title-secondline”)
    .append(‘${stateTxt}
    ‘);
    });
    })`;
    } catch (e) {
    // Deliberately suppress any errors as this non-critical function should not block the record from loading
    log.error(‘Error’, `Suppressing error encountered while attempting to set the custom state: ${e}`)
    }
    }

  4. Great article. As the writer said, be careful with DOM manipulation. You could also add an email notification if the “catch” is triggered so that you can quickly fix any errors (i.e. if the DOM has changed).

Leave a Reply

Your email address will not be published. Required fields are marked *

×