Creating a dynamic form with Meteor Spacebars - meteor

I want to create a form that shows different sections depending on which template it belongs to. I want the data that the user enters to be reactive: if the user changes from one template to another, her previous entries should still be visible. I plan to create a "form" template, so that I can have a single Template.form.events function that will set the appropriate Session variables as the form is filled in.
My question is about how to populate the form dynamically. Here's how I've attempted to go about this, but all the fields appear all the time.
<body>
{{> form1}}
{{> form2}}
<h1>Log in</h1>
{{> form name=1 password=1}}
</body>
<template name="form1">
{{#form name=1 species=1}}
<h1>Form 1</h1>
{{/form}}
</template>
<template name="form2">
<h1>Form 2</h1>
{{>form name=1 planet=1 asMenu=1}}
</template>
<template name="form">
{{#if name=1}}
<input type="text" name="name" placeholder="Name" value="">
{{/if}}
{{#if species=1}}
<input type="text" name="species" placeholder="Species" value="">
{{/if}}
{{#if planet=1}}
{{#if asMenu=1}}
<select name="">
<option value="Erth">Erth</option>
<option value="Othr">Othr</option>
</select>
{{else}}
<input type="text" name="planet" placeholder="Planet" value="">
{{/if}}
{{/if}}
{{#if password=1}}
<input type="password" name="password" value="">
{{/if}}
<br />
<button type="submit">Submit</button>
</template>
Can you help me to understand how to resolve this?

Firstly spacebars doesn't support comparisons so {{#if var=1}} is invalid syntax. However 1 is true so I'm going to take advantage of that to replace {{#if name=1}} with {{#if name}}:
<body>
{{> form1}}
{{> form2}}
<h1>Log in</h1>
{{> form name=1 password=1}}
</body>
<template name="form1">
<h1>Form 1</h1>
{{>form name=1 species=1}}
</template>
<template name="form2">
<h1>Form 2</h1>
{{>form name=1 planet=1 asMenu=1}}
</template>
<template name="form">
{{#if name}}
<input type="text" name="name" placeholder="Name" value="">
{{/if}}
{{#if species}}
<input type="text" name="species" placeholder="Species" value="">
{{/if}}
{{#if planet}}
{{#if asMenu}}
<select name="">
<option value="Erth">Erth</option>
<option value="Othr">Othr</option>
</select>
{{else}}
<input type="text" name="planet" placeholder="Planet" value="">
{{/if}}
{{/if}}
{{#if password}}
<input type="password" name="password" value="">
{{/if}}
<br />
<button type="submit">Submit</button>
</template>

Related

Meteor aldeed:autoform custom arrayField template not working

I've looked for tutorials about AutoForm's custom field templates but I'm not sure where I'm going wrong with mine. If anyone has any suggestions it would be greatly appreciated.
My Schema: One field is an Array of Objects.
guests: {
type: Array,
minCount: 1,
maxCount: 10,
label: "Guests in Party"
},
"guests.$": {
type: Object,
label: "Guest Object"
},
"guests.$.firstName": {
type: String,
label: "First Name"
},
"guests.$.lastName": {
type: String,
label: "Last Name"
}
Template Code:
<template name='afArrayField_guestsObjectField'>
{{#afEachArrayItem name="guests" minCount="this.atts.minCount" maxCount="this.atts.maxCount"}}
<div class="form-group">
<label class="control-label col-sm-2">Guest</label>
{{> afObjectField name="this.name" label="false" template='customObjectField'}}
<div class="col-sm-2">
{{#if afArrayFieldHasLessThanMaximum name="guests"}}
<button type="button" class="btn btn-primary autoform-add-item" data-autoform-field="{{guests}}" data-autoform-minCount="{{this.atts.minCount}}" data-autoform-maxCount="{{this.atts.maxCount}}"><span class="glyphicon glyphicon-plus"></span></button>
{{/if}}
{{#if afArrayFieldHasMoreThanMinimum name="guests"}}
<button type="button" class="btn btn-primary autoform-remove-item pull-left"><span class="glyphicon glyphicon-minus"></span></button>
{{/if}}
</div>
</div>
{{/afEachArrayItem}}
</template>
<template name="afObjectField_customObjectField">
<div class="col-sm-4">
{{> afFieldInput name="this.firstName" class="form-control" placeholder="First Name"}}
{{#if afFieldIsInvalid name='this.firstName'}}
<span class="help-block">{{{afFieldMessage name='this.firstName'}}}</span>
{{/if}}
</div>
<div class="col-sm-4">
{{> afFieldInput name="this.lastName" class="form-control" placeholder="Last Name"}}
{{#if afFieldIsInvalid name='this.lastName'}}
<span class="help-block">{{{afFieldMessage name='this.lastName'}}}</span>
{{/if}}
</div>
</template>
The problem I am having is that the plus buttons shows up after the firstName and lastName field how I want it to, but when I press it another guest object (in the form) does not generate. Any thoughts?

IntelliJ IDEA 14 does not recognize spacebars templates

I am writing a simple meteor app and finding that IntelliJ IDEA 14.1.4 (with the Meteor and Handlebars plugins installed and enabled) does not recognize spacebars templates:
After googling, I tried File > Invalidate Caches/Restart but this did not work.
I also find that when I run Code > Reformat Code, the resulting indentation is not correct. I assume both problems are related.
Here is an even simpler illustration of the problem:
How can I debug this?
Finally, I find the really tricky syntax error in my IntelliJ IDEA 14.
The main problem is the space between {{ and # or /.
{{#if currentUser}} is right in syntax but {{ #if currentUser }} is wrong.
Alike, user {{/if}} instead of {{ /if }}.
So the spacebars usage is really strict here. Actually, there should be no extra spaces.
<template name="home">
{{#if currentUser}}
<div class="template-home">
<div class="well">
<form class="form-inline syllabus-chooser">
<div class="form-group">
<select name="syllabusChooser" id="syllabusChooser" class="form-control">
<option value="0">(Select a syllabus to edit)</option>
{{#each syllabusSelectors}}
<option value="{{ value }}">{{ label }}</option>
{{/each}}
</select>
</div>
<button type="submit" id="syllabusChooserButton" class="btn btn-default">Edit</button>
</form>
</div>
{{#if displayID}}
<div class="well">
{{#autoForm collection="Syllabuses" doc=selectedSyllabusDoc id="insertSyllabusForm" type="update"}}
<fieldset>
<div class="row">
<div class="col-sm-2">{{> afQuickField name='alphaNumber' placeholder="ICS 101"}}</div>
<div class="col-sm-2">{{> afQuickField name='creditHours' placeholder="3"}}</div>
<div class="col-sm-2">{{> afQuickField name='prerequisites' placeholder="311 or consent"}}</div>
<div class="col-sm-6">{{> afQuickField name='title' placeholder="Course title"}}</div>
</div>
<div class="row">
<div class="col-sm-6">{{> afQuickField name='instructor' rows=2 placeholder="Name\noffice address, email"}}</div>
<div class="col-sm-6">{{> afQuickField name='textbooks' rows=2 placeholder= "Textbook title and author, or 'none'"}}</div>
</div>
<div class="row">
<div class="col-sm-6">{{> afQuickField name='objectives' rows=4 placeholder='* Students have ...\n* Students can ...\n* Students can ....'}}</div>
<div class="col-sm-6">{{> afQuickField name='policies' rows=4 placeholder="Can be 'none'."}}</div>
</div>
<div class="row">
<div class="col-sm-6">{{> afQuickField name='description' rows=4 placeholder='Insert course catalog description: http://www.catalog.hawaii.edu/courses/departments/ics.htm'}}</div>
<div class="col-sm-6">{{> afQuickField name='grading' rows=4 placeholder="5 homework assignments (10% each)\n1 midterm (15%)\n1 final exam (15%)\n1 final project (20%)"}}</div>
</div>
<div class="row">
<div class="col-sm-6">{{> afFormGroup name='learningOutcomes' type="select-checkbox"}}</div>
<div class="col-sm-6">
{{> afQuickField name='courseLearningOutcomes' rows=12 placeholder="* Learning Outcome 1\n* Learning outcome 2"}}
{{> afQuickField name='schedule' rows=12 placeholder="Week 1: ...\nWeek 2: ...\nWeek 3: ..."}}
</div>
</div>
</fieldset>
<button type="submit" class="btn btn-default btn-success btn-block">Save</button>
{{/autoForm}}
</div>
{{/if}}
</div>
<div class="well" style="padding: 0; max-height: 100px; overflow-y: auto">
<ul>
{{#each editStatusList}}
<li>Started editing {{ syllabusName }} {{ editTimestamp }} {{#if editFinished}} ... finished. {{/if}} </li>
{{/each}}
</ul>
</div>
{{/if}}
</template>

Meteor: Using an HTML Template to add to the DOM.

I'm building an app with Meteor.js, and I've got a form where I would like to be able to allow the user to add a new row to the form when they click a button (button.addExperience). I'm using an HTML Template to populate each row of the form.
How would I have the template (experienceRow) rendered each time the user clicks the button?
See example code below:
<body>
<form>
{{> experienceRow }}
</form>
<button class="addExperience">Add Experience</button>
</body>
<template name="experienceRow">
<div id={{experienceNumber}} class='experienceRow'>
<input type="text" placeholder="name" value="" class="name">
<input type="text" placeholder="address" value="" class="address">
<input type="text" placeholder="phone" value="" class="phone">
</div>
</template>
You will need to use an each block along with a reactive variable. That variable could be a ReactiveVar, a session varaible, a local collection, etc. Here's an example implementation using a ReactiveVar to hold an array of ids:
html
<body>
{{> experienceForm }}
</body>
<template name="experienceForm">
<form>
{{#each experienceIds}}
{{> experienceRow }}
{{/each}}
</form>
<button class="addExperience">Add Experience</button>
</template>
<template name="experienceRow">
<div id={{this}} class='experienceRow'>
<input type="text" placeholder="name" value="" class="name">
<input type="text" placeholder="address" value="" class="address">
<input type="text" placeholder="phone" value="" class="phone">
</div>
</template>
js
Template.experienceForm.onCreated(function() {
this.experienceIds = new ReactiveVar(Random.id());
});
Template.experienceForm.helpers({
experienceIds: function() {
return Template.instance().experienceIds.get();
}
});
Template.experienceForm.events({
'click .addExperience': function(e, template) {
e.preventDefault();
var ids = template.experienceIds.get();
ids.push(Random.id());
template.experienceIds.set(ids);
}
});
Note that you'll need to meteor add reactive-var for this to work.
Recommended reading: scoped reactivity.

error in closing autoform template

I have this piece of code in my meteor application.
Meteor version is : Meteor 1.0.3.1
The code well formatted as required by blaze template. But I don't understand this problem.
I was able to use quickForm of autoform package but not able to use autoform.
<template name="register">
{{> autoForm collection="Users" id="addUserForm" type="insert"}}
<fieldset>
<legend>Register</legend>
<div class="form-group">
<label for="inputFirstName" class="col-lg-2 control-label">First Name</label>
<div class="col-lg-10">
{{> afFieldInput name="firstName" class="form-control" id="inputFirstName"}}
</div>
</div>
<div class="form-group">
<label for="inputLastName" class="col-lg-2 control-label">Last Name</label>
<div class="col-lg-10">
<input type="text" class="form-control" id="inputLastName" placeholder="Last Name" />
</div>
</div>
<div class="form-group">
<label for="inputEmail" class="col-lg-2 control-label">Email</label>
<div class="col-lg-10">
<input type="email" class="form-control" id="inputEmail" placeholder="Email" />
</div>
</div>
<div class="form-group">
<label for="inputPass" class="col-lg-2 control-label">Password</label>
<div class="col-lg-10">
<input type="password" class="form-control" id="inputPass" placeholder="Password" />
</div>
</div>
<div class="form-group">
<label for="inputMobileNum" class="col-lg-2 control-label">Mobile Number</label>
<div class="col-lg-10">
<input type="tel" class="form-control" id="inputMobileNum" placeholder="Mobile Number" />
</div>
</div>
<div class="form-group">
<label for="inputDOB" class="col-lg-2 control-label">Date of Birth</label>
<div class="col-lg-10">
<input type="date" class="form-control" id="inputDOB" placeholder="Date of Birth" />
</div>
</div>
<div class="form-group">
<label for="bgroup" class="col-lg-2 control-label">Blood Group</label>
<div class="col-lg-10">
<select class="form-control" id="bgroup">
<option>A+</option>
<option>A-</option>
<option>B+</option>
<option>B-</option>
<option>AB+</option>
<option>AB-</option>
<option>O+</option>
<option>O-</option>
</select>
</div>
</div>
<div class="form-group">
<label for="country" class="col-lg-2 control-label">Country</label>
<div class="col-lg-10">
<select class="form-control" id="country">
<option>India</option>
</select>
</div>
</div>
<div class="form-group">
<label for="state" class="col-lg-2 control-label">State</label>
<div class="col-lg-10">
<select class="form-control" id="state">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
</div>
<div class="form-group">
<label for="city" class="col-lg-2 control-label">City</label>
<div class="col-lg-10">
<select class="form-control" id="city">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
</div>
</fieldset>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<button type="submit" class="btn btn-primary">Register</button>
</div>
</div>
{{/autoForm}}
</template>
I am getting following error:
While building the application:
register.html:96: Unexpected closing template tag
... </div> {{/autoForm}}
Have a look at the Spacebars syntax.
{{> template ... }} means, put the contents of "template" there. There's no closing tag; it's just a one-line inclusion.
{{# block ... }} on the other hand, is a block helper, which has content and a matching closing tag {{/block}}. The most popular block helper is each:
{{#each players}}
{{> player}}
{{/each}}
So you don't need {{/autoform}}.

Routing not happening in iron-router

I have updated meteor project to 0.8.0 and have installed iron-router package. Did everything that is required but routing not happening. It is showing the front page i.e I am able to login into the application. But after that not able to go to any of the pages. My homepage have so many buttons as can be seen in header.html file. When I clicked on grumble link, in url it is displaying that "localhost:3000/grumble". But nothing is getting displayed on that form.
--> My router.js page is:
Router.configure({
layoutTemplate: 'layout'
});
Router.map(function() {
this.route('issues', {path:'/'});
this.route('issues', {path:'/issues'});
this.route('closedIssues', {path:'/closedIssues'});
this.route('subscribedKeywords', {path:'/subscribedKeywords'});
//this.route('grumble');
//this.route('grumble2');
this.route('grumble', {path:'grumble'});
this.route('grumble2', {path:'grumble2'});
this.route('issuePage', {
path:'/issues/:_id',
data: function() {Session.set('currentIssueId', this.params); }
});
this.route('closedIssuePage', {
path:'/closedIssues/:_id',
data: function() { Session.set('currentClosedIssueId', this.params); }
});
});
var requireLogin = function() {
if ( Meteor.user())
this.render(this.params);
else if (Meteor.loggingIn())
this.render('loading');
else
this.render('accessDenied');
this.stop();
}
var clearErrors = function() {
clearErrors();
this.render(this.params);
this.stop();
}
Router.onBeforeAction(requireLogin, {only: 'grumble'});
Router.onBeforeAction(clearErrors);
--> Header.html file is from where grumble.html has been called meas href is present in this page to transfer the control:
<template name="header">
<header class="navbar">
<p>inside header.html</p>
<div class="navbar-inner">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-coll
apse">
</a>
<a class="details btn" href="{{pathFor 'grumble'}}">Grumble</a>
{{#if currentUser}}
<a class="details btn" href="{{issuesPath}}">See Issues</a>
<a class="details btn" href="{{closedIssuesPath}}">Closed Issues</a>
<a class="details btn" href="{{subscribedKeywordsPath}}">Watchlist</a>
{{> notifications}}
{{/if}}
<span class="nav pull-right">
<li>{{> loginButtons}}</li> <!--should be {{> }} here in order to display login functionality-->
</span>
</div>
</header>
</template>
--> Grumble.html, the file to which control should be transferred means routing has been done for this page to get the control
<template name="grumble">
<p>inside form i.e. grumble.html</p>
<form class="main">
<fieldset>
<legend>New Grumble</legend>
<table border="0">
<tr>
<td>
<label class="control-label" for="shortdesc"><span style="color:red;">*</span> Description</label>
<input name="shortdesc" type="text" value="" placeholder="Radiator not working"/>
</td>
<td>
<label class="control-label" for="urgency">Urgency</label>
<select name="urgency" >
<option value="high">High</option>
<option value="medium">Medium</option>
<option value="low">Low</option>
</select>
</td>
</tr>
<tr>
<td>
<label class="control-label" for="date">Date</label>
<input name="date" type="date" value="{{date}}" />
</td>
<td>
<label class="control-label" for="time">Time</label>
<input name="time" type="time" value="{{time}}" />
</td>
</tr>
<tr>
<td>
<label class="control-label" for="dept">Department/Building</label>
<input name="dept" type="text" value="" placeholder="Physiotherapy"/>
</td>
<td>
<label class="control-label" for="unit">Unit</label>
<input name="unit" type="text" value="" placeholder="Occupational Therapy"/>
</td>
</tr>
<tr>
<td>
<label class="control-label" for="room">Room</label>
<input name="room" type="text" value="" placeholder="P2"/>
</td>
<td>
<label class="control-label" for="category">Category</label>
<input name="category" type="text" value="" placeholder="Utility"/>
</td>
</tr>
<tr>
<td>
<label class="control-label" for="details">Details</label>
<textarea name="details" value="" placeholder="Broken radiator next to vending machine."></textarea>
</td>
<td>
<label class="control-label" for="anonymous">Anonymity</label>
<select name="anonymous" >
<option value="anonymous">Anonymous</option>
<option value="identifiable">Identifiable</option>
</select>
</td>
</tr>
</table>
<div class="control-group">
<div class="controls">
<input type="submit" value="Submit" class="btn btn-primary"/>
</div>
</div>
</fieldset>
</form>
</template>
<template name="grumble2">
<form class="main">
<fieldset>
<legend>New Grumble</legend>
<table border="0">
<tr>
<td>
<label class="control-label" for="details"><span style="color:red;">*</span> Description</label>
<textarea name="details" value="" placeholder="Broken radiator next to vending machine."></textarea>
</td>
</tr>
</table>
<div class="control-group">
<div class="controls">
<input type="submit" value="Submit" class="btn btn-primary"/>
</div>
</div>
</fieldset>
</form>
</template>
Please help me where I am wrong as have read the article : http://www.manuel-schoebel.com/blog/iron-router-tutorial. And tried to make changes but not working. Any pointers please.
I think the route this.route('issues', {path:'/issues'}); overwrites the route this.route('issues', {path:'/'}); (they have the same name!), so you have no route for /. Try changing name on one of them, and see if that makes a different.
You're missing a "/" in front of your grumble route path. It should be this.route('grumble', {path:'/grumble'})

Resources