Store template data as a string in Ember - javascript

I'm using Ember and an upload plugin. The plugin allows me to overwrite it's HTML template through a property as a string.
$("#fileUpload").dropzone({
previewTemplate: ' some huge html string',
});
Adding in a string of HTML would be difficult to support and look awful so I created an external Handlebars .hbs file which houses the template HTML.
Normally I would populate this template without an issue using $.get(). However, I imagine that Ember has a way to do this intelligently. I've dug through the API and haven't seen anything specific to help me with this.
I would think something like var template = Ember.Handlebars.get('upload.hbs'); would work but it returns an error.
Any help would be appreciated.

Just trying to summarise what you are doing, after clarification from my previous (deleted) answer.
You have a plugin, that accepts a plain html string.
The html string you want to provide to the plugin is very long.
You want to store the string as an external file, to avoid including in your regular code.
The html string is not a Handlebars template though you store it as upload.hbs.
You were hoping that Ember would have a method for loading remote templates, that you could use to avoid using jQuery GET.
No method to load remote templates:
The reality is that Ember does not have a built in method for loading remote template files in their raw format. It does however allow you to precompile handlebars templates to JavaScript that can be included as a regular script tag. But as you are not using a handlebars template pre-compilation would do nothing more than wrap your html string in some JavaScript.
There is no such feature documented.
Nor is there in the source code.
Why Ember.Handlebars.get('upload.hbs') won't work:
This method is used to get the content of locally included templates. That means it only looks for templates that exist in the Ember.TEMPLATES array or from the <script> tags of type text/x-handlebars.
The reason why Ember does not have the ability to load remote template files:
It does not have a method for loading in raw handlebars files because:
Many people use the precompiled handlebars files (which can be loaded as remote JS)
Many people use the inline <script type="text/x-handlebars"></script> tags. It's notable that you cannot use the src attribute of script to pull in a handlebars template, because browsers will only accept src for text/javascript.
Ember relies on jQuery, and as jQuery provides suitable methods GET & AJAX it's trivial to implement in conjunction with Ember.Handlebars.compile("<strong>Hello {{name}}</strong>"), if required.
Your template:
As you are not using a Handlebars template and you are just loading html, the correct approach, as you suspected is simply jQuery GET.
$.get( "dropZoneUploadTemplate.html", function(template) {
$("#fileUpload").dropzone({
previewTemplate: template
});
});
Summary
While it is nice to use Ember where possible, this simply is a jQuery task. Sorry it's not the answer you were hoping for. Maybe in future versions of Ember it will include such as feature.
Making the uploader into an Ember Component:
You could turn your uploader into an Ember Component like this, and combine with the jQuery GET to take care of loading in your html.
App.FileUploadComponent = Ember.Component.extend({
template: Ember.Handlebars.compile("<input type='file' />"),
didInsertElement: function(){
var c = this.$(":file");
$.get("dropZoneUploadTemplate.html", function(template){
c.dropzone({ previewTemplate: template });
});
}
});
This would mean every time you want to use the upload control in your Ember templated view you can simply do:
{{file-upload}}
I hope this helps.

Related

django and javascript how to organize

I'm trying to figure out how to organize my javascript/django code.
So far I used to put my javascript page specific code in the same file. i.e I embed javascript in a <script> tag inside the template.
This creates a lot of mess when my JS code become large:
- django template variables {{var}} inside my JS code does not look well,
- I get an error when I try to minify it with tools like this one: http://jscompress.com/ ,
- And I just try to separate them as much as possible.
Today, in my embeded <script> tag my JS code looks like:
var app = {
func: function() {
// can I use the {% url %} tag here ?
$.post('/url/', {csrfmiddlewaretoken:'{{csrf_token}}', something:'value'} )
},
jsonFromServer: '{{pythonDict|safe}}', // I need this data structure,
};
As you can see, there are some values I need to pass form django to javascript, the most common is the csrftoken, for ajax requests. But sometimes I also pass a json dictionary that is needed for the app itself. Sometimes I want to pass the server time as well.
I'm thinking of moving the JS code to a separate file, I read that it is better way to organize like that. But I can't see how it is possible in a normal django app, without django have to render the .js files. And I believe it is better the JS file won't be served by django?
So how could I organize my JS without too much django code in it ?
I Don't know if it's "beautiful" but usually, I organize my code like that when it's about make web dev in MVC:
I put my <script> tag in the template of my page.
I write my js in an external file, traditionally in the /static/JS/my_template_name.js
As my gobal layout can have some JS code too, I make a great use of the JS modules: https://medium.freecodecamp.com/javascript-modules-a-beginner-s-guide-783f7d7a5fcc#.bjf4xwuq4
Usually, I don't have to do that.
When I need var from server in my js code, I make some Ajax calls.
But if you really want to process like that, I can suggest you to do something like this in your template:
<script>
var from_server = {{vars_from_server}};
</script>
Normally, if you pass a variable named vars_from_server to your template it will replace the placeholder between the script tags. Just think to format "vars_from_server" in a correct JS way.
After that, you will be able to access your vars in your scripts by accessing from_server variable from anywhere.

Backbone: managing templates

I'm using underscore template engine for an backbone application. As of now I have over 15 templates in the <head>. Its getting hard to maintain. So far, most of the solutions I seen to manage templates ended up needing them to be js files. That's also a headache, I prefer them to be html files for editing purposes.
I took a look at requirejs and not sure if I need that since it kinda revolves around a more modular approach that I can't say I'm using at the moment (although I will soon).
What will be the best way to manage templates and load/cache them as needed?
Personally we needed a robust solution at my company, so we went with:
Require.js - for module loading
Handlebars - for more powerful templating than Underscore can offer
HBS - an excellent require plug-in from Alex Sexton that handles bringing compiled templates in via Require
With this setup I can keep all of my templates in their own file, and then to use them I have files like this:
define(['template!path/to/someTemplate'], function(someTemplate) {
var MyNewView = BaseView.extend({template: someTemplate});
$('body').append(new MyNewView().render().el);
}
(and as you might guess we have a base Backbone view called BaseView which uses the view's template property to render the view).
Now, all that being said, if you don't need such a robust setup then Require may not be for you. In that case I would do the following:
Put all of your templates in to one or more HTML files; wrap them in script tags, like so:
<script id="dummyTemplate" type='text/template'>
<span>I'm a template!</span>
</script>
Write some code on your server-side to include those HTML files in the main HTML file you send to the client
Write a function which takes a template ID, gets the text of that element, compiles it in to a template, and returns that template (maybe cache the compiled templates if you want ... of course, with Underscore templates I don't think you even need compiling, so you can skip all that).
Use your function to access your templates: $("#something").html(templateFunc('dummyTemplate').template())
This will allow you to store your templates in html files (for syntax coloring), but still access them conveniently in JS. You can also divide your templates between as many files as you want, as long as you can write include logic to bring them in.
If you do opt for Require though, definitely check out the HBS plugin. And if you haven't looked at Handlebars templates yet, you might want to; they're far more powerful than Underscore ones (but like any good templating system, don't allow for too much logic).
Not sure what you mean by it being unmaintainable. Is it just a long list?
You don't need to keep your templates in the head. They can be at the bottom of your body as well. They just need to be defined before you try to use them.
One thing you might look into, depending on the server technology you are using would be to separate your templates into a different HTML file and include it at runtime.

JavaScript templating

I was trying to convince a fellow co-worker into using Mustache/Hogan in the front-end of a project and I proposed the following:
Having a templates.js file, which could roughly look like this:
var tpl_alert = '<div class="alert">{{msg}}</div>';
var tpl_welcome = '<p class="user-{{type}}">Welcome, {{name}}</p>';
...
Then, we would include templates.js and use the corresponding tpl in the Mustache/Hogan.js rendering.
My proposal was turned down, since we're hardcoding html templates into js variables.
Is this really that bad? Which are other alternatives to this?
To answer your question, putting your templates in javascript variables inside a static JavaScript file makes it difficult to maintain your templates. You need to worry about string escaping whenever you want to make a simple change. And 1 syntax error will crash your app.
However, putting all your templates in a single JavaScript file is the fastest way to load your templates.
Your alternatives are:
Storing your templates in seperate files and generating the static template.js file as a prebuild step.
Loading your html template files async through AJAX into javascript variables.
Using a library like Require.js that will load your templates asynchronously as needed into variables.
My preferred way of doing this is to create a separate template file that can be loaded dynamically in development and baked into pure js for production.
Specifically I use eco templates (I wouldn't recommend them unless you're familiar with coffee script) and Stitch for node.js. Stitch supports custom engines tied to file extensions, so when it finds an eco file in my project directory it compiles it into a Javascript function. I can now include that function in any other part of my application using the stitch provided require function using the original path of the eco file. So if the template resided in src/views/listItem.eco I would run var listItemView = require('views/listItem'); to fetch it and use it like this
var html = listItemView({item: items[i]});
$someElement.html(html);
You could use require.js instead of stitch if course, or any other similar framework.

jquery/javascript in rails 3

I was under the impression that you could put javascript in a view template in Rails 3. For example, if I had this html in views/public/home.html.erb
<div id="block">click</div>
then in views/public/home.js.erb, I thought I could put the following javascript, and then click on html to trigger the javascript. However, when I tested it, I got no results. But if I put the javascript in assets/javascript/application.js, then everything worked fine...Shouldn't it also work if it was in a js template with the same name as the html view?
$(document).ready(function(){
test();
});
function test() {
$("#block").click(function() {
$('#block').hide();
});
}
Ummm. no. It just doesn't work that way. Only one of views/public/home.* will be rendered, depending on the responds type.
Javascript shouldn't be added as a view file (bla.js.erb). They must be put in assets/javascripts or at least in lib or vendor directory.
You must also require them in your application.js file, if you already don't use require_tree.
In this way you won't need to reference the javascript in any way in your view (the application.js will include it for you). Otherwise, you need to specify a layout to insert javascript files in block, because views are rendered after tag.
There are a lot of reason not to put javascript directly in html (except for tests obviusly), read the rails asset pipeline for more information.
When you create a view with a different extension from html.erb that will be used only if your url specify a format with that extension, for example mywebsite/users.json will return eventually a index.json.erb.
For AJAX you would like to return a JSON object, not javascript which is definitely not a correct approach. Remember that you are using a framework and you should follow it's guidelines. If you want to live it's rails, it will be hard to work with it.
You can use javascript_include_tag
If you have the js files source1.js, source2.js in public/javascript then you can include them using
javascript_include_tag 'source1', 'source2'

template engine javascript and php/html

Recently I became interested of the jQuery template engine.
For the ajax call is very performant, because the data exchange is less.
But when I load my application the first time, I use only php and html for print the data, so for use this technic do I have to duplicate the template? One for php html and one for javascript?
How could I resolve this problem?
It is possible to use the same templates on the server side and the client. For example, mustache has implementations in several languages including PHP and Javascript. But generally I find it's easier to stick to one approach.
If you're using jQuery templating to render on the client anyway, why not render in Javascript the first time as well. To avoid needing an extra AJAX call, you can inject your data model into the page as a javascript object and pass that into the template renderer.
Here's an example. The json_encode function should be useful for this.
<script type="text/javascript">
// This line gets generated by your PHP code.
// You'll want to use the JSON methods instead of generating it by hand.
var myModel = { name: 'Fred', surname: 'Bloggs' };
$(document).ready(function() {
// Here you render the template using the data that's
// already in myModel
});
</script>
You could try Distal templating engine.
Your HTML page serves as part of the template.
<div>
Hi, <span data-qtext="user.name">Guest</span>
</div>
When you first load it displays "Hi, Guest" then you run the template and you can substitute for "Guest".

Categories