I am totally newbie with Kohana and have been reading Docs, tutorials and forum posts to know how it works.
I am trying to implement this framework on one of my application and now I am stuck at managing multiple templates and it's assets.
Basically my application will have a templates folders like template1, template2 .... and all the images, css, js related with particular template needs to contain within the template folder.
So is it possible to have such implementations? If so how can I load template specific assets to the parent template files?
In short Yes
I use templates myself on a site I made with Kohana 3.0. I'll try to explain the basic setup of it; to use templates your controllers need to extend Controller_Template and the $template variable inside specifies what template page to load in your views folder, so I made my own master controller class that extends the controller_template class to manage which template to load; below you'll see my default template's name is simply template so it'll load template.php from my views folder if one isn't specified on my controllers.
I have a master.php master controller with a class definition of (dumbed down)
abstract class Controller_Master extends Controller_Template
{
public $template = 'template'; // Default template
public function before()
{
// Set a local template variable to what template the controller wants to use, by default 'template'
$template = $this->template;
// This is important and for abstraction, since we're extending a class and its functions we need to make sure we still execute its before(); function
// This will load the view you need from /views/template.php or /views/template2.php depending on what your controller specifies into $this->template
parent::before();
// Check which template our code/controller needs to use
if ($template == 'template')
{
$this->template->header = View::factory('template/head'); // Loads default header file from our views folder /views/template/head.php
$this->template->content = View::factory('template/index'); // Loads default index file from our views folder /views/template/index.php
$this->template->footer = View::factory('template/footer'); // Loads default footer file from our views folder /views/template/footer.php
return;
} elseif ($template == 'template2')
{
$this->template->header = View::factory('template2/head'); // Loads default header file from our views folder /views/template2/head.php
$this->template->sidebar = View::factory('template2/sidebar'); // Loads default sidebar file from our views folder /views/template2/sidebar.php
$this->template->content = View::factory('template2/index'); // Loads default index file from our views folder /views/template2/index.php
$this->template->footer = View::factory('template2/footer'); // Loads default footer file from our views folder /views/template2/footer.php
return;
}
}
}
I have a user.php user controller with a class definition of
// This is important, make sure your controllers extend your master controller class
class Controller_User extends Controller_Master
{
// In this example this user controller just needs to use the default controller
// so nothing needs to be changed on it besides extending our Controller_Master
// Example action inside the user class on how to load different content into your template instead of the default index page.
function action_login()
{
// Load the login view page from /views/template/forms/login.php
$this->template->content = View::factory('template/forms/login');
}
}
Now lets say we have a controller that needs to use a different template so lets say
you have have a photo.php photo controller with a class definition of
// This is important, make sure your controllers extend your master controller class
class Controller_Photo extends Controller_Master
{
// Since this controller needs to use a different template we extend the before() function
// to override the $template variable we created in master to use 'template2'
function before()
{
$this->template = 'template2';
}
}
/views/template.php contains something like
<body>
<div id="header">
<?= $header; ?>
</div>
<div id="content">
<?= $content; ?>
</div>
<div id="footer">
<?= $footer; ?>
</div>
</body>
/views/templat2e.php contains a different layout like
<body>
<div id="header">
<?= $header; ?>
</div>
<div id="sidebar">
<?= $sidebar; ?>
</div>
<div id="content">
<?= $content; ?>
</div>
<div id="footer">
<?= $footer; ?>
</div>
</body>
Where's $header, $sidebar, $content, and $footer are set in the master controller or overwriten by the code in your controller by $this->template->header and so forth.
Hopefully that explains enough how to work with templates in Kohana.
I'd advise against structuring your assets this way because you won't be using the framework as it was intended.
CSS, JavaScript and Images should really be stored outside of the main application directory
e.g.
application/
modules/
system/
assets/
template1/
css/
styles.css
js/
script.js
img/
thing.jpg
template2/
css/
styles.css
js/
script.js
img/
another-thing.jpg
Otherwise every asset request is going to be routed through the framework which is going to impact on the responsiveness of your application.
If you still want to go down this path have a look at the action_media method in /modules/userguide/classes/controller/userguide.php to see how CSS, JavaScript and Images are loaded by the userguide module.
Alternatively you could amend your .htaccess rules to allow access to asset files beneath the application directory.
Related
I'm new to express JS and try to build CMS like this:
Users have a page builder, where they can drag-and-drop different components on the page.
each component has its own data which also is defined by a user
Each component has its own view template
So, I have to check what components have to load, prepare data for each of them, send this data to an appropriate template, render one big HTML and send to the client.
I know, It's too complicated to explain how to build this, but any tutorials, examples, resources would be appreciated.
IIUC, you can accomplish this using the include function that most template languages have. For the example, I'll use ejs. Also, I'm assuming you know how to get the data for user selections to your server.
on your app.js:
app.get('/someRoute', function(req, res) {
var data = //get user data here
res.render('someTemplate', {data:data});
});
someTemplate.ejs:
<%- include('header') %> //you should do this on every page
<% if (data == 'foo') { %>
<%- include('foo', {data:data}) %> //note that you can pass data to templates like this
<% } %>
<% if (data == 'bar') %>
<%- include('bar') %>
<% } %>
<% include('footer') %>
foo.ejs:
//some component here
If you want to read more, check the docs.
Hope this helps!
You can use Template Engine for that purpose because it enables you to use static template files in your application. At run time, the template engine replaces variables in a template file with actual values, and transforms the template into an HTML file sent to the client. This approach makes it easier to design an HTML page.
Some popular template engines that work with Express are Pug, Mustache, and EJS. The Express application generator uses Jade as its default, but it also supports several others.
Also check this link
I am using partials in my views but am wondering if it is possible to include another partial within an existing partial. It seems not at present but cannot find any information on if this is possible at present.
My current setup looks like this
views
partials
home
section1
file.ejs
partial.ejs
home.ejs
So within my home.ejs file I can include my partial.ejs partial
<% include partials/partial %>
But within my partial.ejs I can't seem to include another partial
<% include home/section1/file %>
Has anyone done this ?
Thanks
I have severals views in my project let's say: "view1", "view2", "view3".
View engine is "ejs". For those views I have different scripts/css files. I have also partials like: header.ejs and footer.ejs, that I am including on the top of view(header) and bottom(footer):
As it is in the picture view1.ejs is using two stylesheets(styleA,styleB) and scripts(scriptA,scriptB).
When I am going to use another view with those static files everything is ok because I am including header.ejs and footer.ejs inside view.
But since I am using different stylesheets and scripts for another view, and I don't want to include "styleA" and "styleB" I have a problem. I just want to keep the same partials header and footer but with another links inside.
Is there any "Assets Manager" or another solution to manage all those links?
When I want to use header.ejs in over 20pages things getting complicate, because without solution of my problem, I need to include all links/styles and some of them are not necessary.
In express, you can pass styles and scripts as arrays to render your ejs template :
app.get('/', function (req, res) {
res.render('index', { styles: ['styleA.css', 'styleB.css'], scripts: ['scriptA.js', 'scriptB.js']});
});
Now update your ejs template. First the styles part :
<% styles.forEach(function(sty){ %>
<link href="<%- sty %>" rel="stylesheet">
<% });%>
Then, the scripts part :
<% scripts.forEach(function(scr){ %>
<script src="<%- scr %>"></script>
<% });%>
I'm using handlebars with KeystoneJS and am trying to extend the main import in the default template. At the moment it only includes the {{{body}}} tag imported through the view plus the partials that I'm using.
Is there any way to add a couple of other imports (i.e. intro content, page title, additional scripts). In the jade version on the demo site it just imports it as a content block. Is this a limitation of handlebars?
You can do this with handlebars just fine using partials.
Put your partial in the folder indicated below:
Then in your layout ('default.hbs' in this case) reference the partial like you would normally in handlebars.
<div id="header">
{{> navigation this}}
</div>
The '>' means insert partial.
In this case 'navigation' is the
partial name in the partials folder.
'this' is the data context. Its what you want to do with the 'locals.data' object passed into handlebars by keystone. Using 'this' will pass the whole lot through whereas doing something like 'locals.data.navigation' would pass the navigation object through to the partial making it directly accessible in the partial (good for DRY).
Hope that helps. The partials specific documentiation for handlebars is here if you are interested in looking into a few more things you can do with scope etc http://handlebarsjs.com/partials.html
I have a folder of static html files files as part of an existing project. I would like to find the simplest way to serve these via node/express using jade. There is a common head/menu/header section at the top that I would like to strip out and put in the jade template, a common section of js includes at the bottom that should also be in the template, and I would like to send a couple variables (e.g. the user) from the server. I would very much appreciate a pattern of how to do this that shows:
the route and controller for the render and how to set up the corresponding static serving with node
the sections of content in the jade files
where the static files should be stored
how jade links together blocks with the same class/id.
Thank you.
You can just read the static files with fs and then pass the data of each file through res.render('page', {contentHTML: data}). In the client page use the != operator to unescape the data and inject it to the view.
For example:
static.html (suppose that the file is in the views folder)
<div>
<p> some text </p>
</div>
Server: (suppose this code is in the routes folder)
router.get('/static', function(req, res){
fs.readFile('./views/static.html', function(err, data){
res.render('page', {responseHtml: data});
});
});
page.jade: (suppose this view is in the views folder)
extends layout
block content
div!= responseHtml
The app structure is this:
-example
...
-routes
index.js (here is the code show above, in the Server section)
users.js
-views
...
page.jade (client code show above)
static.html (content to load in page.jade)
app.js
package.json