Common Mistakes In JS.


In Frappe applications, setting query filters dynamically based on the state of the document is crucial for ensuring that users can only select valid options. This documentation outlines a common mistake encountered while setting filters for the mode_of_payment field based on the payment_type and multi_expense attributes of the document.

Problem Statement

The initial implementation had logical errors that caused the filters for the mode_of_payment field not to display correctly when users selected different payment types. This issue manifested particularly when switching between "Pay" and "Receive" options in the payment type.

this.frm.set_query("mode_of_payment", (doc) => {
    let custom_filters = {};

    if ((doc.multi_expense == 1  && doc.payment_type == "Pay") || doc.payment_type == "Internal Transfer") {
        custom_filters = { "is_payable_cheque": 0, "is_receivable_cheque": 0 };
    } else if (doc.multi_expense == 0 && ["Pay" , "Receive"].includes(doc.payment_type)) {
        custom_filters = doc.payment_type === "Receive" ? { "is_payable_cheque": 0 } : { "is_receivable_cheque": 0 };
    } 

    return {
        filters: custom_filters
    }
});


Issues Identified

  1. Inconsistent Filter Logic: The original implementation checked for specific conditions in a way that did not handle the scenarios correctly when switching payment types. Specifically, the logic that set custom_filters was overly complicated and failed to reset when changing between "Pay" and "Receive".
  2. Failure to Reset Filters: If a user switched from "Receive" to "Pay", the filters would not update as expected due to the conditional logic structure.
  3. Resetting the variable with "{}": using {} in JS is a crucial mistake because {} !== {} in JS the {} value is pointing at an address hence why {} is different. In this issue we wanted to have the filters on initially, so we need to initialize it with the normal condition of else if. Much more space and better refactoring.
  4. JS IS SYNC NOT ASYNC: IT'S VERY IMPORTANT TO NOT THAT JS IS SYNC NOT ASYNC, because the following issue happened because the if conditions took sometime to set the value of the initial value so the {} are back at the game.

Corrected Implementation

The following implementation simplifies the logic for setting custom_filters, ensuring that it correctly applies based on the selected payment_type while also considering the multi_expense status:

this.frm.set_query("mode_of_payment", (doc) => {
    let custom_filters = doc.payment_type === "Receive" 
        ? { "is_payable_cheque": 0 } 
        : { "is_receivable_cheque": 0 };

    if ((doc.multi_expense == 1 && doc.payment_type === "Pay") || doc.payment_type === "Internal Transfer") {
        custom_filters = { "is_payable_cheque": 0, "is_receivable_cheque": 0 };
    }

    return {
        filters: custom_filters
    };
});


Key Improvements

  1. Simplified Logic: The filter assignment for custom_filters is now based directly on the payment_type. This ensures that the filters are set appropriately based on the selection without unnecessary complexity.
  2. Correct Filter Resetting: The implementation ensures that whenever the payment_type changes, the custom_filters are correctly updated and relevant options are displayed based on the current selection makes sure that the state is running no matter what on the load of the page with the default filters.
  3. Enhanced Readability: The revised code is easier to read and maintain, clearly indicating how custom_filters are determined.

Conclusion

This correction ensures that the mode_of_payment field in the Frappe application dynamically updates its available options based on user selections. By simplifying the logic and making sure filters reset correctly, the user experience is significantly improved, leading to fewer errors and confusion.

Discard
Save

On this page

Review Changes ← Back to Content
رسالة الحالة Space Raised By Last update on