对话框API

Frappe 提供了一组标准、交互式且灵活的对话框,它们易于配置和使用。同时也有一个针对 Python 的 API。

frappe.ui.Dialog

new frappe.ui.Dialog({ title, fields, primary_action })

创建一个新的 Dialog 实例。

let d = new frappe.ui.Dialog({
    title: 'Enter details',
    fields: [
        {
            label: 'First Name',
            fieldname: 'first_name',
            fieldtype: 'Data'
        },
        {
            label: 'Last Name',
            fieldname: 'last_name',
            fieldtype: 'Data'
        },
        {
            label: 'Age',
            fieldname: 'age',
            fieldtype: 'Int'
        }
    ],
    size: 'small', // small, large, extra-large 
    primary_action_label: 'Submit',
    primary_action(values) {
        console.log(values);
        d.hide();
    }
});

d.show();

frappe.ui.Dialog

frappe.msgprint

frappe.msgprint(message)frappe.msgprint({ title, message, indicator })

在模态框中显示 message

// only message
frappe.msgprint(__('Document updated successfully'));

// with options
frappe.msgprint({
    title: __('Notification'),
    indicator: 'green',
    message: __('Document updated successfully')
});

frappe.msgprint

你也可以通过在 primary_action 中传递 action(作为一个方法)来为此对话框绑定一个主要操作。或者,primary_action 可以包含 server_action client_action

server_actionclient_action 是指向相应方法的点分路径,这些方法将在点击主要按钮时执行。

// with primary action
 frappe.msgprint({
    title: __('Notification'),
    message: __('Are you sure you want to proceed?'),
    primary_action:{
        action(values) {
            console.log(values);
        }
    }
});

// with server and client action
frappe.msgprint({
    title: __('Notification'),
    message: __('Are you sure you want to proceed?'),
    primary_action: {
    'label': 'Proceed',
    // either one of the actions can be passed
    'server_action': 'dotted.path.to.method',
    'client_action': 'dotted_path.to_method',
    'args': args
    }
});

绑定了主要操作的 frappe.msgprint

frappe.throw

frappe.throw(error_message)

在模态框中显示 error_message 并抛出 throw 异常。

frappe.throw(__('This is an Error Message'))

frappe.throw

frappe.prompt

frappe.prompt(label)frappe.prompt(df)frappe.prompt(fields)

提示用户输入一个值或一组值。

// prompt for single value of type Data
frappe.prompt('First Name', ({ value }) => console.log(value))

// Set title and button label
frappe.prompt('First Name', console.log, 'Enter First Name', 'Submit');

// prompt for single value of any type
frappe.prompt({
    label: 'Birth Date',
    fieldname: 'date',
    fieldtype: 'Date'
}, (values) => {
    console.log(values.date);
})

// prompt for multiple values
frappe.prompt([
    {
        label: 'First Name',
        fieldname: 'first_name',
        fieldtype: 'Data'
    },
    {
        label: 'Last Name',
        fieldname: 'last_name',
        fieldtype: 'Data'
    },
], (values) => {
    console.log(values.first_name, values.last_name);
})

frappe.prompt

frappe.confirm

frappe.confirm(message, if_yes, if_no)

显示一个确认模态框,如果确认则执行 if_yes,否则执行 if_no

frappe.confirm('Are you sure you want to proceed?',
    () => {
        // action to perform if Yes is selected
    }, () => {
        // action to perform if No is selected
    })

frappe.confirm

frappe.warn

frappe.warn(title, message_html, proceed_action, primary_label, is_minimizable)

显示一个警告模态框,如果确认则执行 proceed_actiion。它可以设置为 minimizable,这允许对话框被最小化。

frappe.warn('Are you sure you want to proceed?',
    'There are unsaved changes on this page',
    () => {
        // action to perform if Continue is selected
    },
    'Continue',
    true // Sets dialog as minimizable
)

frappe.confirm

frappe.showalert

frappe.show_alert(message, seconds)frappe.show_alert({message, indicator}, seconds)

警报对话框用于显示非阻塞性的消息。

其参数包括 message,它也可以包含指示器颜色,以及它的显示时长。默认是 7 秒

frappe.show_alert('Hi, you have a new message', 5);

//show_alert with indicator
frappe.show_alert({
    message:__('Hi, you have a new message'),
    indicator:'green'
}, 5);

frappe.showalert

frappe.showprogress

frappe.show_progress(title, count, total, description)

显示一个进度条,其中 count(作为当前进度)和 total(作为最大进度值)。

frappe.show_progress('Loading..', 70, 100, 'Please wait');

frappe.showprogress

frappe.newdoc

frappe.new_doc(doctype, route_options, init_callback)

打开指定 DocType 的新表单,允许编辑和保存它。如果为该 DocType 启用了“快速录入”(允许输入最重要的字段),则会显示“快速录入”弹出窗口。否则,你将被重定向到通常的文档录入表单。

例如,让我们创建一个新的 任务

frappe.new_doc("Task");

通常,当你在用户界面中创建新文档时,你可能希望根据触发创建的用户交互来初始化其某些字段。另外两个参数可用于此类初始化。

具体来说,route_options 参数是一种快速便捷的方式,用于设置新文档中任何类型为 Link、Select、Data 或 Dynamic Link 的字段。其值应为一个对象,对象的键是所需的字段名,值则是初始值。

frappe.new_doc("Task", {subject: "New Task"});

如果你需要对无法通过 route_options 完成的新文档进行任何其他初始化,init_callback 可以让你完全控制。它应该是一个带一个参数的函数。如果 doctype 使用“快速录入”表单初始化,则在控制权交还给用户之前,会使用“快速录入”对话框对象调用该回调。否则,在允许用户在标准表单中编辑新文档之前,会使用新文档调用该回调。

frappe.new_doc("Task", {subject: "New Task"},
                doc => {doc.description = "Do what's necessary";});

请注意,subject 是一个类型为“Data”的字段,因此我们可以利用 route_options 参数来设置它。description 是一个类型为“Text Editor”的字段,所以如果我们想初始化它,必须在回调中完成。

举一个稍微复杂一点的例子,下面这个调用创建了一个类型为“Bank Entry”的新 日记账分录,并填充了交易的一方:

frappe.new_doc("Journal Entry", {"voucher_type": "Bank Entry"}, doc => {
    doc.posting_date = frappe.datetime.get_today();
    let row = frappe.model.add_child(doc, "accounts");
    row.account = 'Bank - A';
    row.account_currency = 'USD';
    row.debit_in_account_currency = 100.0;
    row.credit_in_account_currency = 0.0;
});

frappe.ui.form.MultiSelectDialog

new frappe.ui.form.MultiSelectDialog({ doctype, target, setters, date_field, get_query, action })

MultiSelectDialog 由筛选字段和一个多选列表组成。主要按钮将对选中的选项执行传递的 action

默认情况下,搜索词字段和日期范围字段将构成筛选字段。

参数列表包括:

  • doctype:用于获取和显示选择条目的数据源。
  • target:模态框要显示的目标位置。
  • setters:这些将构成筛选字段及其填充值。这些也会转换为选择列表的自定义列。
  • read_only_setters:如果你希望将设置器(筛选器)设为只读,以便用户无法更改筛选器的值,则将这些字段添加到“read_only_setters”中。
  • add_filters_group:一个布尔值,用于在 setters 下方的对话框中添加/移除筛选组。该筛选组与列表视图筛选器相同。
  • date_field:必须传递所考虑 DocType 的 date_field
  • get_query:一个函数,返回 queryfilters 以查询选择列表。可以通过 query 传入自定义的服务器端方法,并且 filters 将被传递给该方法。
  • action:包含要对所选选项执行的主要操作。它接受 selections 作为参数,该参数包含所选选项。
  • columns:自定义查询返回的字段数组,这些字段将成为结果数据表中的列。仅适用于自定义查询(get_query 参数返回一个 query)。
  • 假设我们想要将物料申请获取到对话框中。然后我们可以按以下方式调用 MultiSelectDialog:

    new frappe.ui.form.MultiSelectDialog({
        doctype: "Material Request",
        target: this.cur_frm,
        setters: {
            schedule_date: null,
            status: 'Pending'
        },
        add_filters_group: 1,
        date_field: "transaction_date",
        get_query() {
            return {
                filters: { docstatus: ['!=', 2] }
            }
        },
        action(selections) {
            console.log(selections);
        }
    });
    
    // MultiSelectDialog with custom query method
    let query_args = {
        query:"dotted.path.to.method",
        filters: { docstatus: ["!=", 2], supplier: "John Doe" }
    }
    
    new frappe.ui.form.MultiSelectDialog({
        doctype: "Material Request",
        target: this.cur_frm,
        setters: {
            schedule_date: null,
            status: 'Pending'
        },
        add_filters_group: 1,
        date_field: "transaction_date",
        columns: ["name", "transaction_date", "status"],
        get_query() {
            return query_args;
        },
        action(selections) {
            console.log(selections);
        }
    });
    

    frappe.ui.form.MultiSelectDialog

    这里,所有满足筛选条件的物料申请都会被获取到选择区域中。setter company 会连同其传递的值一起添加到筛选字段中。date_field 将用于从指定的 DocType 中获取和查询日期。

    创建物料申请(或 Make {DocType})次要操作按钮将重定向您到一个新表单,以便向传递的 DocType 中创建新条目。

    现在,如果我们只想从物料申请中选择特定项目,则可以使用可选的 child_selection_mode 来启用子项选择。

    
    // MultiSelectDialog for individual child selection
    new frappe.ui.form.MultiSelectDialog({
        doctype: "Material Request",
        target: this.cur_frm,
        setters: {
            schedule_date: null,
            status: null
        },
        add_filters_group: 1,
        date_field: "transaction_date",
        allow_child_item_selection: 1,
        child_fieldname: "items", // child table fieldname, whose records will be shown & can be filtered
        child_columns: ["item_code", "qty"], // child item columns to be displayed
        get_query() {
            return {
                filters: { docstatus: ['!=', 2] }
            }
        },
        action(selections, args) {
            console.log(args.filtered_children); // list of selected item names
        }
    });
    

    frappe.ui.form.MultiSelectDialog

    在这里,您会看到一个复选框 选择单个项目,用于在子项选择与父项选择之间切换。一旦切换,所有查询到的物料申请中的各个物料申请项目都会被列出,您现在可以筛选这些项目以进行选择。

    要访问选中的子项,您可以使用 args.filtered_children 列表,其中包含选中的子项名称。

    对话框中的表格/网格

    可以向对话框中添加表格,就像添加任何其他字段一样,如下所示:

    const dialog = new frappe.ui.Dialog({
      title: __("Create Logs"),
      fields: [
          {
              fieldname: "logs",
              fieldtype: "Table",
              label: __("Logs"),
              in_place_edit: true,
              reqd: 1,
              fields: [
                  {
                      fieldname: "log_type",
                      label: __("Log Type"),
                      fieldtype: "Select",
                      options: "
    IN
    OUT",
                      in_list_view: 1,
                      reqd: 1,
                  },
                  {
                      fieldname: "time",
                      label: __("Time"),
                      fieldtype: "Time",
                      in_list_view: 1,
                      reqd: 1,
                  }
              ],
              on_add_row: (idx) => {
                // idx = visible idx of the row starting from 1
                // eg. set `log_type` as alternating IN/OUT in the table on row addition
                  let data_id = idx - 1;
                  let logs = dialog.fields_dict.logs;
                  let log_type = (data_id % 2) == 0 ? "IN" : "OUT";
    
                  logs.df.data[data_id].log_type = log_type;
                  logs.grid.refresh();
              },
          },
      ],
      primary_action: (values) => { ... },
      primary_action_label: __("Create"),
    });
    

    on_add_row:一个在向表格添加行时触发的事件。您可以通过向此事件挂钩添加功能来执行数据操作或其他类型的计算等操作。