I have 2 pages index.htm and links.htm and a partial sidebar.htm.
I'm trying to get my sidebar to display different content based on whether index.htm or links.htm is active.
Reading through the documentation it looks as if you can do this with the param.tab but I can't get it to work and not sure if this is the best way to accomplish this seeing as it's a partial.
sidebar.htm
description = "sidebar"
url = "/sidebar/:{% this.page.url %}"
==
{% if this.param.tab == 'links' %}
Display this if page = links
{% elseif this.param.tab == 'index' %}
Display this is page = index
{% endif %}
In blade I used - #elseif(isset($guidesslugs) && $guidesslugs->guidesslug == 'area-guide') but I'm not sure how to accomplish the same thing using twig or whether it's possible to used the param.tab on a partial?
There's multiple ways to do it.
First of all, partials may not have the url parameter into config section.
The Configuration section is optional for partials and can contain the
optional description parameter which is displayed in the back-end user
interface.
Partials - Introduction
You could use param if the sidebar has different content based on the same page. Example:
pages/home.htm
url = "/home/:type"
==
{% partial 'sidebar' type=this.param.type %}
partials/sidebar.htm
{% if type == 'foo' %}
{# foo type #}
{% elseif type == 'bar' %}
{# bar type #}
{% else %}
{# anything... #}
{% endif %}
When including partials you can pass variables, in this case, we injected type as this.param.type value. You could also access this.param (global) variable inside partial:
partials/sidebar.htm
{% if this.param.type == 'foo' %}
{# foo type #}
{% endif %}
If I understand your question, you have two different pages where each has his own distinct url so doesn't seems like a case for param property.
Use this.page variable.
You're able to access the page url defined into page configuration section by using:
{{ this.page.url }}
This property seems like hidden from docs.
So considering your structure:
pages/home
url = "/home"
layout = "default"
==
{% partial 'sidebar' %}
pages/links
url = "/links"
layout = "default"
==
{% partial 'sidebar' %}
partials/sidebar
{% if this.page.url == '/home' %}
{# home page #}
{% elseif this.page.url == '/links' %}
{# links page #}
{% else %}
{# other pages #}
{% endif %}
As I said, there's so many ways to do this by defining variables, passing parameters to partial and others.
Related
TL;DR: I am currently struggling with the idea how to elegantly generate CRUDs/GRID using Twig.
Long story:
I have a Phalcon app with AngularJs, templating system is Twig.
PHP is suppose to prepare a template for CRUD that contains:
List od entities, table that contains proper headers, columns, row items, action buttons
Simple and advanced search
Mass actions block
Main buttons - Add/Import/Export etc.
AngularJs is responsible for:
Paginating results in 2 modes: Ajax Loaded entities, All entities at once
Changing number of entities per page
Displaying various forms in modals - Add/Edit/Import
Filtering entities - simple and advanced search
Everything is working right now but I am not particularly fond of how it works.
For example a simple entity with few fields needs a following template:
{% extends 'index.twig' %}
{% block containerAttr %}ng-controller="InventoryController as ctrl"{% endblock %}
{% set ctrlName = 'ctrl' %}
{% set columnWidth = 'col-xs-12' %}
{% set tableClass = 'table table-bordered table-striped table-hover' %}
{% block header %}
{% include '#crud/crud/header.twig' %}
{% endblock %}
{% block content %}
{% embed '#crud/crud/main-box.twig' %}
{% block tableHeader %}
{% autoescape false %}
{{ crud.tableHeader('Id', 'id') }}
{{ crud.tableHeader('Nazwa', 'name') }}
<th class="col-xs-1">Actions</th>
{% endautoescape %}
{% endblock %}
{% block tableRow %}
<td ng-bind="e.id"></td>
<td ng-bind="e.name"></td>
{% endblock %}
{% endembed %}
{% embed '#crud/crud/form.twig' %}
{% block modalBody %}
{% autoescape false %}
<div class="row">
{{ crud.input('ctrl.entity.name', 'Name', 12) }}
</div>
{% endautoescape %}
{% endblock %}
{% endembed %}
{% embed '#crud/crud/upload.twig' %}{% endembed %}
{% embed '#crud/crud/advancedSearch.twig' %}{% endembed %}
<script>
window.xdata = {{ xdata | json_encode | raw }};
</script>
{% endblock %}
crud in this template is responsible for generating form fields compatible with AngularJs.
Idea is: To create new CRUDs/Grids with the least amount of work required. While still giving a room for some flexibility.
Right now to make a CRUD/Grid inside my application there is a really little work required:
PHP Controller needs to contain only one line:
class SubCategoryController extends CrudBase
{
protected $entityClass = InventoryCategory::class;
}
Thanks to extending it is really easy to customize every part of it.
Model needs to have just a few fields:
class InventoryCategory extends ModelBase
{
/** #var integer */
public $id;
/** #var string */
public $name;
public function initialize()
{
$this->setSource('inventory_subcategory');
$this::setup(['castOnHydrate' => true]);
}
}
Even the AngularJs controller contains only URLs and one line:
class InventoryCategoryController extends CrudBase {
constructor($injector, $scope) {
super($injector, $scope);
this.urlSave = '/inventory/category/save';
this.urlImport = '/inventory/category/import';
this.urlExport = '/inventory/category/export';
this.urlDelete = '/inventory/category/delete';
this.init({
advancedSearch: false
});
}
}
angular.module('App').controller('InventoryCategoryController', InventoryCategoryController);
Yes I use ES6, application is not compatible with older browsers anyways and it is admin panel so I do not care about older browsers.
But now only templates remains a tedious work to copy it over and change it. Not to mention they do look pretty ugly.
So my idea was to use Annotation Reader (Phalcon has one) to read fields from Model, then transform it into a base configuration, check if there is custom configuration in json and merge it. Then based on configuration, generate this whole template on the fly.
So the grand question is:
I was wondering if I can create some class that extends Twig_Template to generate this template on the fly?
I have seen Twig cache and it should be pretty easy but then how can i use it? How can i render it? Will extend still work?
I'm using OctoberCMS which uses Twig.
The way I retrieve user permissions is by getting the information in php then pass a twig variable.
Is there a way to do this using just Twig?
Permissions Docs
PHP
if (BackendAuth::check()) {
# Get User Info
$backend_user = BackendAuth::getUser();
# Superuser
$this['is_superuser'] = $backend_user->is_superuser;
# Permissions
$this['permissions_allow_edit'] = $backend_user->hasPermission(
[
'mycomponent.gallery.allow_edit'
]);
}
Twig
{% if is_superuser or permissions_allow_edit %}
//edit button
{% endif %}
Twig (Standalone)
//another way to backendauth check in twig?
if (BackendAuth::check()) {
$this['backend_user'] = BackendAuth::getUser();
}
//////
{% if backend_user.is_superuser or backend_user.permissions.mycomponent.gallery.allow_edit %}
//edit button
{% endif %}
{{ backend_user }} gives the user information array
{"id":2,"first_name":"Matt","last_name":"","login":"matt","email":"user#example.com","permissions":{"mycomponent.gallery.allow_edit":1},"is_activated":false,"activated_at":null,"last_login":"2017-03-11 09:59:48","created_at":"2017-02-11 10:32:14","updated_at":"2017-03-11 10:03:45","is_superuser":0}
{{ backend_user.permissions }} throws an "Array to string conversion" error.
{{ backend_user.permissions.mycomponent.gallery.allow_edit }} shows nothing.
How do I get the values inside the permissions array?
I have not tested this but you should be able to use the hasPermission method to check if backend user has a specific permission:
{% if backend_user.is_superuser or backend_user.hasPermission('mycomponent.gallery.allow_edit') %}
//edit button
{% endif %}
I get the following error: Variable "file" does not exist.
The included template Contractor:file.html.twig looks like this:
{{ dump(file) }}
The main template form.html.twig looks like this:
{% extends '::base.html.twig' %}
{% form_theme form 'NaSoftEdmBundle:Form:fields.html.twig' %}
...
{% block files %}
{% for file in form.files %}
{{ include('NaSoftEdmBundle:Contractor:file.html.twig', {'file': file}) }}
{% endfor %}
{% endblock %}
Controller:
public function editAction(Request $request, Contractor $contractor)
{
...
return $this->render('NaSoftEdmBundle:Contractor:form.html.twig', array(
'form' => $form->createView(),
));
}
But when I try to display a variable inside the main template file (form.html.twig), the variable becomes available:
{% for file in form.files %}
{{ dump(file) }} {# it work! #}
{% endfor %}
ContractorFile {#499 ▼
-id: 154
-uploadedFile: null
-name: "57c6d217d9a92.jpg"
-origName: "1471590585502.jpg"
-path: "/contractor/docs/files/2/335"
-size: 153536
-mimeType: "image/jpeg"
-updateDate: DateTime {#496 ▶}
-contractor: Contractor {#370 ▶}
}
command php app/console cache:clear did not help
The problem was that I was before starting the cycle "for" included the same template for attribute data-prototype:
data-prototype="{% filter escape %}
{% include 'NaSoftEdmBundle: Contractor: file.html.twig' with { '_form':form.files.vars.prototype} %}
{% endfilter %}"
I've created for the attribute "data-prototype" new template and it worked.
data-prototype="{% filter escape %}
{% include 'NaSoftEdmBundle: Contractor: filePrototype.html.twig' with { 'file':_form.files.vars.prototype} %}
{% endfilter %}"
This has been implemented to customize the template collection
The correct way to pass variables to a Twig include command is this:
{% include 'NaSoftEdmBundle:Contractor:file.html.twig' with {'file': file} %}
As #walther pointed out in comments, it is not actually required to pass variables since an included template get access to variables of the active context, i.e. you can simply write:
{% include 'NaSoftEdmBundle:Contractor:file.html.twig' %}
and the file variable will be used.
You still have to use the with syntax if you want to assign a new variable, e.g.
{% include 'NaSoftEdmBundle:Contractor:files.html.twig' with {'files': form.files} %}
See http://twig.sensiolabs.org/doc/tags/include.html
I want show the list of multiple attributes Name => value in a table overriding single field of only for PortsAdmin in ShowMapper
Ports Entity mapped with PortsAttributes Entity.
Relation of entity is OneToMany Ports with multiple attributes.
Admin View (Edit Action)
Show Action
I want change attribute view same as edit Action.
You can create a custom template for the PostAttributes:
Example:
/* ShowMapper in admin */
$showMapper->add('attributes', null, array(
'template' => 'YOUR_TEMPLATE.html.twig' // <-- This is the trick
));
In your template, you can extend the base show field (SonataAdminBundle:CRUD:base_show_field.html.twig or #SonataAdmin/CRUD/base_show_field.html.twig for symfony > 4.0), and override the field block. The variable named value stores the data in twig.
Example:
YOUR_TEMPLATE.html.twig
{% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
{# for sf > 4.0 #}
{# {% extends '#SonataAdmin/CRUD/base_show_field.html.twig' %} #}
{% block field %}
{% for val in value %}
{{ val.name }} - {{ val.value }} {# I'm just guessing the object properties #}
<br/>
{% endfor %}
{% endblock %}
#SlimenTN you can try changing this line in template file:
{% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
with this:
{% extends '#SonataAdmin/CRUD/base_show_field.html.twig' %}
The rest of code seems ok (I have the same in a SF4 project)
I passed data in 3 languages to the twig template and display this data in this way:
{% set lang=app.request.get("lang")%}
{% for item in contests%}
{% if lang=="fa"%}
{{item.titlefa}}
{% elseif lang=="en"%}
{{item.titleen}}
{% elseif lang=="ar"%}
{{item.titlear}}
{% endif%}
{% endfor%}
It is wirking but I must create 3 if condition for each object in "contests"
How can i show data in this logic:
{% set lang=app.request.get("lang")%}
{{item.title~lang}}
{% endfor%}
that can call proper method in contest
You can use the attribute TWIG function for call at runtime a method name, as example:
{% set lang=app.request.get("lang")%}
{% methodname = 'title'~lang %}
{% for item in contests%}
{{ attribute(item, methodname) }}
{% endfor%}
Hope this help