SendGrid map dynamicTemplateData to the same template multiple times - sendgrid

I basically want to be able supply an array of objects to the dynamicTemplateData. When the template in Sendgrid receives this data, it should replicate the template within the email its creating for each object in the array. Is this currently possible, or would I need to send separate emails for each object?

Twilio SendGrid developer evangelist here.
In a SendGrid dynamic template you use handlebars to render the data into the email. If you have an array of items you can iterate through the array to render each of the object using the #each function.
For example, with the data
{
"user": {
"orderHistory": [
{
"date": "2/1/2018",
"item": "shoes"
},
{
"date": "1/4/2017",
"item": "hat"
}
]
}
}
You can write a template like this:
<ol>
{{#each user.orderHistory}}
<li>You ordered: {{this.item}} on: {{this.date}}</li>
{{/each}}
</ol>
And it will render:
<ol>
<li>You ordered: shoes on: 2/1/2018</li>
<li>You ordered: hat on: 1/42017</li>
</ol>
There are more examples in the documentation.

Related

Dynamic Template in SendGrid: check a string

I'm creating a dynamic template in SendGrid. I want to change the color of a field based on a field in my case Success.
For example, this is my json.
{
"Environment": "[DEV] ",
"RunAtTime": "09/06/2020 11:29:02 +01:00",
"Status": "Success",
"OrganisationId": "6",
"OrganisationName": "Test",
"InvoiceId": "2",
"InvoiceRef": "Acme Ltd., A1 Taxis",
"Amount": "50.00"
}
Following the documentation, I tried to do something like
{{#if this.Status = 'Success'}}
#00b300
{{else}}
#ff0000
{{/if}}
I found example only for boolean field.
My goal is to change the text color based on a field. What is the best way to do that?
Sendgrid doesn't allow to check strings like this
Please modify code as below
{{#equals this.Status "Success"}}
Reference link for other conditions statements:
https://sendgrid.com/docs/for-developers/sending-email/using-handlebars/#conditional-statements

Meteor: access user's name and profile_picture from the users collection by id

I have 2 collections in my project : Users & Topics
In the topics collection I have a 'createdBy' field that stores the '_id' of the user.
*Sample object*
{
"_id": "SNj6C5fqMntSCaXdL",
"opic": "Best Gaming Laptop",
"tags": [
"games",
"technology",
"product"
],
"createdBy": "uzsMa4fZgmrrAD9ea",
"createdAt": "2016-03-06T21:25:38.672Z"
}
In the users collection I have the fields'_id', 'name' and 'profile_picture_url' for every user.
{
"_id": "uzsMa4fZgmrrAD9ea",
"createdAt": "2016-03-03T03:48:05.787Z",
"name": "Karan Sarin",
"profile_picture_url": "https://pbs.twimg.com/pro2_normal.jpg"
}
I am iterating over topics and showing a list of all topics and would like to show the profile picture and name of the creator.
{{#each topics}}
<h2>{{topic_title}}<h2>
*Profile picture here* *User's name here*
{{/each}}
P.S. I don't want to store the user's picture and name in the topics collection. Just want to access them from the user's collection when needed.
Perhaps the easiest way to accomplish what you're after is to have the name as a part of the schema that gets stored to the topics when they're created. Then you can simply call {{name}} in your template. For your profile image you would want to create a custom variable in the template. Something like {{getProfileImage userId}}. Then write a template helper in a file like common.js to pull the profile image based on the userId.
You could implement a helper function which returns the document of the user who created the topic. After that, you could use the #with expression to set the data context to the user document which corresponds to the current topic.
For example:
Template.topicsList.helpers({
user: function () {
return Users.findOne({_id: this.createdBy});
}
});
<template name="topicsList">
{{#each topics}}
<h2>{{topic_title}}<h2>
{{#with user}}
<img src="{{profile_picture_url}}" alt="{{username}}">
<strong>{{name}}</strong>
{{/with}}
{{/each}}
</template>
Please pay attention that you subscribe also to the required documents in the Users collection.

Using Dynamic templates correctly in Meteor

Passing values dynamically through templates in meteor fails, whereas doing so statically succeeds. What am I doing wrong? The set-up is as follows
I have the following 2 templates set-up in Meteor
<template name="search">
{{#each cards}}
{{>card}}
{{/each}}
<template name="card">
<div class="card">
{{docName}}
</div>
</template>
Passing values to this like this works perfectly
if (Meteor.isClient) {
Template.search.helpers({
cards: [
{docName: "Dr. Maga" },
{docName: "Dr. Macha" },
]
});
}
However, passing the same values dyamically like this fails
Cards = new Mongo.Collection("cards");
if (Meteor.isClient) {
Template.search.helpers({
cards: function() {
return Cards.find({});
}
});
}
There is data in the mongo collection "Cards". I insert it after the app starts by using
db.Cards.insert({ docName: "Hello world!", createdAt: new Date() });
and verify it using the following command
db.Cards.find()
which returns
{ "_id" : ObjectId("558b0a1394990bf66c75775d"), "docName" : "Hello world!", "createdAt" : ISODate("2015-06-24T19:50:42.996Z") }
What am I doing wrong?
The error was that the Cards collection was defined on the client side only. (Under the Meteor.isClient() Code block).
This means that meteor was trying to read from the Server, couldn't find the item coz it wasn't defined in the server side, and failed.
Solution is to define it in the "both" folder so that both server and client can access the collection.
http://docs.meteor.com/#/basic/filestructure
Of course, don't forget to publish and subscribe to the collection.

MeteorJS: Autoform + CollectionFS, associating images from an FS.Collection with Corresponding Mongo.Collection Document?

I'm building a very small Meteor application simply to get a better understanding of Autoform and CollectionFS, and their use together. I currently have everything set up with the following packages:
iron:router, aldeed:autoform, aldeed:collection2, cfs:standard-packages,
cfs:filesystem, cfs:autoform
I have a sample Mongo Collection assigned to "Books" set up with a SimpleSchema attached, with fields from the demo like title and author. The corresponding code for the file upload is:
fileId: {
type: String,
autoform: {
afFieldInput: {
type: "cfs-file",
collection: "images"
}
}
}
The FS.Collection code is:
Images = new FS.Collection("images", {
stores: [new FS.Store.FileSystem("images", {path: "~/uploads"})]
});
This is in conjunction to a quickform: {{> quickForm collection="Books" id="insertBookForm" type="insert"}}
The insert is fine, and I can iterate over the documents and display the various fields using spacebars and a helper function called "books", like so:
{{#each books}}
<li>{{title}} by {{author}}</li>
{{/each}}
I can also iterate over images uploaded to the FS.Collection with a helper returning the entire collection called "files," and looping over them like so:
{{#each files}}
<img src="{{this.url}}" />
{{/each}}
The issue I'm having is linking the two together. I want to be able to do something along the lines of:
{{#each books}}
<li>{{title}}, by {{author}} <img src="The-Corresponding-Image}}" /></li>
{{/each}}
Obviously not that exact layout, but I basically just want to be able to print images with their corresponding titles and authors to be able to use autoform with collectionfs for my needs.
I'm stuck trying to retrieve the fileId from a specific document in the Books collection, and then plugging that into an Images.findOne({fileId: fileId}) and linking the two together.
Can anyone point me in the right direction?
I was able to figure it out thanks to Ethaan's guidance. What I had to do was the following:
Autoform Hook:
AutoForm.hooks({
insertBookForm: {
after: {
insert: function(error, result, template) {
insertedFile = Books.findOne(result).fileId;
Images.update({_id: insertedFile}, {$set: {'book': result}});
}
}
}
});
I set a field of 'book' to the _id of the document being inserted (stored in the result parameter) right after it was inserted.
This is my corresponding HTML:
{{#each books}}
<li>{{title}} by {{author}}</li>
{{#with files}}
<img src="{{this.url}}" />
{{/with}}
{{/each}}
And my helpers:
Template.layout.helpers({
books: function () {
return Books.find({});
},
files: function() {
return Images.findOne({book: this._id});
}
});

mongodb query field in object that is being edited

How can I query a field in an object? My html retrieves all the objects in array called 'postcards'
Meteor.user.profile.postcards [
{
_id: 84fh83f,
field_one: "a name",
field_two: " winter whether",
field_three: " lost more writing"
},
{
_id: 6jsf58s,
field_one: "another name",
field_two: " topical issues ",
field_three: " lost more writing"
}
]
Note: I used random.Id() so each object in the array can be uniquely identified.
Setting a session value to this._id when the user is focused on the input field will retrieve this unique id, however, I would like to query the actual field in focus. The value in these fields are projected within the text input area by using the spacebars syntax within the html.
Can I somehow assign the name within the curly braces of the value attribute to a variable? Then query?
Is there a whole new way to achieve this?
I want to update that specific field in this object instead updating the entire object.
HTML:
{{#with currentUser.profile}}
{{#each postcards}}
<input id="one" value="{{field_one}}" type="text">
<input id="two" value="{{field_two}}" type="text">
<input id="three" value="{{field_three}}" type="text">
{{/each}}
{{/with}}
client.js
Within events, I would like to update the field on focus upon keyup.
Templates.myTemplate.events({
'keyup input[type=text]': _.throttle(function(event) {
Meteor.users.update(this._id, {$set: {**fieldbeingedited**: event.target.value}});
}, 500);
});
What you want to have is an ES6 capability named 'Computed property names'.
This is what is looks like :
var x = 'hello',
obj = {
[x]: 'world'
};
console.log(obj); // Object {hello: "world"}
You have two options :
- you use the meteor harmony package to transpile your es6 to es5 (https://github.com/mquandalle/meteor-harmony)
- you build your object first
To build you object first :
var obj = {};
obj[ this.targetField ] = event.target.value
Meteor.users.update(this._id, {$set: obj});