The UiBundle in OroCRM is rich and very flexible , but the courses about 'use case' and practice is very few .
Ibnab Team decided to make a reference needed by programmers, combine theoretical and practical lessons .
Theoretical paragraph
We introduce in this course the idea of activityButton (action button) and activityLink (action link if you go for example to page contact view and click in More action , all this links is action links) , and how you can use with Placeholder , how the system work ,how read from your placeholders.yml.
Ok inside Oro BAP you have bundle with name UIBundle for managing layouts templates and actions without touching the core just with injection or implementation in real time of application execution , in order to improve layouts and make them more flexible a new twig token placeholder is implemented. It allows us to combine several blocks (templates or actions) and output them in different places in twig templates. This way we can customize layouts without modifying twig templates.
Practical paragraph :
1 – Create your action link and button
So for inject your Two actions without touching the core or override the template of Oro you need pass by placeholder .
ok inisde you Resource\config\inside placeholdes.yml :
items: ibnab_doc_add_button: template: IbnabDocBundle:Doc:activityButton.html.twig acl: doc_defaut_create ibnab_doc_add_link: template: IbnabDocBundle:Doc:activityLink.html.twig acl: doc_defaut_create
This is very simple you declared here link and action button with it template and acl (access control level) ,
The content activityButton.html.twig :
{{ UI.clientButton({ 'dataUrl': path( 'doc_defaut_create', { entityClass: oro_class_name(entity, true), entityId: entity.id }), 'aCss': 'no-hash', 'iCss': 'icon-file-alt', 'dataId': entity.id, 'label' : 'doc_defaut_create'|trans, 'widget' : { 'type' : 'dialog', 'multiple' : true, 'refresh-widget-alias': 'activity-list-widget', 'options' : { 'alias': 'call-dialog', 'dialogOptions' : { 'title' : 'doc_defaut_create'|trans, 'allowMaximize': true, 'allowMinimize': true, 'dblclick': 'maximize', 'maximizedHeightDecreaseBy': 'minimize-bar', 'width': 500, autoResize: true, modal: true, minHeight: 100 } } } }) }}
The important section is the type UI.clientButton, it give as result a button and when you click , it give you the dialog widget …
The content activityLink.html.twig :
{{ UI.clientLink({ 'dataUrl': path( 'doc_defaut_create', { entityClass: oro_class_name(entity, true), entityId: entity.id }), 'aCss': 'no-hash', 'iCss': 'icon-file-alt', 'dataId': entity.id, 'label' : 'doc_defaut_create'|trans, 'widget' : { 'type' : 'dialog', 'multiple' : true, 'refresh-widget-alias': 'activity-list-widget', 'options' : { 'alias': 'call-dialog', 'dialogOptions' : { 'title' : 'doc_defaut_create'|trans, 'allowMaximize': true, 'allowMinimize': true, 'dblclick': 'maximize', 'maximizedHeightDecreaseBy': 'minimize-bar', 'width': 500, autoResize: true, modal: true, minHeight: 100 } } } }) }}
But you need declare the responsible provider ( you need declare you actions to provider of UiBundle ) inside services.yml:
services:
ibnab_docwidget_provider.actions: parent: oro_ui.widget_provider.action_button.abstract arguments: - ibnab_doc_add_button - ibnab_doc_add_link tags: - { name: oro_ui.view_action_provider, group: activity, priority: 100 } - { name: oro_ui.update_action_provider, group: activity, priority: 100 }
Ok you declared your actions to provider but what is this :
in arguments you pass your 2 actions declared inside the placeholders.yml with the same identifier , inside the tags you tell it I want render my action inside view and update screen , inside group activity , with order 100 normal case is the last ..
You can go to it and see the function getWidgets:
orocrm2/vendor/oro/platform/src/Oro/Bundle/UIBundle/Provider/ActionButtonWidgetProvider.php
public function getWidgets($object) { $result = []; $buttonWidget = $this->placeholderProvider->getItem($this->buttonWidgetName, ['entity' => $object]); if ($buttonWidget) { $widget['name'] = $this->buttonWidgetName; $widget['button'] = $buttonWidget; $linkWidget = $this->placeholderProvider->getItem($this->linkWidgetName, ['entity' => $object]); if ($linkWidget) { $widget['link'] = $linkWidget; } } $result[] = $widget; } return $result; }
This is simple too , it read all infos(key,value) and return for merge and inject to global result , but where is rendered ?
You can go to :
orocrm2/vendor/oro/platform/src/Oro/Bundle/UIBundle/Resources/views/macros.html.twig
and see for example how UiBunlde inject the link action to dropdown , parameters.elements is the big merged actions result .
{# Create dropdown button Parameters - array: [ 'label' - button label 'elements' - dropdown elements 'html' - html from placeholder 'aCss' - additional drop down class ] #} {% macro dropdownButton(parameters) %} <div class="btn-group"> <a class="btn dropdown-toggle" data-toggle="dropdown" href="#"> {% if parameters.iCss is defined %} <i class="{{ parameters.iCss }}"></i> {% endif %} {{ parameters.label }} <span class="caret"></span> </a> <ul class="dropdown-menu {{ parameters.aCss is defined? parameters.aCss : '' }}"> {% if parameters.elements is defined and parameters.elements is not empty %} {% for item in parameters.elements %} {{ _self.dropdownItem(item) }} {% endfor %} {% endif %} {% if parameters.html is defined and parameters.html is not empty %} {{ parameters.html|raw }} {% endif %} </ul> </div> {% endmacro %}
Now oro render your action , but is rendered in all place calls cases and contact … how you can filter and showing in the specific place .
2 – Filter the place of where showing your actions :
Ok you can add tag applicable inside placeholders.yml for filtering (show or hide your action )
items: ibnab_doc_add_button: template: IbnabDocBundle:Doc:activityButton.html.twig applicable: @ibnab_doc.placeholder.filter->isApplicable($entity$) acl: doc_defaut_createview ibnab_doc_add_link: template: IbnabDocBundle:Doc:activityLink.html.twig applicable: @ibnab_docplaceholder.filter->isApplicable($entity$) acl: doc_defaut_createview
But we use here the function isApplicable, and we pass as parameter the current entity of current view or update screen (related to route and principal entity of current screen ) , we using the class or identifier of service @ibnab_doc.placeholder.filter , we need create inside services.yml :
parameters: ibnab_doc.placeholder.filter.class: Ibnab\Bundle\DocBundle\Placeholder\PlaceholderFilter services: ibnab_doc.placeholder.filter: class: %ibnab_doc.placeholder.filter.class% arguments: - @oro_entity.doctrine_helper
Go to Ibnab\Bundle\DocBundle\Placeholder and create class PlaceholderFilter.php :
with content example :
<?php namespace Ibnab\Bundle\DocBundle\Placeholder; use Doctrine\Common\Util\ClassUtils; use Oro\Bundle\EntityBundle\ORM\DoctrineHelper; use Oro\Bundle\EntityExtendBundle\Tools\ExtendHelper; class PlaceholderFilter { /** @var DoctrineHelper */ protected $doctrineHelper; /** * @param DoctrineHelper $doctrineHelper */ public function __construct( DoctrineHelper $doctrineHelper ) { $this->doctrineHelper = $doctrineHelper; } /** * * @param object $entity * @return bool */ public function isApplicable($entity) { || !$this->doctrineHelper->isManageableEntity($entity) || $this->doctrineHelper->isNewEntity($entity) ) { return false; } $className = ClassUtils::getClass($entity); if($className == 'OroCRM\Bundle\CampaignBundle\Entity\Campaign') { return false; } return true; } }
If you see : with function isApplicable we create simple filter = “don't show or render my 2 actions if the current principal entity or current of entity OroCRM\Bundle\CampaignBundle\Entity\Campaign”
look great after explain …...
Comments