Alternative to Dynamic Includes In Jade - templates

What is an alternative solution to trying to use dynamic includes using express + jade? Here is what I'm trying to do with the following setup:
routes
index.js
widgets.js
views
widgets
widget1.jade
index.jade
widget.jade
app.js
In app.js, I specify the following route:
app.get('/widgets/:widget', widgets.widgets);
In my widgets route, widgets.js I have:
exports.widgets = function(req, res){res.render('widgets/' + req.params.widget);};
This gives me the ability to view a widget on its own by browsing to /widgets/widget1. This works great. I can also include a widget in another view like this
include widgets/widget1
This works great too. However, I now want to add widget2 and I want to sometimes show widget1 and sometimes show widget2 within another page. I had hoped to pass a variableWidgetName into the view and then reference it like this:
include widgets/#{variableWidgetName}
This fails. When I try to access page, I get a 500 error stating that no such file or directory views\widgets#{variableWidgetName}.jade exists. Clearly I cannot reference variables for includes.
What other options do I have. If this is a limitation in Jade, is there a different approach that I should be using? I've thought of loading the widget via ajax but hoped for a better solution using jade or express.
Does anyone know of a better way to do this?

Try using partial instead of include.
Here is what works for me (I use harpjs.com with jade, which uses "jade": "0.35.0"):
- var name = "something"
!= partial('./'+name+'/hello.md')`

Related

How do you add parameters to the current URL?

I want to add a language modifier via query, by adding "?lang=xx" to the current URL.
I'm currently using something like this:
=link_to request.request_parameters.slice(:lang).merge(lang: 'en')
This is fine, except it adds "welcome/index" or the correspondent route when I use customized routes, which is not great for sharing links.
I also tried this:
=link_to "#{request.path}/?lang=en"
Simple, it works, but doesn't allow me to remove unwanted parameters.
I read somewhere that there was one of these that was supposed to not include "welcome/index", I've already tried request.query_parameters and request.request_parameters, both include 'welcome/index' when I do something while on my website's root.
I could add conditionals and remove the controller and action when I'm in a customized route, but I think that's unnecessary work.
Is there a clean way to do this without overengineering a solution?
I'm currently on Rails 4.2.5 and thinking on upgrading to 5.0.
Guess I had to overengineer it. This is the simplest implementation I could think of:
Slim:
=link_to_if request.path == '/', 'Home', root_path(lang: :en) do
=link_to 'Not Home', request.request_parameters.slice(:lang).merge(lang: 'en')
I know it's two lines, I just hate adding more code than it'd seem necessary.

TextField View Helper - Ember.Handlebars.helpers.view.call is not a function

I'm working on upgrading my grunt CLI based ember 1.8 app to 1.10 with HTMLbars & have made progress, but my view helpers and components don't work; such as date-input, ember-select, bing-map, product-item. So I'm starting with the date-input view helper which returns this error now - "Ember.Handlebars.helpers.view.call is not a function". This input control is rendered via {{date-input... which is associated to 'DateInputView' in views/date-input.js which extends Ember.TextField. It's also associated to helpers/date-input.js and Ember.Handlebars.makeBoundHelper(). The function inside returns Ember.Handlebars.helpers.view.call() which results in the error. I read something about how maybe my template compiler isn't the new one required or maybe a Component should be used rather than a View Helper, but it seems like there should be a simple fix for the View Helper, don't you think?
Development of this viewHelper was done by another party and the purpose of the callback making a call to viewHelper is a mystery. Regardless, the use of viewHelpers is being discouraged going forward and I've re-worked the date-input as a Component.

Emberjs - unable to redefine named, explicitly compiled Handlebars template

As part of an attempt to port a fairly large/complex existing application to the Ember world, I'm generating and compiling named Handlebars templates dynamically, and associating views with them, using the technique:
var template = Ember.Handlebars.compile("some handlebars stuff");
Ember.TEMPLATES["myTemplate"] = template;
var view = Ember.View.create({
templateName: "myTemplate"
});
One of the things I'd like to do is be able to recompile new/different Handlebars template markup which overwrites the template named "myTemplate" and have it be accessible to views at that name.
I'm getting unexpected results trying to do this - a couple fiddles that illustrate the problems:
First fiddle - Shows what happens if you wait before rendering a view after the named template contents have changed.
Second fiddle - Shows what happens if there's no delay before rendering a view after the named template contents have changed.
There's obviously some magic under the hood that I'm not understanding. Can anyone shed some light on this?
UPDATE:
I went through the source code for Ember.View and the container module, and came to realize that I could solve the problem in the First fiddle by overriding the "template" computed property in a way that skips the container cache lookup. I've put up another fiddle here to demonstrate the solution I found.
This seems to be working the way I'd like it to - but - it feels like I might be fighting with the framework and "unhooking" from the container in a way that might bite me later. Is there a better, more Ember-esque way to accomplish what I'm trying to do? Will the hack I found break things?
UPDATE 2
I've also discovered that it's also possible to simply call
view2.get('container').reset();
before appending view2 in the First fiddle. Seems cleaner/safer, but is it "legal"? I've updated the First fiddle to illustrate this.
(in the second fiddle, both views show the second template)
This is because view1.appendTo($("#target")); just schedules the append, actual view rendering does not happen until end of the run loop. Before that happens, you've set Ember.TEMPLATES["myTemplate"] = template2;
(in the first fiddle, both views show the first template)
Pretty sure this is because ember container caches template fx, but not 100% on that. Checking...
I'm going to call this one answered. As I mentioned in my second comment, I'm using the solution shown in this fiddle in my project, along these lines:
mYiew.get('container').reset();
There's some discussion about the container not being intended to be used as an API here: https://github.com/emberjs/ember.js/commit/5becdc4467573f80a5c5dbb51d97c6b9239714a8 , but there doesn't seem to be any mention of using the container from Views for other use cases.
Also, a View's container can be accessed directly (at ".container") - meaning the devs haven't made it "hard" to get to the way they have for an Application's ".__ container __". This might suggest something about how they intend it to be used.
Since a View having the ability to clear its cache whenever it wants to doesn't seem to me to be unreasonable or a bad practice, I'm using the above mentioned solution...at least until someone sets me straight with a better idea (or a cache API).

Templating in Kohana Framework 3.3

I'm using Kohana Framework and this is actually the first framework that I am using. I just wanted to know how to properly add templates in views. What I am doing right now is.
In controller.
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Welcome extends Controller_Template {
public $template = 'site';
public function action_index()
{
$this->template->header = View::factory('templates/header');
$this->template->header->title = 'Page name - Welcome';
$this->template->header->description = 'Blah blah blah.';
}
Now inside view I make a file called site.php (the view) and echo the variable $header on the top so it shows the contents of the page, and it's working fine but is it actually the right way to do it? I mean echoing out the header in every single view? I'm sure there must be a more complex or better way to do that. I have also heard that the use of Kohana Templete is discouraged.
Have a look at the Mustache Plugin KOstache for Kohana. IMO the best way to separate your layout from your logic.
Have a look at Kostache
It allows you to do simple things like
<li>{{kostachevariable}}</li>
You just create the view extending Kostache class and that's it.
Once you do that you can just set variables using
$pagetitle="My Title"
$myview-bind('mypagetitle',$pagetitle)
In your template file you will only need
<head>
<title>{{mypagetitle}}</title>
It has tons of other nice features.

How to set a controller property and update a template in Ember.js

I am trying to show a TopController property in a TopView template. In TopView, I have sectionBinding: 'controller.section'.
From my understanding of Ember.js, in TopView, the controller property should refer to my TopController. Yet it seems to refer to ApplicationController? Read on:
In my router, I have router.set('topController.section', 'index');... But that doesn't seem to do anything in this case. Changing it to router.set('applicationController.section', 'index'); works and the {{section}} part in the TopView template changes to "index".
I have created two fiddles showing my issue. The first one doesn't work:
FAULTY -> http://jsfiddle.net/8tQ4q/4/
The second one does work:
WORKS -> http://jsfiddle.net/8tQ4q/5/
The only difference is the topController / applicationController part in router.set(). Any idea what I am doing wrong?
I'm not sure why you're expecting topController to be connected to TopView. You haven't done anything to make this connection. I think you may be confused because connectOutlet('top') would create a TopView that is connected to topController. However, you aren't doing this anywhere in your app.
You also don't need the sectionBinding. If you have a controller defined on your view, it will be the default context.
I think what you want to do is this:
router.get('topController').set('section', 'index');