I've a project with backend and frontend.
In the backend I want to add one option to change template
The style is defined on base.html.twig on this line:
<link href="{{ asset('css/themes/default.css') }}" rel="stylesheet" type="text/css" id="style_color"/>
My question is how can I change the style when I load this file.
The template option will be stored on database.
EDIT:
In the moment I'm doing like this: I created an action on default controller to return a new Response with the template defined on DB, then in base.html.twig.
{{ render(controller("AdminPageBundle:Default:getTemplateAdmin")) }}
it works like this, but I don't think is the best way to do this
I hope that I understood the question. I assume that you're looking for a way to 'bind' the correct stylesheet depending on settings from the database, the latter being already solved
Twig provides an OOP like inheritence that you may leverage to make this work.
Here's a solution in three steps :
Step one : write a "theme aware" action. In the controller
...
public function adminAction(){
//get the settings information, this is hardcoded for the sake of esample
//you may as well fetch this from the DB
$themeSettings = array('style'=>'blue');
//render the template and inject the variable
return $this->render('AdminPageBundle:Default:template.html.twig',
array('theme'=>$themeSettings));
}
Step2 : create a base template with the default theme (failsafe)
//let's call it base.html.twig
<!DOCTYPE html>
<html>
<head>
...
{% block stylesheets %}
<link href="{{ asset('css/themes/default.css') }}" rel="stylesheet" type="text/css"/>
{% endblock %}
....
</head>
...
Step3 : Override the 'stylesheets' block in the theme-aware template
//template.html.twig:
{# make it a child of base.html.twig #}
{% extends '::base.html.twig' %}
{# override the stylesheets block #}
{% block stylesheets %}
{# include what you already have in the parent template (link to default.css) #}
{{ parent }}
{# add your own theme from the database (using the 'theme' variable from the controller #}
<link href="{{ asset('css/themes/'~ theme.style ~ '.css') }}" rel="stylesheet" type="text/css"/>
{% endblock %}
With this example, rendering 'template.html.twig' will load the stylesheet at '/css/themes/blue.css'.
You may as well implement this directly in the base template without relying on inheritence, but I'm assuming that some templates are theme-aware and some aren't. Inheritence provides flexibility to implement this feature only where you need it.
Of course, there are several other ways to solve the problem. Writing a custom twig extension to handle theming would be the right thing to do for a reliable long term solution, especially if theming is not just about loading a stylesheet. You may also write an event handler (for the kernel.view event) to modify the template or inject theme settings just before rendering. This answer shows an example.
Related
I need to load a page, that will be "inserted" in a template - as I read it, Volt's Template Inheritance should do the trick and it does... kinda. Hardcoded values, as shown in the examples, work fine - the following example works:
<!-- Template -->
<div id="site_content">
{% block test %}
{% endblock %}
</div>
and the page, that inherits the template:
{% extends "../../templates/de/index.volt" %}
{% block test %}
{{ content() }} {# this is a registered volt function that outputs the generated content #}
{% endblock %}
However, the same page might need to inherit a different template and that must be decided on runtime, so the name of the template must be generated dynamically. Two options occurred to me:
Set the template name to a variable and use it when extending - the problem here is that I don't see a way to use it afterwards. That guy seems to have had the same problem, but there is neither an answer of how to do it, nor a confirmation that it isn't possible at all.
Register another function to generate the complete string (e.g. {% extends "../../templates/de/index.volt" %}) and then compile it, e.g.
$compiler->addFunction('get_template',
function ($resolvedArgs, $exprArgs) use ($volt) {
return $volt->getCompiler()
->compileString('{% extends "../../templates/de/index.volt" %}');
});
and then use that function in the page, e.g.
{{ get_template() }}
{% block test %}
{{ content() }}
{% endblock %}
However, using that approach does not parse the page content (e.g. the content returned by the registered content() function is not shown). I'm also open to other solutions (using Twig instead of Volt is only a last resort, for performance issues), advices of what I'm doing wrong or pointers of useful articles on the topic. Thanks in advance!
Try using partials as documented in the Phalcon doc: Using Partials
How to register js,css file to head tag from inside bundle automatically? so we don't need to add it manually to layout.
In zend framework there is HeadScript and InlineScript Helper, prepend or append method to do this. How about symfony2 ? is it possible too?
In zend framework we can register it like this from module bootstrap :
public function onBootstrap($e) {
$sm = $e->getApplication()->getServiceManager();
$headLink = $sm->get('viewhelpermanager')->get('headLink');
$headLink->appendStylesheet('/assets/MyModule/css/mystylesheet.css');
}
I mean, I want register it from e.g AcmeBlogBundle.php so we don't need to add manually to <head></head> in layout.
I'm not sure if this is what you are looking for, but check this out, this shows you how to include every js-file inside a directory, without listing them all manually.
You can't do it like in Zend. But you can define the appropriate block with js in base layout only once. And then from any template you can put anything you want into this block. Symfony implements a bit different logic than Zend does.
In your layout:
<head>
{% block custom_head_js %}
<some basic js files for all the pages>
{% endblock%}
</head>
In your templeate:
{% block custom_head_js
'#YourBundleNamespace/YourBundleName/Resources/public/js/your_js_filename.js'
%}
<script src="{{ asset_url }}"></script>
{% endblock %}
So, as I said it's not necessary to change base layout every time you want to add js into 'head' js files - you have to do it only once.
I need to apply a purchased template to our dashboard. In this template, the login, register and forgot password forms are all under the same view, and switching between them using simple JQuery.
I have been looking for a nice, not-too-flashy way of combining all three forms into one, but I came up empty.
My standing options (as I see them), and why I don't like any of them:
Take the views from the fos bundle, copy them to /app/Resources/FOSUserBundle/views/, remove the {% extend %} part and {% include %} them in my own login view. Reason for dislike: to me this looks a little like a quick-n-dirty fix - "that part's not working? Let's break it off!" :)
Extend the fos bundle, accept an extra parameter in the LoginAction and RegisterAction, use {% render %} with parameters in my own login view. Reason for dislike: extending a whole bundle and modifying two different controllers just to change the way it renders feels like bad MVC.
XHR load everything. Reason for dislike: this approach makes sense when using inner pages, but for pages that reload anyway it just doesn't make sense.
TL;DR version: I'm looking for a non-hack way of including the login, register and forgot password form in one page.
Any help would be greatly appreciated!
I found a solution with which I am comfortable with for my current project. The advantages and disadvantages of the proposed solution upfront:
Advantages:
few LOC to implement
FOSUserBundle update proof (does not override the view scripts*)
Disadvantages:
performance overhead due to subrequests
only forms can be displayed, form submission (and subsequently error handling upon submission) will always go to the pages provided by FOSUserBundle
still feels like a quick-n-dirty fix, but better than other options
* only needs to override the layout.html.twig file
With that being said, here is what I have done:
Render the form in your template
Use embedded controllers to render the forms you need:
<div>
<h2>Login</h2>
{{ render(controller('FOSUserBundle:Security:login', { embeddedForm: true})) }}
</div>
<div>
<h2>Reset</h2>
{{ render(controller('FOSUserBundle:Resetting:request', { embeddedForm: true})) }}
</div>
Override FOSUserBundle layout
As I use the routes provided by the bundle, I had to override the FOSUserBundle layout template file to extend the standard layout of my application. As the overriden FOSUserBundle layout file extends the main applications layout file the layout would be repeated for each call {{ render ... }}. To prevent that, we need to dynamically disarm the extended layout file. Here is what the overriden layout file looks like:
{# app/Resources/FOSUserBundle/views/layout.html.twig #}
{% if app.request.get('embeddedForm') %}
{% set layout = 'AcmeBundle::layout-content.html.twig' %}
{% else %}
{% set layout = 'AcmeBundle::layout.html.twig' %}
{% endif %}
{% extends layout %}
{% block content %}
{% block fos_user_content %}{% endblock %}
{% endblock %}
Create the AcmeBundle::layout-content.html.twig file
This layout should only render the content block of the FOSUserBundle view scripts and is such short and simple:
{# src/Acme/DemoBundle/Resources/views/layout-content.html.twig #}
{% block content %}{% endblock %}
Now the forms will render nicely with all dependencies (CSRF and so forth). Submitting the form will however take you to the FOSUserBundle actions.
Alternative solution:
This answer describes how to manually implement the forms and link them to the FOSUserBundle controller.
i want to override a css file i.e reside in sonata-project/admin-bundle/Sonata/AdminBundle/Resources/public/bootstrap/css path of sonata admin bundle project.
Please help me out.
One way you can you override the css files of sonata admin but remember this will override the block of stylesheets but still you can call the stylesheets of parent block by calling {{ parent() }}
{% block stylesheets %}
/* this will override the parent block you can define here your css files*/
<link rel="stylesheet" href="{{ asset('cssfilepath.css') }}"/>
{% endblock %}
{% block stylesheets %}
/*this will extend the parent block */
{{ parent() }}
<link rel="stylesheet" href="{{ asset('cssfilepath.css') }}"/>
{% endblock %}
I used the answer of M Khalid Junaid that is working like a charm. Here some facts I missed while implementing this.
Update your config.yml like this:
sonata_admin:
templates:
list: AppBundle::Admin/list.html.twig
The src/AppBundle/Resources/views/Admin/list.html.twig then can look like this:
{% extends 'SonataAdminBundle:CRUD:base_list.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<style type="text/css">
* {
}
</style>
<!-- and/or -->
<link rel="stylesheet" href="{{ asset('cssfilepath.css') }}"/>
{% endblock %}
It is possible to remove/add stylesheets in Sonata Admin Bundle within configuration file without handling template files:
sonata_admin:
assets:
remove_stylesheets:
- bundles/sonataadmin/css/old.css # path to vendors css-file to remove
extra_stylesheets:
- build/admin/css/new.css # your css-file to add
Considered above options are listed in Sonata Admin Bundle CONFIGURATION in FULL CONFIGURATION OPTIONS section.
I'm working on a Symfony2 application and I'm trying to import resources (here, css and js) in a specifig twig template, instead of in the layout templates. However, what I've tried doesn't seem to work when I use the extends property. Yet it does work when there is no layout inheritance.
Here's the code I used :
{% block stylesheets %}
{% stylesheets 'bundles/mybundlename/css/style.css'
filter='cssrewrite' %}
<link rel="stylesheet" href="{{ asset_url }}" type="text/css" />
{% endstylesheets %}
{% endblock %}
{% block javascripts %}
{% javascripts 'bundles/mybundlename/js/jquery-1.7.2.min.js'
'bundles/mybundlename/js/jquery-ui-1.8.20.custom.min.js'
%}
<script src='{{ asset_url }}' type='text/javascript'></script>
{% endjavascripts %}
{% endblock %}
{% extends "MyBundle::layout.html.twig" %}
... the rest of my template ...
Bottom line, how would I import those resources in my inheriting template?
Or is it simply better to just import them in the general layout (but then it loads for every page :/) ?
Edit : I have used #MyBundle route types as well, and they are being searched by the engine (if the path is wrong, I get an error), but the resources are not added the the html section.
Second edit : The reason why it was not working is likely that I hadn't declared the {{% blocks %}} in my top level layout. I did and used {{ parent() }} (as a matter of "cleanliness") in my sub layouts and pages, and it works.
{% extends ... %} must come first.
You might also want to use the parent function to append to the stylesheets and javascripts defined in the layout instead of overwriting them.