简体   繁体   English

在Express App中动态填充模式

[英]Dynamically populating modal in express app

I'm writing an express app that will allow someone to create a recipe (cooking recipe), which is then saved to mongodb. 我正在写一个快递应用程序,它将允许某人创建一个食谱(烹饪食谱),然后将其保存到mongodb中。 When they open the app they can see the list of recipes, edit them, delete them etc. 当他们打开应用程序时,他们可以查看食谱列表,对其进行编辑,将其删除等。

The recipes are being stored in mongo like this 像这样将食谱存储在mongo中

> db.recipes.find()
{ "_id" : ObjectId("542fc7d635ebd51b8afd507b"), "name" : "chili", 
  "ingredients" : [ 
    { "ingredient" :     "mince", "quantity" : "500", "unit" : "g" }, 
    { "ingredient" : "cumin", "quantity" : "1", "unit" : "tsp" }, 
    { "ingredient" : "paprika", "quantity" : "2", "unit" : "tsp" } ] 
}
{ "_id" : ObjectId("542fccbb6de6181f8da58346"), "name" : "test", 
  "ingredients" : [ 
    { "ingredient" : "stuff", "quantity" : "10", "unit" : "g" }, 
    { "ingredient" : "stuff", "quantity" : "10", "unit" : "g" } ] 
}

The db is read from whenever the 'recipes' page is viewed 每当查看“食谱”页面时,都会从数据库中读取数据库

router.get('/recipes', function(req, res) {
  db.collection('recipes').find().toArray(function(err, results) {
    if(results.length > 0) {
      recipes = results;

      for(var i = 0; i < results.length; i++) {
        recipeList[i] = results[i].name;
      }

      res.render('recipes', {recipes: recipes, recipeList: recipeList});
    } else {
      recipes = [];

      res.render('recipes', {recipes: recipes, recipeList: recipeList});
    }

  });
});

and then in recipes.jade the recipes are listed as follows 然后在recipes.jade ,秘诀列出如下

table.table
  thead
    tr
      th Name
  tbody
  - for(var i = 0; i < recipes.length; i++)
    tr
      td= recipes[i].name

食谱清单

When one of these recipes is clicked on a modal is launched as follows 当单击这些配方之一时,将按以下方式启动模态

script("type=text/javascript").
  $('td').on('click', function() {
    var recipe = $(this).clone().children().remove().end().text();

    $('#myModalLabel.modal-title').html(recipe);
    $('#myModal').modal();
  });

which should list the ingredients 应该列出成分

在此处输入图片说明

I'm having difficulty figuring out how to display the ingredients for a recipe when it is clicked on. 我很难弄清楚如何在单击时显示配方的成分。 I tried to figure it out by adding this code in the modal, which I know is wrong but I don't know what to change. 我试图通过在模式中添加此代码来弄清楚这一点,我知道这是错误的,但我不知道要更改什么。

p ingredients
- for(var j = 0; j < recipes.length; j++)
  ul
    li= recipes[j].ingredients[0].ingredient

在此处输入图片说明



Following nanoamps's answer, and modifying slightly, I now have a separate template file singleRecipe.jade 遵循纳安的回答并稍加修改,我现在有了一个单独的模板文件singleRecipe.jade

- var theIngredients = recipes[recipeIndex].ingredients;
p ingredients
ul
- for(var j = 0; j < theIngredients.length; j++)
  li= theIngredients[j].quantity + theIngredients[j].unit + ' ' + theIngredients[j].ingredient

so when a recipe is clicked, this handler gets the name and index 因此,单击配方时,此处理程序将获取名称和索引

$('td').on('click', function() {
  var recipeIndex = $(this).parent().index();
  var recipeName = $(this).text();
  $('#myModal .modal-body').load('/singleRecipe/' + recipeIndex, function() {
    $('#myModal').modal();
  });
});

and the route handler in app.js is now 并且app.js的路由处理程序现在是

router.get('/singleRecipe/:d', function(req, res) {
  db.collection('recipes').find().toArray(function(err, results) {
    if(results.length > 0) {
      recipes = results;
      for(var i = 0; i < results.length; i++) {
        recipeList[i] = results[i].name;
      }
      res.render('singleRecipe', {recipes: recipes, recipeIndex: req.params.d});
    } else {
      recipes = [];
      res.render('recipes', {recipes: recipes, recipeList: recipeList});
    }
  });
});

I know this is still quite messy, but it's working as shown below, so now I can just start refactoring. 我知道这仍然很混乱,但是它的工作方式如下所示,所以现在我可以开始重构了。

在此处输入图片说明

Your current display code is looping through all the recipes (with the for j loop) and then printing the first ingredient of each (with the .ingredient[0] reference). 您当前的显示代码将遍历所有配方(使用for j循环),然后打印每种配方的第一个成分(使用.ingredient[0]参考)。

Start by finding out which recipe you've chosen in your click handler with something like: 首先找出您在点击处理程序中选择的配方,例如:

var recipeIndex = $(this).index();
var recipeName = $(this).text();

Then you can use the recipe index to pick the right one from your recipes array. 然后,您可以使用食谱索引从recipes数组中选择正确的一个。 You could build a massive list somewhere in your initial recipes.jade page, hide it with CSS and then clone into the modal when required, but that's not very scalable. 您可以在最初的recipes.jade页面上的某个位置构建一个庞大的列表,使用CSS将其隐藏,然后在需要时克隆到模式中,但这不是非常可扩展的。 You'd be better off putting the rendering of the individual recipe details into a separate template with its own route: 最好将各个配方详细信息的呈现放入具有其自己路线的单独模板中:

- var theIngredients = recipes[recipeIndex].ingredients;
p ingredients
ul
- for(var j = 0; j < theIngredients.length; j++)
  li= theIngredients[j].quantity + theIngredients[j].unit + ' ' + theIngredients[j].ingredient

This will build a list of ingredients for the given index, looping to create each list item with the concatenated ingredient details. 这将为给定的索引构建一个配料列表,循环创建带有串联配料详细信息的每个列表项。

Then pull that into your modal using a separate GET request in the click handler with something like: 然后在点击处理程序中使用单独的GET请求将其拉入模态,如下所示:

$('#myModal .modal-body').load('/singleRecipe?index=' + recipeIndex, function() {
  $('#myModal').modal();
});

which requests your new template, passing the index in the URL. 它将请求您的新模板,并在URL中传递索引。

Although that should work, any changes to the collection will bring up the wrong recipe. 尽管这应该可行,但是对集合的任何更改都会带来错误的配方。 Build on that by instead rendering MongoDB's unique _id identifier somewhere in the initial table rows (eg. as a data-id attribute) and using that as the thing you lookup and pass through your click handler and request. 在此基础上,通过代替将MongoDB的唯一_id标识符呈现在初始表行中的某个位置(例如,作为data-id属性),并将其用作您查找的对象并通过点击处理程序和请求。 Then the single recipe route can lookup the single record in the database instead of loading the whole collection. 然后,单个配方路线可以在数据库中查找单个记录,而不是加载整个集合。 It'll be faster, less data down the wire, and less brittle. 这样会更快,传输的数据更少,并且变脆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM