Populate input fields with data from another collection


#1

Hey guys,

I have this form, where I want to dynamically create input fields based on values from another collection.

So when the user clicks on a button, it populates the form with the correct data from the collection inside the input fields.

Event handler:

Template.workout.events({
  'click .loadProgramme': function(event) {
    event.preventDefault();

    var programme = event.target.value;

    Programmes.findOne({title: programme});

  },

Workout template:

 <button class="loadProgramme" value="Fullbody">Fullbody</button>
    <button class="loadProgramme" value="Split day 2">Split day 2</button>
    
    <form class="insertExercise">
      <input type="text" name="name" placeholder="Exercise name?">
      <input type="number" name="sets" placeholder="# of sets performed">
      <input type="number" name="reps" placeholder="# of reps performed">
        <select name="kgs">

Essentially I need to create exercise name fields, for each exercise in the Programmes collection, can anyone point me in the right direction on this one?


#2

Okay, so i’ve expanded my code a little, trying to atleast get it to return the collection depending on the button pressed:

Template.workout.events({
  'click .loadProgramme': function(event) {
    event.preventDefault();

    var programme = event.target.value;

    var item = Programmes.findOne({title: programme});

   return Session.set('chosenProgramme', item);

  },

My problem now is how to return the data to my template? Im trying to use sessions, but it tells me:

Error: {{#each}} currently only accepts arrays, cursors or falsey values.

This is my helper:

programmes: function() {
    return Programmes.findOne(Session.get('chosenProgramme', item));
}

#3

Use find() instead of findOne().


#4

Hey Steve,

I solved it by using the #with template helper, and having the following code:

Helper function

   programmes: function() {
        Session.get('chosenProgramme');
        return Programmes.findOne(Session.get('chosenProgramme'));
      },
      ...

Template:

  <button class="loadProgramme" value="Fullbody">Fullbody</button>
        <button class="loadProgramme" value="test">test</button>
    
        <form class="insertExercise">
    
        {{ #with programmes }}
        {{title}}
            {{ #each actions }}
            <input type="text" name="name[]" class="exerciseName" placeholder="Exercise name?" value="{{name}}">
            <input type="number" name="sets[]" placeholder="# of sets performed">
            <input type="number" name="reps[]" placeholder="# of reps performed">
            <select name="kgs[]">
                <option value="2.5">2.5 kg</option>
                <option value="5">5 kg</option>
            </select>
            <input type="submit" value="Create exercise">
           ...
         {{ /each }}

I actually managed to create the rest of the setup as I wanted it, however I think my database design/thinking is a bit flawed here, and doesn’t help me.

By having a programmes table with exercises in it, I make it easier for the end user, but I also make it a lot harder for myself in building the application I think.

Is it possible to make it so that the above list is just replaced with the values from my form? So that I dont have to show 2 separate lists? One for the input fields, and one for the actual submits?


#5

Sorry, I don’t understand your point. I see only one list.


#6

Hello,

as u never pasted whole template, it is quite hard to understand what you are asking for…

So I would expect you mean that 1st is collection which represent inital list you are picking.
I personally would probably use dropdown and yeld values in it, than wait for submit button, or listen for “change” event on that input dropdown element.

2nd is based on 1st selected value, you can always create helper which indicate if you already picked and put it in IF statement in template

As an example, my little prototype there is input dropdown to pick sort metric on http://shockitv.meteor.com/
And yes, it is ugly + partially responsive atm. Reworking from bootstrap to polymer 1.0 + flex.


#7

Hey shock and Steve!

Thanks for answering. I’m sorry about the missing template, I guess I was in my own thoughts for a while there, but here it is:

<template name="workout">
    <h1>Workout with the id of: {{_id}}</h1>
    <p>{{formatTime title}}</p>

    {{ #each exercises }}
      <li>{{name}}, {{sets}}, {{reps}}, {{kgs}}</li>
    {{ /each }}

    <button class="loadProgramme" value="Fullbody">Fullbody</button>
    <button class="loadProgramme" value="test">test</button>

    <form class="insertExercise">

    {{ #with programmes }}
    {{title}}
        {{ #each actions }}
        <li>
            <input type="text" name="name[]" class="exerciseName" placeholder="Exercise name?" value="{{name}}">
            <input type="number" name="sets[]" placeholder="# of sets performed">
            <input type="number" name="reps[]" placeholder="# of reps performed">
            <select name="kgs[]">
                <option value="2.5">2.5 kg</option>
                <option value="5">5 kg</option>
            </select>
            <input type="submit" value="Create exercise">
        </li>
        {{ /each }}
    {{ /with }}
    </form>

</template>

So the layout is messy here, but it should give the right idea about what I want to do:

  1. user chooses a predefined programme (another collection)
  2. The form is populated with new input fields according to how many items the collection returns
  3. When the user submits the form, the values are persisted to the database, and shown as items in the template.

All of the above works as it is now.

Optimally though, i would like it to be so that there is only one list, or that the input fields somehow get replaced with the data that is submitted, is that possible ?