I am trying to find a way to add content to a div that is defined in my application.html.haml file from individual view files. The reason I want to do this is because I have a sidebar that is always present and is defined in the template, but I would like to have content specific to each page included in the sidebar. Would this be done best with javascript or is there some ruby on rails trick that I can use to make this easier?
I would use the content_for helper (Rails Guide) (API).
In haml, this would look something like:
(layout template)
#sidebar= yield :sidebar
(page template)
-content_for :sidebar do
...your content here
If you work with professional designers who handle the views, it may be easier over the long term to have rather repetitive view code. Some people have a hard time searching through partials and "seeing" how they all fit together. I've found it easier with those people to let them manage the whole shebang and update more than one file if they need to. Optimal? Not to us as programmers, but designers are more often used to seeing most of the HTML in one or three files rather than 20. :)
use partials as much as possible to keep your code DRY
this link helps you
http://guides.rubyonrails.org/layouts_and_rendering.html
Related
For the first time as a jnr progammer I'm looking at how to write my js code so that it's isolated to certain pages within my Rails app. I figure this is a sensible thing to do for the purposes of;
a) certain js i write I only want to target a certain element on an individual page, not other elements on other pages within the same controller that may get picked up due to using a class selector for example and marking every single thing with unique id's doesn't seem too neat. (I see that rails already has controller isolation through the naming of js files by controller, but further dividing things up into action/page names js files doesn't sound nice either!).
b) perhaps in finding a solution to only running js on certain pages it could mean that the js only needs to be loaded on certain actions thereby saving on load times.
There's a well attended question here with folks approaches here but most answers are 6 years old now and another nice post about the so called 'Garber Irish method of Dom ready execution' here that sounds quite nice, but again this is quite old now and all based on Rails 3...
So without wanting to create duplicate content I'm seeking to get a refreshed answer to this same question and find out whether there's a best practice now established these days.
Thanks
Convention:
Rails when using scaffold generator by default creates corresponding
app/assets/javascripts/MODEL_NAME.coffee
app/assets/stylesheets/MODEL_NAME.scss
which separates JS and CSS logic by "controller" name
Personal Preference:
Rather than controller-based segregation, I prefer layout-component-based segregation. Best explained through a sample code below:
app/assets/javascripts/application.js
//= require_tree ./layouts/
app/assets/javascripts/layouts/__shared.coffee
// WRITE GLOBAL JS LOGIC HERE FOR ANY LAYOUT
app/assets/javascripts/layouts/application/__shared.coffee
// WRITE GLOBAL JS LOGIC HERE ONLY FOR THIS "application" LAYOUT
app/assets/javascripts/layouts/blog/__shared.coffee
// WRITE GLOBAL JS LOGIC HERE ONLY FOR THIS "blog" LAYOUT IF YOU HAVE ANOTHER layout such as "layouts/blog.html.erb"
app/assets/javascripts/layouts/application/components/header.coffee
// WRITE JS code here for the header component
app/assets/javascripts/layouts/application/components/footer.coffee
// WRITE JS code here for the footer component
app/assets/javascripts/layouts/application/components/users/__shared.coffee
// You can also divide a component into subcomponents just like this
// WRITE JS code shared amongst all users subcomponents
app/assets/javascripts/layouts/application/components/users/form.coffee
// WRITE JS CODE HERE regarding the form that creates or updates a User
app/assets/javascripts/layouts/application/components/users/list.coffee
// WRITE JS CODE HERE regarding the table listing all users
You also structure the CSS files in the same way, matching the components
I would like to ask your advice on our situation about dynamic/static loading components.
We're developing a "multi language teaching app" for Android/iOS. For UI text we use ng2-translate plugin (JSON files for each language). For the lesson content we use separate HTML files for each language. In the beginning the user selects a language to learn and then sees related lessons as a list (which comes from a JSON file too). Clicking a lesson loads the related HTML file and dynamically compiles directives/pipes in it (which makes it more interactive). By directives, I mean simple functions like showing a toast when user clicks a custom directive, like this: <example tooltip="explanation to show as a toast">An example sentence</example>. But maybe we can use more complex directives in the future.
Up to building the app, everything goes well in browser. But the AoT compiler does not support "dynamic loader components" in mobile devices, so we need to decide whether or not use this approach. And at that point I'm really confused. We may change our structure but I don't know which way is better.
As far as I can see, we have three options (if there are more, please enlighten me):
Stop using html files and convert each of them into a component with html templates (using AoT compiler (--prod mode)):
Be able to use directives/pipes
Gain interactivity
Gain performance (that's the main purpose of AoT, right? but what if I use hundreds of html pages/components? isn't it a bulky solution?)
Use hundreds of pre-compiled html pages for grammar lessons, stories, texts...
Load pure HTML files into an innerHTML of a loader component (using AoT compiler (--prod mode)):
Don't use directives/pipes
Loose interactivity (except being able to use simple HTML tags like p, strong, em, table etc. --if we count this as an interactive content)
Gain performance a bit (as we use AoT?)
Load HTML files dynamically as components via one dynamic template component (using JiT compiler (--dev mode)):
Be able to use directives/pipes
Use separate html files
Gain interactivity
Loose performance
Do something that Angular generally does not recommend
I can't decide what to do now, if I want more interactivity, I should drop the performance that Angular proposes.
I just wanted to be able to handle these grammar lessons in a simple syntax (like HTML) as seperate files and not to use/declare components for each of them...
What would you recommend?
I asked same question to Ionic forum and I decided to implement the solution of a user that replied to me:
I went through this with Markdown, tried a bunch of things, and here's what I eventually settled on:
Store your objects however is convenient for you. In my case, that's markdown source.
Define two components; we'll call them skeleton and bone for now.
skeleton has an input property giving it the source. In ngOnChanges, you need to parse that source into an array of elements, each corresponding to a different type of bone.
skeleton's template looks something like this:
<template ngFor let-bone [ngForOf]="bones">
<app-bone [bone]="bone"></app-bone>
</template>
Make sure each bone has a discriminator indicating its type, and then the BoneComponent template is a big giant switch:
<blockquote *ngIf="bone.tag === 'blockquote'">
<app-bone *ngFor="let child of bone.children" [bone]="child"></app-bone>
</blockquote>
<br *ngIf="bone.tag === 'br'">
... every other block-level element we support...
Note that this can work recursively if you need it to, in that the
inside of the blockquote case is effectively another skeleton. I'm
using HTML elements here, but the general technique works equally well
for other user-defined components (as types of bones).
I just started looking at plates, as many people are talking about it.
There are some examples for plates with little html snippets, but not really a full-blown template file. So I am wondering how I can separate especially the layout into a layout.html file and the content distributed into several content.html files?
Also, I'd like to know if there are some strategies for multi-language-sites in flatiron.js/plates?
Thanks!
You can do the seperation pretty easily. You can write a function which binds given string into a layout. Now all you need to do is form the string using plates.bind (this is the content) and pass it to that function which uses plates.bind on the layout.html
Example: https://github.com/flatiron/flatiron/blob/scaffolding/lib/flatiron/plugins/plates.js#L64-66
Update: after another day of digging
into this issue, I have found that the
current jQuery template lib provides
no way to do this. this article
describes a good approach.
I would still like to hear of any
additional thoughts on doing this. The
article linked above requires that the
returned string of templates be
inserted into the DOM. Seems as though
leaving the DOM out of this would be
ideal, and less overhead on the
browser. Imagine a large page, with
multiple composite templates that may
not get used. Although, maybe because
the templates are wrapped in a script
tag, there is only a single DOM item per template? Come on, let's
hear some thoughts...
Using jQuery template libs, what's the best way to combine multiple, related, relatively small templates together? Do you need a single <script> tag for each individual template? What about in the case of dynamically pulling these templates via AJAX? Can I combine these templates somehow?
Consider the following:
<script id="movieTemplate" type="text/x-jquery-tmpl">
{{tmpl "#titleTemplate"}}
<tr class="detail"><td>Director: ${Director}</td></tr>
</script>
<script id="titleTemplate" type="text/x-jquery-tmpl">
<tr class="title"><td>${Name}</td></tr>
</script>
Now because these two templates are very closely related (and one depends on the other) it would make sense to consolidate these into a single AJAX call, and get them both at once. I have a few ideas, but I'd like to know if there is common/best way to do this? Currently I pull in a chunk of HTML, and then do a .find() to get the specific peice of HTML for a template... e.g.:
var templatePackage = fancyAjaxCalltoGetTemplates();
"templatePackage" might then look like this:
<div id="templatePkg">
<div id="movieTemplate">
{{tmpl "#titleTemplate"}}
<tr class="detail"><td>Director: ${Director}</td></tr>
</div>
<div id="titleTemplate">
<tr class="title"><td>${Name}</td></tr>
</div>
</div>
I could then do:
var titleTemplate = jQuery.template('titleTemplate', $(templatePackage).find('#titleTemplate') );
and
var movieTemplate = jQuery.template('movieTemplate', $(templatePackage).find('#movieTemplate') );
...let me know what you think... what would you do?
I like the referenced article in your update, except the assumption that you can't cache templates unless you insert them into the DOM. From the jQuery.tmpl documentation,
"To cache the template when using markup that is obtained from a string (rather than from inline markup in the page), use $.template( name, markup ) to create a named template for reuse. See jQuery.template()."
Using this, we can build a javascript template management system that allows us to load as many templates at a time as we need while keeping the DOM clean. On the client, keep a hash of template objects by name. You can use your favorite object based javascript pattern here, but I would think the structure could be like this:
templates[templateName] = {
templateMarkup: markupFromServer,
loadedAt: Date.now(),
compiledTemplateFunction: jQuery.template( templateName, markupFromServer )
}
Then use the templates to generate HTML like this:
templates['unique-name'].compiledTemplateFunction(inputData)
Then, build an unload mechanism to free up memory:
function unload(templateName) {
delete templates[templateName];
delete jquery.template[templateName];
}
Most importantly, you now have a method of storing multiple templates so you can make requests like: $.get('/TemplateManagement/Render', arrayOfTemplateNamesToLoad, loadManyTemplatesSuccess) to load multiple templates at a time. The only thing we need is a controller TemplateManagement that will take an array of template names as an input and return JSON that pairs a template name with its markup. There are a few ways to do this but it seems to me the most convenient is to define partial views for each template. In ASP.NET MVC 3, you can use this technique and RenderPartial to emit each template's markup into a JSON response. You can either name the partial views the same as the templates or map the names in some custom way.
OK, I read the article you reference in this post. As I see it, his way is probably one of the best ways to load up the template page(s). The only thing I don't like is the asynchronous problems that could crop up, esp. if you need to immediately do some templating before the async get returns... plus any binding issues that could happen before it returns something. In several projects I have done I use his "ancient" SSI (server side includes), but I just use something even easier like:
<% Response.WriteFile("this_page_template_file.html"); %>
You could put it anywhere where you'd place a tag. Like he says, just put in only the templates you need, or maybe include two templates: one is a "base" template with commonly-used items and the second one would have the page-specific ones with template references {{tmpl}}.
Is this even close to an answer? ;-)
[First off, great question. I love this topic]
I have no experience with the plugin "jquery-template-libs", but there is a particular lightweight javascript template plugins that are becoming almost a standard and plays very nicely with jQuery, which is probably better suited for the task than JTL, Mustache:
https://github.com/janl/mustache.js
It's got something that's called a "partial" which is essentially a way to include smaller templates within another one. Which sounds like it will help you out a lot.
On top of that there is a library called ICanHaz.js:
http://icanhazjs.com/
ICanHaz essentially extends Mustache to include built in functionality for templates and works incredibly well.
Mustache/ICanHaz allow you to add templates by variable, by a json call or by using tags. The choice is yours.
I know this is an old question but you might want to take a look at Closure-Templates. They provide the kind of functionality you're after with the added advantage of being compiled into JavaScript at compile-time instead of at run-time in each user's browser.
If you do decide to look into using them then I'd suggest using plovr for building them.
I am trying to reorganize my Javascript into JS files and clear out my js from my html... The way I see if is the following.... I would really like some input or any documentation/information confirming my plans - a little uncertain.
Basically if I have a Home.htm file then I will have a home.js file also, notice they are named the same. The home.js will be like the bootstrapper for that page and will assign events (onclick etc)...
I was planning on doing this with all files i.e. login.htm > login.js ...
I was also thinking about have a global.js file which will be included in EVERY page that contains items that are needed in every file..
I also plan on having other js files which I plan on producing in a namespace so that my bootstrapper files can call classes in that namespace to do things like date manipulation etc.. I know JS is not a true OOP language but i have some helper js which allow to create namespaces and better class structures.
Does anyone have a better idea? Am completely going in the wrong or right direction?
I would really like some input, I am trying to separate all my js into separate files but I don't want to repeat myself so I thought of creating those bootstrapper files to take care of everything for the page..
Depending on how you go about it, I think the idea itself is quite reasonable. Namespacing your JS code in an OOP-like fashion is a good idea, and many libraries such as YUI and Dojo already do it.