erpnext-syntax-clientscripts

安装

npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-syntax-clientscripts
ERPNext Client Scripts Syntax (EN)
Client Scripts run in the browser and control all UI interactions in ERPNext/Frappe. They are created via
Setup → Client Script
or in custom apps under
public/js/
.
Version
v14/v15/v16 compatible (unless noted otherwise) Quick Reference Basic Structure frappe . ui . form . on ( 'DocType Name' , { // Form-level events setup ( frm ) { } , refresh ( frm ) { } , validate ( frm ) { } , // Field change events fieldname ( frm ) { } } ) ; Most Used Patterns Action Code Set value frm.set_value('field', value) Hide field frm.toggle_display('field', false) Make field mandatory frm.toggle_reqd('field', true) Call server frappe.call({method: 'path.to.method', args: {}}) Prevent save frappe.throw('Error message') Event Selection Which event should I use? One-time setup (queries, defaults)? └── setup Show/hide UI, add buttons? └── refresh Validation before save? └── validate Do something right after save? └── after_save React to field change? └── {fieldname} → See references/events.md for complete event list and execution order. Essential Methods Value Manipulation // Set single value (async, returns Promise) frm . set_value ( 'status' , 'Approved' ) ; // Set multiple values at once frm . set_value ( { status : 'Approved' , priority : 'High' } ) ; // Get value let value = frm . doc . fieldname ; Field Properties // Show/hide frm . toggle_display ( 'priority' , condition ) ; // Make mandatory frm . toggle_reqd ( 'due_date' , true ) ; // Make read-only frm . toggle_enable ( 'amount' , false ) ; // Advanced property change frm . set_df_property ( 'status' , 'options' , [ 'New' , 'Open' , 'Closed' ] ) ; frm . set_df_property ( 'amount' , 'read_only' , 1 ) ; Link Field Filters // Simple filter frm . set_query ( 'customer' , ( ) => ( { filters : { disabled : 0 } } ) ) ; // Filter in child table frm . set_query ( 'item_code' , 'items' , ( doc , cdt , cdn ) => ( { filters : { is_sales_item : 1 } } ) ) ; → See references/methods.md for complete method signatures. Server Communication frappe.call (Whitelisted Methods) frappe . call ( { method : 'myapp.api.process_data' , args : { customer : frm . doc . customer } , freeze : true , freeze_message : __ ( 'Processing...' ) , callback : ( r ) => { if ( r . message ) { frm . set_value ( 'result' , r . message ) ; } } } ) ; frm.call (Document Methods) // Calls method on document controller frm . call ( 'calculate_taxes' , { include_shipping : true } ) . then ( r => frm . reload_doc ( ) ) ; Async/Await Pattern async function fetchData ( frm ) { let r = await frappe . call ( { method : 'frappe.client.get_value' , args : { doctype : 'Customer' , filters : { name : frm . doc . customer } , fieldname : 'credit_limit' } } ) ; return r . message . credit_limit ; } Child Table Handling Adding Rows let row = frm . add_child ( 'items' , { item_code : 'ITEM-001' , qty : 5 , rate : 100 } ) ; frm . refresh_field ( 'items' ) ; // REQUIRED after modification Editing Rows frm . doc . items . forEach ( ( row ) => { if ( row . qty

10 ) { row . discount_percentage = 5 ; } } ) ; frm . refresh_field ( 'items' ) ; Child Table Events frappe . ui . form . on ( 'Sales Invoice Item' , { qty ( frm , cdt , cdn ) { let row = frappe . get_doc ( cdt , cdn ) ; frappe . model . set_value ( cdt , cdn , 'amount' , row . qty * row . rate ) ; } , items_add ( frm , cdt , cdn ) { // New row added } , items_remove ( frm ) { // Row removed } } ) ; → See references/examples.md for complete child table examples. Custom Buttons frappe . ui . form . on ( 'Sales Order' , { refresh ( frm ) { if ( frm . doc . docstatus === 1 ) { // Grouped buttons frm . add_custom_button ( __ ( 'Invoice' ) , ( ) => { // action } , __ ( 'Create' ) ) ; // Primary action frm . page . set_primary_action ( __ ( 'Process' ) , ( ) => { frm . call ( 'process' ) . then ( ( ) => frm . reload_doc ( ) ) ; } ) ; } } } ) ; Critical Rules ALWAYS call frm.refresh_field('table') after child table modifications NEVER use frm.doc.field = value — use frm.set_value() ALWAYS use __('text') for translatable strings validate event: use frappe.throw() to prevent save setup event: only for one-time configuration (not repeated) → See references/anti-patterns.md for common mistakes.

返回排行榜