ERPNext Foundation ERPNext Cloud User Manual Blog Discuss Frappé* Donate

Learning Javascript for ERPNext


#1

Hi All,

I am developing an app for ERPNext. I am very comfortable with Python but not so much with javascript. I have watched the video tutorials on frappe development and also read some materials but see that there is little coverage of the client end javascript development. I have been looking at the js code for some of the modules and trying to wrap my mind around the ideas.

Are there any specific tutorials on client end js development that don’t assume advanced js knowledge?

Any tips on reading material that will help speed up my learning (Other than the standard js tutorials in the web)? Up to now I can create some buttons, perform call backs to python and do some front end validation but I still feel out of depth in getting the bigger picture.

Why for example do I see…

erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.extend({
    onload: function(doc) {
        this._super();
        this.frm.set_query("item_code", "items", function() {
            return {
                query: "erpnext.controllers.queries.item_query"
            }
        });
    },

    refresh: function(doc) {
        this._super();

        if(doc.docstatus==0) {
            cur_frm.add_custom_button(__("Get Items from BOM"),
                cur_frm.cscript.get_items_from_bom, "icon-sitemap", "btn-default");
        }

        if(doc.docstatus == 1 && doc.status != 'Stopped') {

            if(flt(doc.per_ordered, 2) < 100) {
                // make
                if(doc.material_request_type === "Material Transfer" && doc.status === "Submitted")
                    cur_frm.add_custom_button(__("Transfer Material"),
                    this.make_stock_entry, __("Make"));

                if(doc.material_request_type === "Material Issue" && doc.status === "Submitted")
                    cur_frm.add_custom_button(__("Issue Material"),
                    this.make_stock_entry, __("Make"));

                if(doc.material_request_type === "Purchase")
                    cur_frm.add_custom_button(__('Purchase Order'),
                        this.make_purchase_order, __("Make"));

                if(doc.material_request_type === "Purchase")
                    cur_frm.add_custom_button(__("Supplier Quotation"),
                    this.make_supplier_quotation, __("Make"));
                
                if(doc.material_request_type === "Manufacture" && doc.status === "Submitted")
                    cur_frm.add_custom_button(__("Production Order"),
                    this.raise_production_orders, __("Make"));
                
                cur_frm.page.set_inner_btn_group_as_primary(__("Make"));

                // stop
                cur_frm.add_custom_button(__('Stop'),
                    cur_frm.cscript['Stop Material Request'], __("Status"));

            }
        }

        if (this.frm.doc.docstatus===0) {
            cur_frm.add_custom_button(__('Sales Order'),
                function() {
                    frappe.model.map_current_doc({
                        method: "erpnext.selling.doctype.sales_order.sales_order.make_material_request",
                        source_doctype: "Sales Order",
                        get_query_filters: {
                            docstatus: 1,
                            status: ["!=", "Closed"],
                            per_delivered: ["<", 99.99],
                            company: cur_frm.doc.company
                        }
                    })
                }, __("Get items from"));
        }

        if(doc.docstatus == 1 && doc.status == 'Stopped')
            cur_frm.add_custom_button(__('Re-open'),
                cur_frm.cscript['Unstop Material Request'], __("Status"));

    },

and what is the difference with putting the code in

frappe.ui.form.on("Material Request Item", {
        "qty": function(frm, doctype, name) {
                var d = locals[doctype][name];
                if (flt(d.qty) < flt(d.min_order_qty)) {
                    alert(__("Warning: Material Requested Qty is less than Minimum Order Qty"));
                }
            }
        }
);

All in all, thank you very much to all the people who have made this possible. It’s really putting back the fun in module development especially for me coming from odoo.

Regards,

Alex


Add js file in view
#2

@weakref Welcome to ERPNext :smile:

The second example is correct. There is till a lot of legacy code that needs to be cleaned up and will take a while.

But with the new event handlers, you can attach multiple handlers on the same event.

The JS documentation is pretty weak, but you are usually playing within the forms.

Do post if you get stuck.


#3

@rmehta Thanks a lot! Will sure come back here


#4

Learning resources are recommended in the official Frappe Tutorial page here.

Excerpt:
JavaScript and jQuery
To customize forms and create rich user interfaces, you should learn JavaScript and the popular library jQuery.

Resources:

Codecademy Tutorial for JavaScript
Codecademy Tutorial for jQuery