I want to give my users the possibility to create document templates (contracts, emails, etc.)
The best option I figured out would be to store these document templates in mongo (maybe I'm wrong...)
I've been searching for a couple of hours now but I can't figure out how to render these document template with their data context.
Example:
Template stored in Mongo: "Dear {{firstname}}"
data context: {firstname: "Tom"}
On Tom's website, He should read: "Dear Tom"
How can I do this?
EDIT
After some researches, I discovered a package called spacebars-compiler that brings the option to compile to the client:
meteor add spacebars-compiler
I then tried something like this:
Template.doctypesList.rendered = ->
content = "<div>" + this.data.content + "</div>"
template = Spacebars.compile content
rendered = UI.dynamic(template,{name:"nicolas"})
UI.insert(rendered, $(this).closest(".widget-body"))
but it doesn't work.
the template gets compiled but then, I don't know how to interpret it with its data context and to send it back to the web page.
EDIT 2
I'm getting closer thanks to Tom.
This is what I did:
Template.doctypesList.rendered = ->
content = this.data.content
console.log content
templateName = "template_#{this.data._id}"
Template.__define__(templateName, () -> content)
rendered = UI.renderWithData(eval("Template.#{templateName}"),{name:"nicolas"})
UI.insert(rendered, $("#content_" + this.data._id).get(0))
This works excepted the fact that the name is not injected into the template. UI.renderWithData renders the template but without the data context...
The thing your are missing is the call to (undocumented!) Template.__define__ which requires the template name (pick something unique and clever) as the first argument and the render function which you get from your space bars compiler. When it is done you can use {{> UI.dynamic}} as #Slava suggested.
There is also another way to do it, by using UI.Component API, but I guess it's pretty unstable at the moment, so maybe I will skip this, at least for now.
Use UI.dynamic: https://www.discovermeteor.com/blog/blaze-dynamic-template-includes/
It is fairly new and didn't make its way to docs for some reason.
There are few ways to achieve what you want, but I would do it like this:
You're probably already using underscore.js, if not Meteor has core package for it.
You could use underscore templates (http://underscorejs.org/#template) like this:
var templateString = 'Dear <%= firstname %>'
and later compile it using
_.template(templateString, {firstname: "Tom"})
to get Dear Tom.
Of course you can store templateString in MongoDB in the meantime.
You can set delimiters to whatever you want, <%= %> is just the default.
Compiled template is essentially htmljs notation Meteor uses (or so I suppose) and it uses Template.template_name.lookup to render correct data. Check in console if Template.template_name.lookup("data_helper")() returns the correct data.
I recently had to solve this exact (or similar) problem of compiling templates client side. You need to make sure the order of things is like this:
Compiled template is present on client
Template data is present (verify with Template.template_name.lookup("data_name")() )
Render the template on page now
To compile the template, as #apendua have suggested, use (this is how I use it and it works for me)
Template.__define__(name, eval(Spacebars.compile(
newHtml, {
isTemplate: true,
sourceName: 'Template "' + name + '"'
}
)));
After this you need to make sure the data you want to render in template is available before you actually render the template on page. This is what I use for rendering template on page:
UI.DomRange.insert(UI.render(Template.template_name).dom, document.body);
Although my use case for rendering templates client side is somewhat different (my task was to live update the changed template overriding meteor's hot code push), but this worked best among different methods of rendering the template.
You can check my very early stage package which does this here: https://github.com/channikhabra/meteor-live-update/blob/master/js/live-update.js
I am fairly new to real-world programming so my code might be ugly, but may be it'll give you some pointers to solve your problem. (If you find me doing something stupid in there, or see something which is better done some other way, please feel free to drop a comment. That's the only way I get feedback for improvement as I am new and essentially code alone sitting in my dark corner).
Related
I'm just a little desperate.
I installed the RSS Display extension.
http://typo3.org/extensions/repository/view/rss_display
Everything works fine, but I have just a little understanding problem.
I pull myself with fluid the Author for the current feed.
<feed:item.get value="author"/>
Than i look whats inside.
<f:debug><feed:item.get value="author"/></f:debug>
Thats the result.
SimplePie_Author prototype object
name => 'Name Name' (12 chars)
link => NULL
email => NULL
So what i need it's to get the name of the author.
Unfortunately i am not able to get the value.
I am really new in Fluid, Typo3.
Hopefully someone can help me.
One way to do this, is to create a fluid variable author and assign the author object to it. Then you can access the name using {author.name}.
To create a variable, you could use the ViewHelper <f:alias>, like this:
<f:alias map="{author: '{feed:item.get(value: \'author\')}'}">
{author.name}
</f:alias>
Another way would be to use the extension "vhs", which provides many tools for use with fluid. One of these tools is the ViewHelper <v:variable.set>, which could be used like this:
<v:variable.set name="author" value="{feed:item.get(value: 'author\'}"/>
{author.name}
This has the advantage that you don't need to use the variable within the tags of the ViewHelper.
There are other ways to reach the same goal, without defining variables, but this seems to be the easiest one to me.
As we all know, Meteor's initial payload sent to the client comprises (in production) a concatenated javascript file containing the Meteor platform, packages, and all templates parsed into Meteor's reactive templating system. Server-side rendering, where the templates are rendered to HTML and sent to the client in the initial payload, is on its way but doesn't have an expected release date yet.
I'm looking for a way to "hack" or approximate server-side rendering given the available functionality in Meteor 0.8.x. Specifically, I want to:
enable the page to render its initial contents without first waiting for the several hundred KB Meteor platform javascript file to be downloaded and parsed.
alternatively, modify Meteor so it only sends the templates it needs to render the initial request in the javascript payload, and fetches the remaining templates once render is complete.
The use case is http://q42.com. I recognise Meteor isn't the best fit for static websites like this one but I want to try and see how far I can get anyway. Right now the Meteor platform JS file is over 600 KB in size (±200 KB gzipped) and I'd like to reduce this size if possible.
Note: I'm aware of and already using Arunoda's fast-render package, which is intended to send data with the initial payload. In this case I want to cut down on time-to-first-render by also getting the templates themselves down faster.
This is a little bit tricky. But there are some things you could do. This may not be the beeest way to do it but it could help you get started somehow.
Meteor is build with many packages as 'default', sometimes some are not needed. You can remove the standard-app-packages and add the packages (that you need and use manually) listed here: https://github.com/meteor/meteor/blob/devel/packages/standard-app-packages/package.js
To cut down the templates you would have to include the bare templates that you use and include the other template's separately and perhaps send down the Template information via a Collection, using a live observer handle to initiate the templates
You would have to 'render' the templates on the server side or store them manually in your collection using Spacebars.compile from the spacebars-compiler package which is a little tricky but you could have it done decently:
This should give you a rough idea, not sure how to get passed the 'eval' bit of it though:
HTML file in /private/template.html
<template name="test">
Hello {{name}}
</template>
JS file in /private/template.js
Template.test.name = function() { return "Bob" }
Server side code
var collection = new Meteor.Collection("templates");
var templateData = Assets.getText("template.html");
var templateJs = Assets.getText("template.js");
var compiled = Spacebars.compile(templateData).toString();
var jsData = templateJs;
collection.insert({templateName:"test", data: templateData, js: templateJs});
Client Side code
collection.find().observeChanges({
added: function(id, fields) {
var template = fields.data,
name = fields.name,
js = fields.js;
Template["name"] = UI.Component.extend({
kind: "name",
render: eval(template),
});
eval(js);
}
});
Then just subscribe to the collection asking for your template and it should exist. If you use iron-router I think (not sure) you could make the subscription wait before the template is rendered so you could have it work.
Again this is just a 'hacky' solution, one thing I personally don't like about it is the use of eval, but javascript needs to run somehow...
You could loop through files in a particular folder using fs = Npm.require('fs') to render each template too.
One alternative would be to inject a 'script' tag calling the compiled js template and template helpers to let the template exist.
An issue has been noticed on one of our old sites running 2.4 where when the user creates a link in the CMS content, selecting an existing page to link to, the link is not being converted to the actual URL on the front end and all links are coming through in the format of <a href="[sitetree_link_id=12]">
What would be causing this and how do I fix it?
The tag looks like it's being set incorrectly. It should be [sitetree_link id=12], not [sitetree_link_id=12].
We later added support to the parser for [sitetree_link,id=12] so that links didn't need to contain spaces, but I can't recall if that's in 2.4 or only 3.0+.
Can you confirm that your WYSIWYG insertion is putting in that errant _? If so, you might want to checkout the handleaction_insert function in tiny_mce_imporvements.js to confirm that it has a line like so:
case 'internal':
href = '[sitetree_link id=' + this.elements.internal.value + ']';
If the inserted links don't actually have the errant _ but they aren't being parsed, then try checking your sapphire/_config.php file for this:
ShortcodeParser::get('default')->register('sitetree_link', array('SiteTree', 'link_shortcode_handler'));
If your site makes changes to the ShortcodeParser at all you might have inadvertently turned off sitetree_link support.
If all of that looks in order, perhaps the ShortcodeParser isn't being called for some reason. In HTMLText::forTemplate(), put a debug statement (I like die("I got here!");) to confirm that HTMLText::forTemplate() is actually getting called. If it's not, you might need to manually call it in some pre-processing of your Content variable. Instead of this:
$content = $this->Content;
Do this:
$content = $this->obj('Content')->forTemplate();
I hope that one of those answers help. Either way, it would be great if you could post back, so we could isolate what caused this. It might help us make the API easier to use in SilverStripe 3.1.
Are there any open source/free frameworks available that take some of the pain out of building HTML e-mails in C#?
I maintain a number of standalone ASP.NET web forms whose main function is to send an e-mail. Most of these are in plain text format right now, because doing a nice HTML presentation is just too tedious.
I'd also be interested in other approaches to tackling this same problem.
EDIT: To be clear, I'm interested in taking plain text form input (name, address, phone number) and dropping it into an HTML e-mail template. That way the receipient would see a nicely formatted message instead of the primitive text output we're currently giving them.
EDIT 2: As I'm thinking more about this and about the answers the question has generated so far, I'm getting a clearer picture of what I'm looking for. Ideally I'd like a new class that would allow me to go:
HtmlMessage body = new HtmlMessage();
body.Header(imageLink);
body.Title("Some Text That Will Display as a Header");
body.Rows.Add("First Name", FirstName.Text);
The HtmlMessage class builds out a table, drops the images in place and adds new rows for each field that I add. It doesn't seem like it would be that hard to write, so if there's nothing out there, maybe I'll go that route
Andrew Davey created Postal which lets you do templated emails using any of the ASP.NET MVC view engines. Here's a video where he talks about how to use it.
His examples:
public class HomeController : Controller {
public ActionResult Index() {
dynamic email = new Email("Example");
email.To = "webninja#example.com";
email.FunnyLink = DB.GetRandomLolcatLink();
email.Send();
return View();
}
}
And the template using Razor:
To: #ViewBag.To From: lolcats#website.com Subject: Important Message
Hello, You wanted important web links right? Check out this:
#ViewBag.FunnyLink
<3
The C# port of StringTemplate worked well for me. I highly recommend it. The template file can have a number of named tokens like this:
...
<b>
Your information to login is as follows:<br />
Username: $username$<br />
Password: $password$<br />
</b>
...
...and you can load this template and populate it like this:
notificationTemplate.SetAttribute("username", Username);
notificationTemplate.SetAttribute("password", Password);
At the end, you get the ToString() of the template and assign it to the MailMessage.Body property.
I recently implemented what you're describing using MarkDownSharp. It was pretty much painless.
It's the same framework (minus a few tweaks) that StackOverflow uses to take plain-text-formatted posts and make them look like nice HTML.
Another option would be to use something like TinyMCE to give your users a WYWIWYG HTML editor. This would give them more power over the look and feel of their emails, but it might just overcomplicate things.
Bear in mind that there are also some security issues with user-generated HTML. Regardless of which strategy you use, you need to make sure you sanitize the user's input so they can't include scary things like script tags in their input.
Edit
Sorry, I didn't realize you were looking for an email templating solution. The simplest solution I've come up with is to enable text "macros" in user-generated content emails. So, for example, the user could input:
Dear {RecipientFirstName},
Thank you for your interest in {ClientCompanyName}. The position you applied for has the following minimum requirements:
- B.S. or greater in Computer Science or related field
- ...
And then we'd do some simple parsing to break this down to:
Dear {0},
Thank you for your interest in {1}. The position you applied for has the following minimum requirements:
- B.S. or greater in Computer Science or related field
- ...
... and ...
0 = "RecipientFirstName"
1 = "ClientCompanyName"
...
We store these two components in our database, and whenever we're ready to create a new instance from this template, we evaluate the values of the given property names, and use a standard format string call to generate the actual content.
string.Format(s, macroCodes.Select(c => EvaluateMacroCode(c, obj)).ToArray());
Then I use MarkdownSharp, along with some HTML sanitizing methods, to produce a nicely-formatted HTML email message:
Dear John,
Thank you for your interest in Microsoft. The position you applied for has the following minimum requirements:
B.S. or greater in Computer Science or related field
...
I'd be curious to know if there's something better out there, but I haven't found anything yet.
A bit of a followup from a previous question.
As I mentioned in that question, my overall goal is to call a Ruby script after ImageCache does its magic with generating thumbnails and whatnot.
Sebi's suggestion from this question involved using hook_nodeapi.
Sadly, my Drupal knowledge of creating modules and/or hacking into existing modules is pretty limited.
So, for this question:
Should I create my own module or attempt to modify the ImageCache module?
How do I go about getting the generated thumbnail path (from ImageCache) to pass into my Ruby script?
edit
I found this question searching through SO...
Is it possible to do something similar in the _imagecache_cache function that would do what I want?
ie
function _imagecache_cache($presetname, $path) {
...
...
// check if deriv exists... (file was created between apaches request handler and reaching this code)
// otherwise try to create the derivative.
if (file_exists($dst) || imagecache_build_derivative($preset['actions'], $src, $dst)) {
imagecache_transfer($dst);
// call ruby script here
call('MY RUBY SCRIPT');
}
Don't hack into imagecache, remember every time you hack core/contrib modules god kills a kitten ;)
You should create a module that invokes hook_nodeapi, look at the api documentation to find the correct entry point for your script, nodeapi works on various different levels of the node process so you have to pick the correct one for you (it should become clear when you check the link out) http://api.drupal.org/api/function/hook_nodeapi
You won't be able to call the function you've shown because it is private so you'll have to find another route.
You could try and build the path up manually, you should be able to pull out the filename of the uploaded file and then append it to the directory structure, ugly but it should work. e.g.
If the uploaded file is called test123.jpg then it should be in /files/imagecache/thumbnails/test123/jpg (or something similar).
Hope it helps.