---
title: "Client Scripts"
space: "Frappe Framework"
url: "https://www.prilk.com/docs/frappe-framework/client-scripts"
updated: "2026-05-14"
---

## Client Scripts

A Client Script runs JavaScript in the user's browser when a DocType form is open. Use for:

- Show/hide fields based on values
- Compute derived fields client-side
- Add custom action buttons
- Validate input before save

For most use cases, Client Scripts are the right tool — fast, no page reload, immediate feedback.

### Creating one
**Customize → Client Script → New**: pick the DocType, view (Form/List), and paste your JS.

### Form events

```javascript
frappe.ui.form.on("Sales Invoice", {
    refresh(frm) {
        // Runs every time the form loads/reloads
        if (frm.doc.status === "Paid") {
            frm.add_custom_button("Print Receipt", () => {
                window.open(`/api/method/erpnext.print_receipt?invoice=${frm.doc.name}`);
            });
        }
    },
    customer(frm) {
        // Triggers when the customer field changes
        frappe.msgprint(`Selected: ${frm.doc.customer}`);
    },
    validate(frm) {
        // Runs before save
        if (frm.doc.grand_total > 100000) {
            frappe.throw("Invoices over 100k require manager approval");
        }
    }
});
```

### Child table events

```javascript
frappe.ui.form.on("Sales Invoice Item", {
    qty(frm, cdt, cdn) {
        const row = locals[cdt][cdn];
        frappe.model.set_value(cdt, cdn, "amount", row.qty * row.rate);
    }
});
```

### Calling the server

```javascript
frappe.call({
    method: "myapp.api.check_credit_limit",
    args: { customer: frm.doc.customer, amount: frm.doc.grand_total },
    callback: (r) => {
        if (!r.message.ok) frappe.throw("Over credit limit");
    }
});
```

### Limits
- Runs in the user's browser — never trust input here for security. Always re-validate on server in a Server Script or whitelisted method.
- Errors fail silently unless you check the browser console. Add `console.error()` while iterating.

For server-side enforcement, see [Server Scripts](/docs/frappe-ecosystem/server-scripts).
