【问题标题】:How to set default option for dynamic select control in Node-Express-Mongoose?如何在 Node-Express-Mongoose 中设置动态选择控件的默认选项?
【发布时间】:2021-03-10 18:14:49
【问题描述】:

我现在正在使用 PUG 作为视图引擎的 Node-Express 环境中工作。

我有 CompanySchema,其中一个字段“comp_ParentName”指的是架构本身:

comp_ParentName: {type: Schema.Types.ObjectId, ref: 'Company', required: false},

这不是必需的,因为并非每家公司都有母公司。因此,我想为用户提供一个选项,当他们想创建一家新公司时(在公司没有母公司或用户根本不知道公司有任何母公司)。

我的“创建新公司”表单中有一些测试代码,但遗憾的是它不能 100% 达到我的目的:

div.form-group.row
  label(class="col-sm-2 col-form-label col-form-label-sm")(for='comp_ParentName') Parent company:
  div.col-sm-10
    select#comp_ParentName.form-control(class="form-control form-control-sm" type='select', placeholder='Select parent company' name='comp_ParentName' required='false' )
      - companies.sort(function(a, b) {let textA = a.comp_OfficialName_ENG.toUpperCase(); let textB = b.comp_OfficialName_ENG.toUpperCase(); return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;});
      for company in companies
        if company
          option(value=company._id selected=(company._id.toString()===company._id.toString() ? 'selected' : false) ) #{company.comp_OfficialName_ENG}
        else
          option(value=company._id) #{company.comp_OfficialName_ENG}

我在使用上述代码时遇到的问题是,我在表单中总是有一个“预选”公司,但正如我所说,我希望有一个选项可以将此字段留空。我尝试在

的帮助下添加一些默认选项,例如“选择母公司”
option(value="" disabled selected) Choose Parent Company

但每次我尝试保存新公司时,都会弹出“请填写此字段”工具提示。

有没有可能的解决方法?

这是我在 companyController.js 中处理公司创建的代码:

exports.company_create_post = [
// Convert the companyrole to an array.
(req, res, next) => {
    if(!(req.body.companyrole instanceof Array)){
        if(typeof req.body.companyrole ==='undefined')
        req.body.companyrole = [];
        else
        req.body.companyrole = new Array(req.body.companyrole);
    }
    next();
},

// Validate and sanitise fields.
body('comp_OfficialName_ENG', 'Must not be empty.').trim().isLength({ min: 1 }).escape(),
body('comp_ShortName_ENG', 'Must not be empty.').trim().isLength({ min: 1 }).escape(),
body('comp_GroupName_ENG', 'Must not be empty.').trim().isLength({ min: 1 }).escape(),
body('comp_Role.*').escape(),
body('comp_cntrID', 'comp_cntrID must be specified').trim().isLength({ min: 1 }).escape(), //reference to the associated country
body('comp_stID', 'comp_stID must be specified').trim().isLength({ min: 1 }).escape(), //reference to the associated state
body('comp_ctyID', 'comp_ctyID must be specified').trim().isLength({ min: 1 }).escape(), //reference to the associated city

// Process request after validation and sanitization.
(req, res, next) => {
    
    // Extract the validation errors from a request.
    const errors = validationResult(req);

    // Create a Company object with escaped and trimmed data.
    var company = new Company(
      { comp_OfficialName_ENG: req.body.comp_OfficialName_ENG,
        comp_ShortName_ENG: req.body.comp_ShortName_ENG,
        comp_GroupName_ENG: req.body.comp_GroupName_ENG,
        comp_ParentName: req.body.comp_ParentName,
        comp_Role: req.body.companyrole,
        comp_cntrID: req.body.comp_cntrID,
        comp_stID: req.body.comp_stID,
        comp_ctyID: req.body.comp_ctyID
       });

    if (!errors.isEmpty()) {
        // There are errors. Render form again with sanitized values/error messages.

        // Get all Company roles for form.
        async.parallel({
            companyroles: function(callback) {
                CompanyRole.find(callback);
            },
        }, function(err, results) {
            if (err) { return next(err); }

            // Mark our selected companyroles as checked.
            for (let i = 0; i < results.companyroles.length; i++) {
                if (company.companyrole.indexOf(results.companyroles[i]._id) > -1) {
                    results.companyroles[i].checked='true';
                }
            }
            res.render('company_form', { title: 'Create Company', companyroles:results.companyroles, company: company, errors: errors.array() });
        });
        return;
    }
    else {
        // Data from form is valid. Save company.
        company.save(function (err) {
            if (err) { return next(err); }
               //successful - redirect to new company record.
               res.redirect(company.url);
            });
    }
}];

更新: 在@Ankur R 的帮助下,问题基本上得到了解决,但现在我面临另一个问题。 当公司有一个母公司时绝对没问题,我可以在我的选择控件的下拉列表中选择母公司的名称。但是,在公司没有母公司的情况下,我的 company_detail.pug 中的点符号停止工作并给我一个错误。

company.comp_ParentName.comp_OfficialName_ENG

它说“无法读取未定义的属性 'comp_OfficialName_ENG'”。考虑到它被分配了一个零值,这是非常合乎逻辑的:

option(value="" selected) No Parent Company

这是我在“company_form.pug”中的选择控件(只是为了展示“comp_ParentName”是如何创建的):

div.form-group.row
  label(class="col-sm-2 col-form-label col-form-label-sm")(for='comp_ParentName') Parent company:
  div.col-sm-10
    select#comp_ParentName.form-control(class="form-control form-control-sm" type='select', name='comp_ParentName' )
      - companies.sort(function(a, b) {let textA = a.comp_OfficialName_ENG.toUpperCase(); let textB = b.comp_OfficialName_ENG.toUpperCase(); return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;});
      option(value="" selected) No Parent Company
      for company in companies
        if company
          option(value=company._id selected=(company._id.toString()===company._id.toString() ? 'selected' : false) ) #{company.comp_OfficialName_ENG}
        else
          option(value=company._id) #{company.comp_OfficialName_ENG}

这是“company_detail.pug”中的代码,其中点表示法停止工作,表示“comp_ParentName”未定义。

div.form-group.row
  label(class="col-sm-2 col-form-label col-form-label-sm")(for='comp_ParentName') Parent company:
  div.col-sm-3
    input#comp_ParentName.form-control(class="form-control rdonly form-control-xs" type='text', name='comp_ParentName' value=(undefined===company ? '' : company.comp_ParentName.comp_OfficialName_ENG ) readonly)

关于如何处理这个问题的任何想法?

【问题讨论】:

    标签: node.js express mongoose pug


    【解决方案1】:

    创建选择和选项的代码存在问题。

    我尝试了下面的代码,它成功了。

    form
        div.form-group.row
            label(class="col-sm-2 col-form-label col-form-label-sm")(for='comp_ParentName') Parent company:
            div.col-sm-10
                select#comp_ParentName.form-control(class="form-control form-control-sm", name="comp_ParentName")
                    option(value="" selected) Choose Parent Company
                    option(value="1") One
                    option(value="2") Two
        div.form-group.row
            button(type="submit") Submit
    

    更新:

    1. 这里在 select 中不需要指定 select="true/false" 因为浏览器只检查必需的属性。
    2. 不建议在选择中禁用清空值选项,因为一旦用户选择了其他选项并想取消选择,就不可能了。

    【讨论】:

    • 感谢@Ankur R!我不确定它是否对我有用。首先,我的列表中没有有限数量的选项,例如 Option1、Option2、Option3 等......它实际上包含“Company”集合中所有公司的所有 _ID 的列表。所以,我肯定需要使用循环。
    • 是的,您可以使用循环。我没有要求改变。您只需从 select 中删除 require="false"。
    • type 和 placeholder 也是 html 中 select 元素不支持的属性。如果这个问题已经解决了您的问题,那么请接受它作为正确答案。
    • 谢谢@Ankur R。我稍后会检查并回复。
    • 其实我赶紧查了一下还是不行。如果我接受您的建议并从 select 中删除 require="false" - 它会给我另一个错误:“公司验证失败:comp_ParentName: Cast to ObjectId failed for value "" at path "comp_ParentName"”。如果我保持原样或将其更改为 require="true" - 当我按下提交时,会弹出相同的工具提示“请填写此字段”。
    【解决方案2】:

    在这里,我已从您的控制器中更正了公司创建代码

    // Create a Company object with escaped and trimmed data.
    var company = new Company(
      { comp_OfficialName_ENG: req.body.comp_OfficialName_ENG,
        comp_ShortName_ENG: req.body.comp_ShortName_ENG,
        comp_GroupName_ENG: req.body.comp_GroupName_ENG,
        ...(!!req.body.comp_ParentName && { comp_ParentName: req.body.comp_ParentName }),
        comp_Role: req.body.companyrole,
        comp_cntrID: req.body.comp_cntrID,
        comp_stID: req.body.comp_stID,
        comp_ctyID: req.body.comp_ctyID
       });
    

    此外,如果您只想对 mongo id 进行更严格的检查,请检查 here

    对于参考。在对象创建中使用扩展运算符遵循 https://medium.com/@slamflipstrom/conditional-object-properties-using-spread-in-javascript-714e0a12f496

    【讨论】:

    • 非常感谢@Ankur R!它现在工作得很好。非常感谢您为我提供帮助的时间和精力!
    • 很高兴知道它对您有所帮助。
    • 如果您能负担得起在我的案子上多花一点时间 - 将非常感谢您提供另一份帮助...
    • 嘿@Ankur R,你能再帮忙吗? :)
    【解决方案3】:

    终于解决了我的问题。只是我对 PUG 很陌生,不知道如何处理其中的 if 语句。我所要做的就是检查我的“company.comp_ParentName”是否已定义。因此添加以下 if 语句有助于解决问题:

    if (typeof(company.comp_ParentName) == 'undefined')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-11
      • 1970-01-01
      • 1970-01-01
      • 2019-09-18
      • 1970-01-01
      • 2015-09-19
      • 1970-01-01
      • 2016-10-01
      相关资源
      最近更新 更多