Use of "#each" with multiple variables in Handlebars - handlebars.js

How to "select" a value with "this" when there are multiple #each in Handelbars ?
{{#each marqueauction}}
{{#each modelauction}}
<div class="results__container--box">
{{this.marqueauction}}
{{this.modelauction}}
</div>
{{else}}
<div class="results__container--box">
<p>Aucun résultat d'enchères n'est disponible pour ce modèle.</p>
</div>
{{/each}}
{{/each}}
EDIT: I want to call my MongoDB database with mongoose and display results in a box container. For that, I loop through my results array.
My Mongoose model:
const DemocarauctionSchema = new Schema({
objectID: {
type: Number
},
cars_getroute: {
type: String
},
gm_url: {
type: String
},
"results": { type: [{
marque: {
type: String
},
model: {
type: String
},
model_year: {
type: String
},
price_str: {
type: String
},
prince_int: {
type: Number
},
price_currency: {
type: String
},
sold: {
type: Boolean
},
auction_house: {
type: String
},
auction_country: {
type: String
},
auction_date: {
type: String
},
auction_datetime: {
type: String
},
auction_url: {
type: String
},
image_urls: {
type: String
},
price_int_eu: {
type: Number
},
}]}
}
I loop through the array in Express/Node:
const [democarauctions] = result;
let marqueauction = [];
for (let i = 0; i < democarauctions.results.length; i++) {
marqueauction.push(democarauctions.results[i].marque)
}
let modelauction = [];
for (let i = 0; i < democarauctions.results.length; i++) {
modelauction.push(democarauctions.results[i].model)
}
...
And I call the results array in my "res.render":
res.render(demo, {
results: democarauctions.results,
marqueauction: marqueauction,
modelauction: modelauction,
modelyearauction: modelyearauction,
etc.})
Now I'd like to render on my HTML multiple box for each result, with marqueauction, modelauction, modelyearauction in each one. I use handlebars.

It is best to avoid this and instead use named block parameters :
{{#each marqueauction as |marque|}}
{{#each modelauction as |model|}}
<div class="results__container--box">
{{marque}}
{{model}}
</div>
{{else}}
<div class="results__container--box">
<p>Aucun résultat d'enchères n'est disponible pour ce modèle.</p>
</div>
{{/each}}
{{/each}}
I'm not sure why you are breaking apart the original collection into multiple collections and then trying to combine them again in the presentation. Just use the results directly.
EDIT: based on your updated question:
{{#each results as |auction|}}
<div class="results__container--box">
{{auction.marque}}
{{auction.model}}
</div>
{{else}}
<div class="results__container--box">
<p>Aucun résultat d'enchères n'est disponible pour ce modèle.</p>
</div>
{{/each}}

Related

Uncaught TypeError: ss.getQuickTypeForKey is not a function at Object.autoFormGetInputValue

I need your help. I have updated Autoform to version 6.0 and my forms doesn't work, I got this error:
Uncaught TypeError: ss.getQuickTypeForKey is not a function
at Object.autoFormGetInputValue [as getInputValue] (autoform-api.js:493)
at HTMLInputElement.<anonymous> (autoform-inputs.js:6)
My template .html autoform: here I have a simple insert autoform in order to insert an image reference and data.
<template name="insertArtForm">
{{#autoForm collection=artCollection doc=user id="insertArtForm" type="insert"}}
<fieldset>
{{> afQuickField name='createdBy' type='hidden' defaultValue=user._id}}
{{> afQuickField name='createdOn' type='hidden' defaultValue=today}}
<h4>Resolución</h4>
<div class="container">
{{> afQuickField formgroup-class="col-md-1" name='width' type='number'}}
<p class='col-md-1'>x</p>
{{> afQuickField formgroup-class="col-md-1" name='height' type='number'}}
</div>
{{> afQuickField name='name' type='text'}}
{{> afQuickField name='description' type='textarea'}}
{{> afQuickField name='prixQuote' type='text'}}
{{> afQuickField name='artURL' type='text'}}
</fieldset>
<button type="submit" class="btn btn-default" id="js-insert-art-form">Guardar</button>
{{/autoForm}}
</template>
My .js events:
Template.insertArtForm.events({
"click #js-insert-art-form": function(e){
console.log("entra en el evento");
$(".js-save-label").css("visibility","visible");
window.setTimeout(function() {
$(".js-save-label").fadeTo(500, 0).slideUp(500, function(){
$(this).remove();
});
}, 3000);
}
});
My schema:
import { Mongo } from 'meteor/mongo';
import { Index, MinimongoEngine } from 'meteor/easy:search';
import SimpleSchema from 'simpl-schema';
SimpleSchema.extendOptions(['autoform']);
/*Create and export Arts Collection*/
export const Arts = new Mongo.Collection('arts');
/*Arts index for easy:search*/
export const ArtIndex = new Index({
collection: Arts,
fields: ['name'],
engine: new MinimongoEngine(),
});
//Define Art schema
Arts.schema = new SimpleSchema({
createdBy: { //Owner
type: String,
label: "Artista",
regEx: SimpleSchema.RegEx.Id,
optional: true
}, createdOn: {
type: Date,
label: "Fecha",
optional: true
}, height: {
type: String,
label: "Alto",
optional: true
}, width: {
type: String,
label: "Ancho",
optional: true
}, name: {
type: String,
label: "Nombre de la obra",
optional: true
}, description: {
type: String,
label: "Descripción de la obra",
optional: true
}, prixQuote: {
type: String,
label: "PrixQuote",
optional: true
}, artURL: {
type: String,
label: "URL de la obra",
optional: true
}
});
/*Attach the Arts schema for automatic validations*/
Arts.attachSchema(Arts.schema);
I'm really desperate.
I also had this issue. Be sure to have the latest node simpl-schema installed in your packages.json. I upaded to "simpl-schema": "0.2.3" and the error went away.

Sort array based on startDate

I'm trying to sort an array and not having much luck. If I remove the helper I print out the all the qualifications in the order they went into the database. I would like to display them chronologically based on their startDate.
Path: dbExample
"profile": {
"CV": {
"education": [
{
"qualification": "Arts Degree",
"startDate": "2009-01-01T00:00:00.000Z",
"endDate": "2013-12-01T00:00:00.000Z"
},
{
"qualification": "Science Degree",
"startDate": "2007-01-01T00:00:00.000Z",
"endDate": "2008-12-01T00:00:00.000Z"
}
]
}
}
Path: education.html
<template name="education">
{{#each educationHistory}}
<div class="box">
<p class="title">{{qualification}}</p>
<p class="dates">{{startDate}} - {{endDate}}</p>
</div>
{{/each}}
</template>
Path: education.js
Template.education.helpers({
educationHistory: function () {
return Meteor.users.find({}, {sort: {"startDate": 1}});
}
});
Path: Schema.js
Schema.Education = new SimpleSchema({
qualification: {
type: String,
optional: true
},
startDate: {
type: Date,
optional: true
},
endDate: {
type: Date,
optional: true
}
});
Schema.CV = new SimpleSchema({
education: {
type: [Schema.Education],
optional: true
}
});
This is a little hard to follow because I don't know the context of the template or which user's education history to use. Here are a couple of solution ideas:
solution 1
Template.education.helpers({
educationHistory: function () {
// replace Meteor.user() with Meteor.users.findOne(someId) or something
const { education } = Meteor.user().profile.CV;
return _.sortBy(education, e => e.startDate);
},
});
This returns an array of education objects, sorted by startDate.
solution 2
If the template already has an educationHistory without the helper (based on your comments below), then you can replace the educationHistory helper with this:
Template.education.helpers({
sortByStartDate: function (education) {
return _.sortBy(education, e => e.startDate);
},
});
Then in your template:
<template name="education">
{{#each sortByStartDate educationHistory}}
<div class="box">
<p class="title">{{qualification}}</p>
<p class="dates">{{startDate}} - {{endDate}}</p>
</div>
{{/each}}
</template>

How to add user id information in the schema and also hide form autoforms?

I am learning the ropes of Meteor and kind of lost here. I am using collections2, autoform for building my application. I want to store the collection along with user id information. So that when we retrieve the collection from the server, I want to show only the ones the user created not everything else. here is the schema.
ExercisesSchema = new SimpleSchema({
"name": {
type: String,
label: 'Name'
},
"workout.$.weight": {
type: String,
label: 'Weight'
},
"workout.$.reps": {
type: String,
label: 'Reps'
},
"notes": {
type: String,
label: 'Notes',
optional: true
}
});
on the server side I want to show only the workouts created by the user
Meteor.publish('exercises', function () {
return Exercises.find({owner: this.userId});
});
When I added the user id to the schema, it shows up in the autoform, I am not sure how to hide it, if I hide it, then possibly I can use hooks in the autoform to add the values?
In the schema you can define the ownerId as type: "hidden"
schema.js
ExercisesSchema = new SimpleSchema({
"name": {
type: String,
label: 'Name'
},
"ownerId": {
type: String,
autoform: {
type: "hidden",
}
},
"workout": {
//not sure if you need this, you didn't have it in your
type: [Object],
defaultValue: []
},
"workout.$.weight": {
type: String,
label: 'Weight'
},
"workout.$.reps": {
type: String,
label: 'Reps'
},
"notes": {
type: String,
label: 'Notes',
optional: true
}
});
And populate it with the hooks as you said.
autoFormHooks.js
AutoForm.hooks({
exerciseForm: {
formToDoc: function(doc) {
doc.ownerId = Meteor.userId();
return doc
},
}
});
An alternative to using hooks would be to use a quickFields inside of your autoForm for each field that you want to set in the doc, including ownerId. With this solution you would set the value of ownerId to currentUser.
{{#autoForm collection="Exercises" id="exerciseForm" type="insert"}}
<fieldset>
<legend>Add an Exercise</legend>
{{> afQuickField name='name'}}
{{> afQuickField name='notes'}}
{{> afQuickField name='ownerId' value=currentUserId}}
{{> afQuickField name='workout'}}
</fieldset>
<button type="submit" class="btn btn-primary">Insert</button>
{{/autoForm}}
template.js
Template.formTemplate.helpers({
currentUserId: function () {
return Meteor.userId();
}
});
You could try the before hook approach:
ExercisesSchema = new SimpleSchema({
...
"ownerId": {
type: String,
autoform: {
type: "hidden",
}
},
...
});
In your template:
{{#autoForm collection="Exercises" id="exerciseForm" type="insert"}}
<fieldset>
<legend>Add an Exercise</legend>
{{> afQuickField name='name'}}
{{> afQuickField name='notes'}}
<!-- Notice I've removed the ownerId from here. Will be added before saving to collection -->
{{> afQuickField name='workout'}}
</fieldset>
<button type="submit" class="btn btn-primary">Insert</button>
{{/autoForm}}
Then your autoform.js
var addUserHook = {
before: {
insert: function(doc) {
if(Meteor.userId()){
doc.ownerId = Meteor.userId();
}
return doc;
}
}
}
AutoForm.addHooks('exerciseForm', addUserHook);
The above adds the ownerId on the fly just when about to save to collection.
As stated in the docs on atmospherejs.com/aldeed/autoform:
For example, you might want to add the current user's ID to a
document before it is inserted. You can use "before", "formToDoc", or
"formToModifier" hooks to do this.

Meteor collection2 field in $unset list

I have a simpleSchema:
imageUrl: {
type: Object,
optional: true,
autoValue: function() {
if (Meteor.isClient) return;
var imageField = this.field('imageId');
if (!imageField.isSet){
this.unset();
} else {
var imageObj = MealsImages.findOne(imageField.value);
if (imageObj){
return {thumb: imageObj.S3Url('thumb'), big: imageObj.S3Url('big')};
}
}
},
autoform: {
label: false,
type: 'hidden',
afFieldInput: {
type: "hidden"
}
}
},
For some reason, when I update the record this field always appears in $unset array:
Meteor.methods({
mealUpsert: function(doc, mealId) {
check(doc, Meals.simpleSchema());
console.log('test7');
console.log(doc);
if (mealId){
Meals.update({_id: mealId}, doc);
} else {
mealId = Meals.insert(doc);
}
return false;
}
});
Will print:
I20150830-21:49:39.560(-4)? { '$set':
...
I20150830-21:49:39.562(-4)? '$unset':
I20150830-21:49:39.562(-4)? { imageUrl: '',
...
I'm using autoform:
<template name="mealUpdateForm">
<div class="meal-content">
{{> quickForm collection="Meals" doc=this id="mealUpdateForm" meteormethod="mealUpsert" type="method-update"}}
</div>
</template>
And will never be updated or set. Any clue why field could appear in $unset list?
I think I've figured this out - you have a this.unset() in your autoValue for imageUrl. This is called whenever you omit imageId from the modifier, even if it is already present in a document you are modifying!

AutoForm.getFieldValue for array fields

I have a schema declared as:
JobSchema = new SimpleSchema({
responsibilities: {
type: [String],
optional: true
},
'responsibilities.$': {
min: 2,
autoform: {
afFieldInput: {
class: 'form-control'
},
placeholder: 'E.g. "Build tools according to specifications"'
}
}
});
Also I have an UI helper declared as:
Template.registerHelper('currentFieldValue', function (fieldName) {
return AutoForm.getFieldValue('insertJobForm', fieldName) || '';
});
I have a template where I used this helper to generate a form preview. It works like charm for all fields except the array ones. Nothing is being rendered. Any ideas?
{{# if currentFieldValue "responsibilities"}}
<h3>Responsibilities</h3>
{{{currentFieldValue "responsibilities"}}}
{{/if}}
A quick and dirty workaround:
job_create.js
Template.jobCreate.helpers({
responsibilities: function() {
var formData = AutoForm.getFormValues('insertJobForm');
return formData.insertDoc.responsibilities || [];
}
});
job_create.html
{{# if responsibilities}}
<h3>Responsibilities</h3>
{{responsibilities}}
{{/if}}

Resources