公共工具API

frappe.get_route

frappe.get_route()

将当前路由以数组形式返回。

frappe.get_route()
// ["List", "Task", "List"]

frappe.set_route

frappe.set_route(route)

将当前路由更改为 route

// route in parts
frappe.set_route('List', 'Task', 'List')

// route as array
frappe.set_route(['List', 'Task', 'Gantt'])

// route as string
frappe.set_route('List/Event/Calendar')

// route with options
frappe.set_route(['List', 'Task', 'Task'], { status: 'Open' })

frappe.format

frappe.format(value, df, options, doc)

将原始值格式化为用户可读的展示格式。

frappe.format('2019-09-08', { fieldtype: 'Date' })
// "09-08-2019"

frappe.format('2399', { fieldtype: 'Currency', options: 'currency' }, { inline: true })
// "2,399.00"

frappe.provide

frappe.provide(namespace)

如果 window 对象上不存在该命名空间,则创建并挂载到 window 对象上。

frappe.provide('frappe.ui.form');

// has the same effect as
window.frappe = {}
window.frappe.ui = {}
window.frappe.ui.form = {}

frappe.require

frappe.require(asset_path, callback)

异步加载 JS 或 CSS 资源。用于加载不常用的库。

// load a single asset
frappe.require('/assets/frappe/chat.js', () => {
 // chat.js is loaded
})

// load multiple assets
frappe.require(['/assets/frappe/chat.js', '/assets/frappe/chat.css'], () => {
 // chat.js and chat.css are loaded
})

树形视图是为所有启用了“是树形”属性的 DocType 生成的。


树形视图

标准树形 JS

要自定义树形视图,你必须在 doctype 目录中有一个 {doctype}_tree.js 文件。
以下是所有可以自定义的选项。

例如,如果你想配置 Account DocType,你需要创建一个包含以下内容的 account_tree.js 文件。

frappe.treeview_settings["Account"] = {
    breadcrumb: "Accounting",
    title: "Chart of Accounts",

    filters: [
        {
            fieldname: "company",
            fieldtype: "Select",
            label: "Company",
            options: "Company 1\nCompany 2",
            on_change: handle_company_change(),
        },
    ],

    get_tree_nodes: "path.to.whitelisted_method.get_children",
    add_tree_node: "path.to.whitelisted_method.handle_add_account",

    fields: [
        {
            fieldtype: "Data",
            fieldname: "account_name",
            label: "New Account Name",
            reqd: true,
        },
        {
            fieldtype: "Link",
            fieldname: "account_currency",
            label: "Currency",
            options: "Currency",
        },
        {
            fieldtype: "Check",
            fieldname: "is_group",
            label: "Is Group",
        },
    ],

    ignore_fields: ["parent_account"],

    menu_items: [
        {
            label: "New Company",
            action: function () {
                frappe.new_doc("Company", true);
            },
            condition: "frappe.boot.user.can_create.indexOf('Company') !== -1",
        },
    ],

    onload: function (treeview) {},

    post_render: function (treeview) {},

    onrender: function (node) {},

    on_get_node: function (nodes) {},

    extend_toolbar: true,

    toolbar: [
        {
            label: "Add Child",
            condition: function (node) {
                return node && node.is_group;
            },
            click: function (node) {
                frappe.treeview_settings["Account"].add_node(node);
            },
            btnClass: "hidden-xs",
        },
    ],
};

页面接口

Desk 中的每个屏幕都渲染在一个 frappe.ui.Page 对象内。

frappe.ui.make_app_page

创建一个新的页面并将其附加到父级。

let page = frappe.ui.make_app_page({
    title: 'My Page',
    parent: wrapper // HTML DOM Element or jQuery object
    single_column: true // create a page without sidebar
})

新建页面

页面方法

本节列出了页面实例对象上可用的常用方法。

page.set_title

设置页面标题以及文档标题。文档标题显示在浏览器标签页中。

page.set_title('My Page')

页面标题

page.set_title_sub

设置页面的副标题。它显示在页面标题的右侧。

page.set_title_sub('Subtitle')

页面副标题

page.set_indicator

设置指示器的标签和颜色。

page.set_indicator('Pending', 'orange')

页面指示器

page.clear_indicator

清除指示器的标签和颜色。

page.clear_indicator()

page.set_primary_action

设置主要操作按钮的标签和处理函数。第三个参数是图标类,将在移动视图中显示。

let $btn = page.set_primary_action('New', () => create_new(), 'octicon octicon-plus')

页面主要操作

page.clear_primary_action

清除主要操作按钮和处理函数。

page.clear_primary_action()

page.set_secondary_action

设置次要操作按钮的标签和处理函数。第三个参数是图标类,将在移动视图中显示。

let $btn = page.set_secondary_action('Refresh', () => refresh(), 'octicon octicon-sync')

页面次要操作

page.clear_secondary_action

清除次要操作按钮和处理函数。

page.clear_secondary_action()

page.add_menu_item

在菜单下拉框中添加菜单项。

// add a normal menu item
page.add_menu_item('Send Email', () => open_email_dialog())

// add a standard menu item
page.add_menu_item('Send Email', () => open_email_dialog(), true)

页面菜单下拉框

page.clear_menu

移除包含菜单项的下拉菜单。

page.clear_menu()

page.add_action_item

在操作下拉框中添加菜单项。

// add a normal menu item
page.add_action_item('Delete', () => delete_items())

页面操作下拉框

page.clear_actions_menu

移除包含菜单项的操作下拉菜单。

page.clear_actions_menu()

page.add_inner_button

在内部工具栏中添加按钮。

// add a normal inner button
page.add_inner_button('Update Posts', () => update_posts())

页面内部按钮

// add a dropdown button in a group
page.add_inner_button('New Post', () => new_post(), 'Make')

页面内部按钮组

page.change_custombuttontype

通过标签(和组)更改特定自定义按钮的类型。

// change type of ungrouped button
page.change_inner_button_type('Update Posts', null, 'primary');

// change type of a button in a group
page.change_inner_button_type('Delete Posts', 'Actions', 'danger');

page.remove_inner_button

移除内部工具栏中的按钮。

// remove inner button
page.remove_inner_button('Update Posts')

// remove dropdown button in a group
page.remove_inner_button('New Posts', 'Make')

page.clear_inner_toolbar

移除内部工具栏。

page.clear_inner_toolbar()

page.add_field

在页面表单工具栏中添加一个表单控件。

let field = page.add_field({
    label: 'Status',
    fieldtype: 'Select',
    fieldname: 'status',
    options: [
        'Open',
        'Closed',
        'Cancelled'
    ],
    change() {
        console.log(field.get_value());
    }
});

页面表单工具栏

page.get_form_values

以对象形式获取页面表单工具栏中的所有表单值。

let values = page.get_form_values()
// { status: 'Open', priority: 'Low' }

page.clear_fields

清除页面表单工具栏中的所有字段。

page.clear_fields()

列表

列表视图是为除子表和单文档类型之外的所有文档类型生成的。

列表视图功能丰富,其中一些功能包括:

  • 筛选
  • 排序
  • 分页
  • 按标签筛选
  • 切换视图为报表、日历、甘特图、看板等。

列表视图

标准列表 JS

要自定义列表视图,您必须在文档类型目录中有一个 {doctype}_list.js 文件。以下是所有可以自定义的选项。

例如,如果您想自定义 Note 文档类型,您需要创建一个包含以下内容的 note_list.js 文件。

frappe.listview_settings['Note'] = {
    // add fields to fetch
    add_fields: ['title', 'public'],
    // set default filters
    filters: [
        ['public', '=', 1]
    ],
    hide_name_column: true, // hide the last column which shows the `name`
    hide_name_filter: true, // hide the default filter field for the name column
    onload(listview) {
        // triggers once before the list is loaded
    },
    before_render() {
        // triggers before every render of list records
    },

    // set this to true to apply indicator function on draft documents too
    has_indicator_for_draft: false,

    get_indicator(doc) {
        // customize indicator color
        if (doc.public) {
            return [__("Public"), "green", "public,=,Yes"];
        } else {
            return [__("Private"), "darkgrey", "public,=,No"];
        }
    },
    primary_action() {
        // triggers when the primary action is clicked
    },
    get_form_link(doc) {
        // override the form route for this doc
    },
    // add a custom button for each row
    button: {
        show(doc) {
            return doc.reference_name;
        },
        get_label() {
            return 'View';
        },
        get_description(doc) {
            return __('View {0}', [`${doc.reference_type} ${doc.reference_name}`])
        },
        action(doc) {
            frappe.set_route('Form', doc.reference_type, doc.reference_name);
        }
    },
    // format how a field value is shown
    formatters: {
        title(val) {
            return val.bold();
        },
        public(val) {
            return val ? 'Yes' : 'No';
        }
    }
}

自定义列表 JS

您还可以通过创建系统中的客户端脚本来自定义列表视图。如果逻辑特定于您的站点,您应该编写客户端脚本。如果您想在多个站点之间共享列表视图自定义设置,则必须通过应用程序来包含它们。

要创建新的客户端脚本,请前往

首页 > 自定义 > 客户端脚本 > 新建

用于列表的新客户端脚本

上述自定义将产生如下所示的列表视图:

自定义列表视图

列表 JS 中的多个按钮

此功能在开发版中可用。

您现在可以通过列表视图客户端脚本,在列表视图行中的下拉菜单内添加多个按钮。此功能通过直接从列表视图方便地访问各种操作,增强了用户体验。

frappe.listview_settings["ToDo"] = {
    hide_name_column: true,
    add_fields: ["reference_type", "reference_name"],

    button: {
      show: function(doc) {
        return doc.reference_name;
      },
      get_label: function() {
        return __("Open", null, "Access");
      },
      get_description: function(doc) {
        return __("Open {0}", [
          `${__(doc.reference_type)}: ${doc.reference_name}`
        ]);
      },
      action: function(doc) {
        frappe.set_route("Form", doc.reference_type, doc
          .reference_name);
      },
    },
    dropdown_button: {
      get_label: __("Dropdown"),
      buttons: [{
          get_label: __("Button 1"),
          show: function(doc) {
            return true;
          },
          get_description: function(doc) {
            return "Open Button 1 " + doc.reference_name;
          },
          action: function(doc) {
            frappe.msgprint("Dropdown Button 1 Clicked " +
              doc.reference_name);
          }
        },
        {
          get_label: __("Button 2"),
          show: function(doc) {
            return doc.status != "Closed";
          },
          get_description: function(doc) {
            return "Open Button 2 " + doc.reference_name;
          },
          action: function(doc) {
            frappe.msgprint("Dropdown Button 2 Clicked " +
              doc.reference_name);
          }
        },
        {
          get_label: __("Button 3"),
          show: function(doc) {
            return doc.status != "Cancelled";
          },
          get_description: function(doc) {
            return "Open Button 3 " + doc.reference_name;
          },
          action: function(doc) {
            frappe.msgprint("Dropdown Button 3 Clicked " +
              doc.reference_name);
          }
        },
      ]
    }
  };

控件

frappe.ui.form.make_control

frappe.ui.form.make_control({ parent, df })

根据 df 属性创建一个 frappe 控件,并将其追加到 parent
容器中。

frappe.ui.form.make_control({
 parent: $wrapper.find('.my-control'),
 df: {
 label: 'Due Date',
 fieldname: 'due_date',
 fieldtype: 'Date'
 },
 render_input: true
})

以下是大多数 frappe 控件类型的 df 属性。

// Attach
{
 label: 'Attachment',
 fieldname: 'attachment',
 fieldtype: 'Attach'
}

// Attach Image
{
 label: 'User Image',
 fieldname: 'user_image',
 fieldtype: 'Attach Image'
}

// Autocomplete
{
 label: 'Select User',
 label: 'user',
 fieldtype: 'Autocomplete',
 options: [
 '[email protected]',
 '[email protected]'
 ]
}

// Barcode
{
 label: 'Item Barcode',
 fieldname: 'item_barcode',
 fieldtype: 'Barcode'
}

// Check
{
 label: 'Enable feature',
 fieldname: 'enable_feature',
 fieldtype: 'Check'
}

// Code
{
 label: 'JS Script',
 fieldname: 'script',
 fieldtype: 'Code',
 // for syntax highlighting
 options: 'Javascript' // JS, HTML, CSS, Markdown, SCSS, JSON,
 // wrap code
 wrap: true,
 // changing `max_lines` will set the max-height of the editor
 max_lines: 10,
 // changing `min_lines` will set the min-height of the editor
 min_lines: 5
}

// Color
{
 label: 'Your favorite color',
 fieldname: 'user_color',
 fieldtype: 'Color'
}

// Currency
{
 label: 'Amount',
 fieldname: 'amount',
 fieldtype: 'Currency',
 options: 'INR' // or name of field which holds currency
}

// Data
{
 label: 'First Name',
 fieldname: 'first_name',
 fieldtype: 'Data',
 options: 'Email' // 'Name', 'Phone', 'URL', 'Barcode'
}

// Date Range
{
 label: 'Select Date Range',
 fieldname: 'date_range',
 fieldtype: 'Date Range'
}

// Date
{
 label: 'Birth Date',
 fieldname: 'birth_date',
 fieldtype: 'Date'
}

// Datetime
{
 label: 'Submission Date and Time',
 fieldname: 'submission',
 fieldtype: 'Datetime'
}

// Dynamic Link
{
 label: 'Party',
 fieldname: 'party',
 fieldtype: 'Dynamic Link',
 options: 'party_type' // fieldname which holds the Link type
}

// Float
{
 label: 'Threshold',
 fieldname: 'threshold',
 fieldtype: 'Float'
}

// Geolocation
{
 label: 'Meeting Place',
 fieldname: 'meeting_place',
 fieldtype: 'Geolocation'
}

// HTML Editor
{
 label: 'Custom HTML',
 fieldname: 'custom_html',
 fieldtype: 'HTML Editor'
}

// Int
{
 label: 'No of days',
 fieldname: 'no_of_days',
 fieldtype: 'Int'
}

// Link
{
 label: 'Select User',
 fieldname: 'user',
 fieldtype: 'Link',
 options: 'User' // name of doctype
}

// Markdown Editor
{
 label: 'Blog Content',
 fieldname: 'content',
 fieldtype: 'Markdown Editor'
}

// MultiCheck
{
 label: 'Blog Content',
 fieldname: 'content',
 fieldtype: 'MultiCheck',
 options: [
 'Option 1',
 'Option 2',
 'Option 3',
 'Option 4',
 ],
 columns: 2 // break into 2 columns
}

// MultiSelect
{
 label: 'Select Users',
 fieldname: 'users',
 fieldtype: 'MultiSelect',
 options: [
 '[email protected]',
 '[email protected]',
 '[email protected]'
 ]
}

// Password
{
 label: 'New Password',
 fieldname: 'password',
 fieldtype: 'Password'
}

// Rating
{
 label: 'Rate your experience',
 fieldname: 'rating',
 fieldtype: 'Rating'
}

// Select
{
 label: 'Status',
 fieldname: 'status',
 fieldtype: 'Select',
 options: [
 'Open',
 'Closed',
 'Cancelled'
 ]
}

// Signature
{
 label: 'Status',
 fieldname: 'status',
 fieldtype: 'Signature'
}

// Text Editor
{
 label: 'Description',
 fieldname: 'description',
 fieldtype: 'Text Editor'
}

// Time
{
 label: 'In Time',
 fieldname: 'in_time',
 fieldtype: 'Time'
}

// Button
{
 label: 'Fetch',
 fieldname: 'fetch',
 fieldtype: 'Button',
 btn_size: 'xs' // xs, sm, lg
}

//Icon
{
 label: 'Page Icon',
 fieldname: 'page_icon',
 fieldtype: 'Icon'
}

添加自定义格式化器

您可以通过将自定义格式化器添加到 frappe.meta.docfield_map 中的 docfield 对象,为文本类型对象(如 Data、Select、Text 等)添加自定义格式化器。

示例:

frappe.meta.docfield_map['DocField'].fieldtype.formatter = (value) => {
 if (value==='Section Break') return '🔵 Section Break';
 else return value;
}

表单脚本

表单脚本(Form Scripts)允许您为表单添加客户端逻辑。您可以编写表单脚本来自动获取值、添加验证或为表单添加上下文操作。

标准表单脚本

当您创建新的 DocType 时,系统会生成一个 {doctype}.js,您可以在其中编写表单脚本。

语法:

frappe.ui.form.on(doctype, {
    event1() {
        // handle event 1
    },
    event2() {
        // handle event 2
    }
})

例如,位于 frappe/desk/doctype/todo/todo.jstodo.js 可能如下所示:

// Script for ToDo Form
frappe.ui.form.on('ToDo', {
    // on refresh event
    refresh(frm) {
        // if reference_type and reference_name are set,
        // add a custom button to go to the reference form
        if (frm.doc.reference_type && frm.doc.reference_name) {
            frm.add_custom_button(__(frm.doc.reference_name), () => {
                frappe.set_route("Form", frm.doc.reference_type, frm.doc.reference_name);
            });
        }
    }
})

子表脚本

子表脚本应与其父表脚本写在同一个文件中。

frappe.ui.form.on('Quotation', {
    // ...
})

frappe.ui.form.on('Quotation Item', {
    // cdt is Child DocType name i.e Quotation Item
    // cdn is the row name for e.g bbfcb8da6a
    item_code(frm, cdt, cdn) {
        let row = frappe.get_doc(cdt, cdn);
    }
})

自定义表单脚本

您还可以通过在系统中创建客户端脚本(Client Script)来编写表单脚本。如果逻辑是针对您特定站点的,则应编写客户端脚本。如果您希望跨站点共享表单脚本,则必须通过应用(Apps)来包含它们。

要创建新的客户端脚本,请前往

首页 > 自定义 > 客户端脚本 > 新建

新建表单客户端脚本

表单事件

表单脚本依赖事件来触发。以下是表单触发的所有表单事件的列表。

这些事件的处理函数会将 frm 作为第一个参数接收。

frappe.ui.form.on('ToDo', {
    // frm passed as the first parameter
    setup(frm) {
        // write setup code
    }
})
事件名称 描述
setup 当表单首次创建时触发一次
before_load 在表单即将加载之前触发
onload 当表单已加载并即将渲染时触发
refresh 当表单已加载并渲染完成时触发。
onload_post_render 在表单加载并渲染完成后触发
validate 在 before_save 之前触发
before_save 在调用保存之前触发
after_save 在表单保存后触发
before_submit 在调用提交之前触发
on_submit 在表单提交后触发
before_cancel 在调用取消之前触发
after_cancel 在表单取消后触发
before_discard 在调用放弃之前触发
after_discard 在表单被放弃后触发
timeline_refresh 在表单时间线渲染后触发
{fieldname}_on_form_rendered 当表格字段中的某行作为表单打开时触发
{fieldname} 当字段名的值发生变化时触发
get_email_recipient_filters 由电子邮件对话框调用,用于获取电子邮件收件人的默认筛选条件。应接受两个参数 frm(当前表单)和 field(”recipients”、”cc” 或 “bcc”),并返回一个数组或字典形式的筛选条件(与联系人(Contact) DocType 相关)。
get_email_recipients 由电子邮件对话框调用,用于获取默认收件人。应接受两个参数 frm(当前表单)和 field(”recipients”、”cc” 或 “bcc”),并返回该字段的电子邮件地址列表。

子表事件

这些事件在子表的上下文中触发。因此,除了 frm 之外,它们的处理函数还会接收 cdt(子 DocType)和 cdn(子 Docname)参数。

假设我们的“待办事项(ToDo)”DocType 有一个名为“链接(links)”的字段,其中包含一个子表。该子表在名为“动态链接(Dynamic Link)”的 DocType 中定义。我们希望每当向该表添加一行时都运行我们的代码。

// this code is located inside `todo.js`

frappe.ui.form.on('Dynamic Link', { // The child table is defined in a DoctType called "Dynamic Link"
    links_add(frm, cdt, cdn) { // "links" is the name of the table field in ToDo, "_add" is the event
        // frm: current ToDo form
        // cdt: child DocType 'Dynamic Link'
        // cdn: child docname (something like 'a6dfk76')
        // cdt and cdn are useful for identifying which row triggered this event

        frappe.msgprint('A row has been added to the links table 🎉 ');
    }
});
事件名称 描述
before_{fieldname}_remove 当一行即将从表格字段中移除时触发
{fieldname}_add 当向表格字段添加一行时触发
{fieldname}_remove 当从表格字段中移除一行时触发
{fieldname}_move 当一行在表格字段中被重新排序到其他位置时触发
form_render 当表格字段中的某行作为表单打开时触发

注意:上表列出的前三个事件,即 before_{fieldname}_remove{fieldname}_add{fieldname}_remove,也会针对字段类型为表格多选(Table MultiSelect)的字段触发。(自版本 16 起)

表单 API

以下是 frm 对象上可用的一些常用方法列表。

frm.set_value

设置字段的值。这将触发表单中的字段更改事件。

// set a single value
frm.set_value('description', 'New description')

// set multiple values at once
frm.set_value({
    status: 'Open',
    description: 'New description'
})

// returns a promise
frm.set_value('description', 'New description')
    .then(() => {
        // do something after value is set
    })

frm.refresh

使用服务器上的最新值刷新表单。将触发 before_loadonloadrefreshtimeline_refreshonload_post_render

frm.refresh();

frm.save

触发表单保存。将触发 validatebefore_saveafter_savetimeline_refreshrefresh

它可以用来触发其他保存操作,如提交、取消和更新。在这种情况下,相关事件将被触发。

// save form
frm.save();

// submit form
frm.save('Submit');

// cancel form
frm.save('Cancel');

// update form (after submit)
frm.save('Update');

// all methods returns a promise

frm.enable_save / frm.disable_save

用于启用/禁用表单中“保存”按钮的方法。

if (frappe.user_roles.includes('Custom Role')) {
    frm.enable_save();
} else {
    frm.disable_save();
}

frm.email_doc

打开此表单的电子邮件对话框。

// open email dialog
frm.email_doc();

// open email dialog with some message
frm.email_doc(`Hello ${frm.doc.customer_name}`);

frm.reload_doc

使用服务器上的最新值重新加载文档,并调用 frm.refresh()

frm.reload_doc();

frm.refresh_field

刷新字段及其依赖项。

frm.refresh_field('description');

frm.is_dirty

检查表单值是否已更改且尚未保存。

if (frm.is_dirty()) {
    frappe.show_alert('Please save form before attaching a file')
}

frm.dirty

将表单设置为“脏”状态。这用于在文档值更改时将表单标记为脏状态。这会触发表单视图中的“未保存”指示器。

frm.doc.browser_data = navigator.appVersion;
frm.dirty();
frm.save();

在不将表单设置为脏状态的情况下调用保存,将触发“文档无更改”的提示消息。

frm.is_new

检查表单是否为新建且尚未保存。

// add custom button only if form is not new
if (!frm.is_new()) {
    frm.add_custom_button('Click me', () => console.log('Clicked custom button'))
}

frm.set_intro

在表单顶部设置介绍文本。该函数接受两个参数:message(字符串,必填)和 color(字符串,可选)。

颜色可以是“蓝色”、“红色”、“橙色”、“绿色”或“黄色”。默认是蓝色。

if (!frm.doc.description) {
    frm.set_intro('Please set the value of description', 'blue');
}

介绍文本示例

frm.add_custom_button

在页面的内部工具栏中添加自定义按钮。是 page.add_inner_button 的别名。

// Custom buttons
frm.add_custom_button('Open Reference form', () => {
    frappe.set_route('Form', frm.doc.reference_type, frm.doc.reference_name);
})

// Custom buttons in groups
frm.add_custom_button('Closed', () => {
    frm.doc.status = 'Closed'
}, 'Set Status');

frm.change_custom_button_type

通过标签(和组)更改特定自定义按钮的类型。

// change type of ungrouped button
frm.change_custom_button_type('Open Reference form', null, 'primary');

// change type of a button in a group
frm.change_custom_button_type('Closed', 'Set Status', 'danger');

frm.remove_custom_button

通过标签(和组)移除特定的自定义按钮。

// remove custom button
frm.remove_custom_button('Open Reference form');

// remove custom button in a group
frm.remove_custom_button('Closed', 'Set Status');

frm.clear_custom_buttons

从内部工具栏中移除所有自定义按钮。

frm.clear_custom_buttons();

frm.set_df_property

更改字段的文档字段属性并刷新该字段。

// change the fieldtype of description field to Text
frm.set_df_property('description', 'fieldtype', 'Text');

// set the options of the status field to only be [Open, Closed]
frm.set_df_property('status', 'options', ['Open', 'Closed'])

// set a field as mandatory
frm.set_df_property('title', 'reqd', 1)

// set a field as read only
frm.set_df_property('status', 'read_only', 1)

frm.toggle_enable

根据条件将字段或字段列表切换为 read_only 状态。

// set status and priority as read_only
// if user does not have System Manager role
let is_allowed = frappe.user_roles.includes('System Manager');
frm.toggle_enable(['status', 'priority'], is_allowed);

frm.toggle_reqd

根据条件将字段或字段列表切换为必填(reqd)状态。

// set priority as mandatory
// if status is Open
frm.toggle_reqd('priority', frm.doc.status === 'Open');

frm.toggle_display

根据条件显示/隐藏字段或字段列表。

// show priority and due_date field
// if status is Open
frm.toggle_display(['priority', 'due_date'], frm.doc.status === 'Open');

frm.set_query

对链接字段应用过滤器,以显示有限的记录供选择。您必须在表单生命周期的早期调用 frm.set_query,通常是在 setuponload 中。

// show only customers whose territory is set to India
frm.set_query('customer', () => {
    return {
        filters: {
            territory: 'India'
        }
    }
})

// show customers whose territory is any of India, Nepal, Japan
frm.set_query('customer', () => {
    return {
        filters: {
            territory: ['in', ['India', 'Nepal', 'Japan']]
        }
    }
})

// set filters for Link field item_code in
// items field which is a Child Table
frm.set_query('item_code', 'items', () => {
    return {
        filters: {
            item_group: 'Products'
        }
    }
})

您还可以覆盖过滤方法,并在服务器端提供自己的自定义方法。只需将查询设置为您的 Python 方法的模块路径即可。

// change the filter method by passing a custom method
frm.set_query('fieldname', () => {
    return {
        query: 'dotted.path.to.custom.custom_query',
        filters: {
            field1: 'value1'
        }
    }
})
# python method signature
def custom_query(doctype, txt, searchfield, start, page_len, filters):
    # your logic
    return filtered_list

frm.add_child

向表格字段添加一行带值的记录。

let row = frm.add_child('items', {
    item_code: 'Tennis Racket',
    qty: 2
});

frm.refresh_field('items');

frm.call

使用参数调用服务器端的控制器方法。

注意: 在使用 frm.call() 访问任何服务器端方法时,您需要使用 @frappe.whitelist 装饰器将该方法列入白名单。

对于以下控制器代码:

class ToDo(Document):
    @frappe.whitelist()
    def get_linked_doc(self, throw_if_missing=False):
        if not frappe.db.exists(self.reference_type, self.reference_name):
            if throw_if_missing:
                frappe.throw('Linked document not found')

        return frappe.get_doc(self.reference_type, self.reference_name)

您可以使用 frm.call 从客户端调用它。

frm.call('get_linked_doc', { throw_if_missing: true })
    .then(r => {
        if (r.message) {
            let linked_doc = r.message;
            // do something with linked_doc
        }
    })

frm.trigger

显式触发任何表单事件。

frappe.ui.form.on('ToDo', {
    refresh(frm) {
        frm.trigger('set_mandatory_fields');
    },

    set_mandatory_fields(frm) {
        frm.toggle_reqd('priority', frm.doc.status === 'Open');
    }
})

frm.get_selected

在子表中获取选中的行,返回一个对象,其中键是表格字段名,值是行名称。

let selected = frm.get_selected()
console.log(selected)
// {
// items: ["bbfcb8da6a", "b1f1a43233"]
// taxes: ["036ab9452a"]
// }

frm.ignore_doctypes_on_cancel_all

为避免在全部取消期间取消链接文档,您需要将 frm.ignored_doctypes_on_cancel_all 属性设置为链接文档的 DocTypes 数组。

frappe.ui.form.on("DocType 1", {
    onload: function(frm) {
        // Ignore cancellation for all linked documents of respective DocTypes.
        frm.ignore_doctypes_on_cancel_all = ["DocType 2", "DocType 3"];
    }
}

在上述示例中,系统将在取消期间避免取消所有与“DocType 1”文档链接的“DocType 2”和“DocType 3”文档。

开发者API

Python

Frappe 旨在为其用户实现最低的认知负担。因此,你可以在
frappe 命名空间本身中找到最常用的方法和工具。在 Python 文件中,
这(大多数情况下)是你唯一需要的导入。

  1. 文档
  2. 数据库
  3. Jinja 模板
  4. 常用工具
  5. 路由器
  6. 响应
  7. 语言解析
  8. 搜索
  9. 钩子
  10. REST API
  11. 全文搜索
  12. 对话框 API
  13. 查询构建器

Javascript

Frappe 将自身挂载到 window 对象下的 frappe 命名空间中。你
可以在 frappe 对象下找到大部分客户端 API。所有这些方法
仅在 Desk 环境中可用。探索这些 API 的一个好方法是从
浏览器控制台入手。

  1. 表单
  2. 控件
  3. 页面
  4. 树形视图
  5. 服务器调用 (AJAX)
  6. 常用工具
  7. 对话框 API
  8. 图表 API
  9. 扫描器 API

其他

  1. REST API
  2. Jinja API