Frappe Technologies
Screenshot 2023-10-25 at 10.48.41 PM.png
Form Scripting in Frappe Framework
Introduction to Form Scripting in Frappe.
author

By

Basawaraj Savalagi

·

4 April 2019

·

4

min read

Frappe is a full-stack web application framework. It provides many views like the form view, tree view, report view, etc. Form view is used to enter data and hence needs to be very interactive. Javascript code is written to make this interactivity possible.

1. What Form Scripts Do

Form scripts help us to make forms interactive. They help us to apply business logic. If ‘X’ happens then ‘Y’ should happen kind of logic.

  1. A project might be linked to a company. In the Task when a project is chosen, the company can be set automatically.
  2. A Task might depend on the other tasks. However, these tasks must also belong to the same project. So the options shown in the ‘DEPENDS ON’ section must belong to the same project.
  3. We can also set a parent task, so the values shown in the parent task field should be those which are marked as a group task by enabling the checkbox ‘Is Group’.


2. What a Form Script Looks Like

Frappe framework offers an object named frappe.ui.form.on and we can use the same to build above logic.

We need to pass three parameters to the above object


  1. DocType → In which DocType the code will execute
  2. Event or field → When the code will execute
  3. Function → What the


The above three parameters can be passed in either of the two formats shown below.


frappe.ui.form.on(string, object)


Where the string is a DocType and object is in “event: function” format.


Below is an example.



frappe.ui.form.on("Customer", { onload:function(frm)
   {
       console.log("Hello")
   }
});


The same code can also be written as below.


frappe.ui.form.on(string1, string2, function)


Where the string1 is a DocType, string2 is an event or field and function is a function.

Below is an example


frappe.ui.form.on("Customer","onload",function(frm){
   console.log(“Hello”)
});


3. Detailed Look at ‘Task’ Form Script


Let's take a look at the js code written for the ‘Task’ DocType.


  1. Below code provides the ‘erpnext.projects’ namespace
frappe.provide(“erpnext.projects”);
  1. Below code fetches the company from the project and sets it in the task.
cur_frm.add_fetch(“project”, “company”, “company”);
  1. Below is the outline of the code for various events and fields.
frappe.ui.form.on(“Task”, {
   onload:   function(frm) { //function_here },
   refresh:  function(frm) { //function_here },
   setup:    function(frm) { //function_here },
   project:  function(frm) { //function_here },
   is_group: function(frm) { //function_here },
   validate: function(frm) { //function_here },
});


Now let's look at the code for individual event or field.


Below code is executed as soon as the form is loaded and it sets the filter for values shown in ‘depends_on’ child table. The same task is excluded and tasks which belong to the same project are shown.


onload: function(frm){
   frm.set_query("task", "depends_on", function() {  
       var filters = {    
           name: ["!=", frm.doc.name]  
       };
       if(frm.doc.project) filters["project"] = frm.doc.project;             `      return {
          filters: filters  
      };
})


Below code filters values shown in ‘parent_task’ field, if the form is local (has not been saved yet it) sets the exp_end_date to 7 days from the current date. Also, if the status is not equal to Completed then adds a button labeled “Completed” else adds a button labeled “Reopen”.


refresh: function(frm) {  
   frm.fields_dict['parent_task'].get_query = function() {  
       return {    
           filters: {     "is_group": 1,    
           }
       }  
   }
   if(!frm.is_group){
       var doc = frm.doc;  
       if(doc.__islocal) {    
           if(!frm.doc.exp_end_date) {
               frm.set_value("exp_end_date",new_date);    
           }  
       }    
       if(!doc.__islocal) {    
           if(frm.perm[0].write) {
               if(frm.doc.status!=="Completed" &&
               frm.doc.status!=="Cancelled") {
               frm.add_custom_button(__("Completed"), function() {
                   frm.set_value("status", "Completed");      
                   frm.save();      
               });    
           } else {      
               frm.add_custom_button(__("Reopen"), function() {
               frm.set_value("status", "Open");      
               frm.save();      
           });    
       }    
   }  
}  
}


Below code calls the ‘get_project’ function and the values returned by that function are shown in the ‘project’ field. This sort of code is generally used to filter the values shown in a field.


setup: function(frm) {  
   frm.fields_dict.project.get_query = function() {  
       return {    
           query: "erpnext.projects.doctype.task.task.get_project"
       }
   };
},


Below code will check if the current task has any child tasks and if so prevents the user from setting it as a non-parent task.


is_group: function (frm) {
   frappe.call({
   method:"erpnext.projects.doctype.task.task.check_if_child_exists",   args: {    
   name: frm.doc.name
  },  
callback: function (r) {    
   if (r.message.length > 0) {    
       frappe.msgprint(__(`Cannot convert it to non-group. The following child Tasks exist: ${r.message.join(", ")}.`));
       frm.reload_doc();    
       }  
   }  
})
},


Below code invalidates the cache.


validate: function(frm) {  
   frm.doc.project && frappe.model.remove_from_locals("Project",   frm.doc.project);
},


You can build the logic to be executed on the forms quickly using the events provided by the Frappe framework.


Happy Scripting!


Resources:

https://docs.erpnext.com/docs/v13/user/manual/en/customize-erpnext/client-scripts

https://frappeframework.com/docs/v13/user/en/api/form

https://youtu.be/BgD7_ORlDwc?list=PL3lFfCEoMxvzHtsZHFJ4T3n5yMM3nGJ1W&t=497

Published by

Basawaraj Savalagi

on

4 April 2019

Share

Add your comment

Success!

Error

Comments

No comments, yet.

Discussion

image7f7d4e.png

Paul Mugambi

·

3 days

ago

Beautiful read, and an insight into an individual I respect and have learned a lot from. Am inspired to trust the process and never give up.

image4c43d6.png

Anna Dane

·

5 days

ago

I must say this is a really amazing post, and for some of my friends who provide Best British Assignment Help, I must recommend this post to them.

Add your comment

Comment