如何在ejs + mongoose中更新具有多个值的表单?

时间:2015-11-04 10:27:26

标签: node.js mongoose ejs

用户拥有mongoose中的字段,如果用户决定更新,该字段将会更新。

这是用户架构

var User = Schema({

    education: [{ type: String}],
});

因此,用户基本上可以更新或添加字段,例如,用户可以使用表单添加其他教育和技能信息。

我如何在ejs和路线中正确地做到这一点?

我在route.js中的尝试

router.post('/update-resume', function(req, res) {
    User.findById(req.user._id, function(err, foundUser) {
        // This part how do I update ?
        if (req.body.education) foundUser.resume.education.push(req.body.education); 

        foundUser.save();
    });

});

价值不断推动,我想,我知道很明显我将数据推送到现场,但我该如何正确更新?

Form.ejs

<div class="form-group">
    <label for="education">Education:</label>
    <% for(var i = 0; i < user.resume.education.length; i++) { %>
    <input type="text" class="form-control" name="education" id="education" value="<%= user.resume.education[i] %>">
    <% } %>
  </div>

我是否需要循环每个字段?如果我想更新特定数据?

2 个答案:

答案 0 :(得分:2)

第一个选项:

根据您使用该应用程序的方式,您可能甚至不关心更新 - 您可以删除以前的教育并保存新的教育。

第二个选项:

要正确更新,您确实需要某种ID,您可以在更新时参考,对吗?

您仍然需要使用for循环,只需要插入id隐藏字段。

为此,您需要传递一个对象而不是唯一的字符串值。我让我的对象数组看起来像这样:

var education = [
    {content:'Education 1',id:1},
    {content:'Education 2',id:3},
    {content:'Education 3',id:5},
    {content:'Education 4',id:2},
];

然后你可以这样做:

<% for(var i = 0; i < education.length; i++) { %>
<input type="hidden" type="hidden" name="education_id" value="<%= education[i].id %>"/>
<input type="text" class="form-control" name="education" id="education" value="<%= education[i].content %>">
<% } %>

数组将始终以您将其发送到服务器的方式传递。在我的情况下,我会得到这个(你可以看到一切都按照它应该的顺序):

  {education_id: [ '1', '3', '5', '2' ],
  education: [ 'Education 1', 'Education 2', 'Education 3', 'Education 4' ] }

现在,让我们看看POST后端,你需要把所有东西都绑回到一个对象上(你真的不需要,但你可以并且可能为了理智而应该):

var education_i;
var education_req = [];
for(education_i=0;education_i<req.body.education.length;education_i++) {
    console.log(req.body.education[education_i]);
    education_req.push({
        content:req.body.education[education_i],
        id:req.body.education_id[education_i]
    });
}

还有一些说明:

  • 您必须检查每条教育记录的用户。你不想让任何人弄乱身份证并毁掉别人的个人资料。
  • 您可能应该在循环之外单独保存数组长度变量,因为它可能会导致非常大的数组上的性能问题,因为在每次循环迭代时都会解析长度。

答案 1 :(得分:2)

这就是我这样做的方式:

模特:

var User = new Schema({
  education: [{ content: String }]
});

EJS / HTML:

<form id="education">
  <% user.education.forEach(function(item) { %>
  <input type="text" data-id="<%= item.id %>" value="<%= item.content %>" />
  <% }); %>
  <button type="submit">Save</button>
</form>

客户端javascript(JQuery):

$('#education').on('submit', function(e) {
  e.preventDefault();

  var data = [];
  $(this)
    .find('input')
    .each(function() {
      var $this = $(this);

      // Collect the data with the id and value
      data.push({
        id: $this.data('id'),
        value: $this.val()
      });
    });


  $.ajax({
    url: '/update-resume',
    type: 'post',
    data: { data: JSON.stringify(data) }
  })
    .done(function(data) {
      if (data.success) {
         // Lazy: refresh window
         window.location.reload();
      }
    })
    .fail(function() {
      // Show an error or something fancy
    });
});

上面的javascript将从输入和值中读取数据ID,并将它们放入教育对象数组中。然后它将对象add和字符串字符串化为键'data'。这意味着您可以从req.body.data中拉出路径中的字符串并解析它。

路由中的服务器端javascript /:

router.post('/update-resume', function(req, res, next) {
  User.findById(req.user._id, function(err, user) {
    var parsed = JSON.parse(req.body.data);


    // update and remove
    var results = user
      .education
      .filter(function(item) {
        return parsed.some(function(input) {
          return input.id === item.id;
        });
      })
      .map(function(item) {
        var related = getRelated(item.id, parsed);
        return { content: related.value };
      });

    // Add new items
    user.education = results
      .concat(parsed.reduce(function(prev, curr) {
        if (!getRelated(curr.id, results)) {
          prev.push({ content: curr.value });
        }
        return prev;
      }, []));

    user.save(function(err) {
      if (err) return next(err);
      res.json({ success: true });
    });
  });
});

获取相关助手:

var getRelated = function(id, arr) {
  for (var i = 0; i < arr.length; i++) {
    if (String(arr[i].id) === String(id)) return arr[i];
  }
};

Mongoose会自动为您的教育数组项目提供ID。通过以上操作,您可以在页面上添加,删除和更新现有的教育项目。