OctoberCMS Partials sharing variables life cycle - components

I'm new in October CMS and I try to develop some components and these components have more than one page. I include every page as a partial in the default.htm file with an if condition depends on the type property of the page.
{% set type = __SELF__.property('type') %}
{% if type == 'y' %}
{% partial 'x::yy' %}
{% elseif type == 'x' %}
{% partial 'x::xx' %}
the problem is when I have a collection of items in one page and send id of one of the items to another ajax handler and want to retrieve full info of the item, I can't pass it to next page because of the page cycle in October CMS.for example :
// firstpage
{% set posts = __SELF__.posts %}
{%for post in posts%}
<button data-request="handlerX" data-request-data="id: {{post.id}}">
{%endfor%}
//hanlerX
public function onHanldlerX(){
$post = $this->post = POST::where('id',post("id"))->first();
return redirect()->to('/my-posts/'.$post->slug);
}
//nextpage -> my-posts/$post->slug
// post informations is unavailible
what's the best way for these type of components?
Is It the right way for this?
how can I send variables to view after the OnRun method in components?

Related

Shopware: Remove Add To Cart for Some products

Within Shopware 6, has anyone figured out how to remove the “add to cart” button for some products? My goal is to allow the add to cart on most items, but I’d like the option/ability to remove it for select products.
Thanks in advance!
Scott
You can use a custom field for this.
In admin go to Settings / Custom fields and add a new custom field set. Name it for example custom_product and assign Products, save. Then add a new custom field. Name it for example custom_product_remove_buy_button and choose Active switch as type.
Alternatively, you can create the custom field programmatically as described in the documentation.
You will see the new custom field in admin in product detail under Specifications / Custom fields.
Then you can use the custom field in a template to disable the "add to cart" button in the storefront. In order to remove the button on the product detail page, create a new file src/Resources/views/storefront/page/product-detail/buy-widget.html.twig in your theme or plugin and paste the following code:
{% sw_extends '#Storefront/storefront/page/product-detail/buy-widget.html.twig' %}
{% block page_product_detail_buy_form %}
{% if page.product.active and page.product.customFields.custom_product_remove_buy_button != true %}
<div class="product-detail-form-container">
{% sw_include '#Storefront/storefront/page/product-detail/buy-widget-form.html.twig' %}
</div>
{% endif %}
{% endblock %}
To remove the button in the product listing, create a file src/Resources/views/storefront/component/product/card/action.html.twig:
{% sw_extends '#Storefront/storefront/component/product/card/action.html.twig' %}
{% block component_product_box_action_buy %}
{% if product.customFields.custom_product_remove_buy_button != true %}
{{ parent() }}
{% endif %}
{% endblock %}
Setting the Max. order quantity to 0 will result in not showing a buy button on the product detail page. However it is still possible to add the product via the listing. To fix this you can extend this file as mentioned before:
src/Resources/views/storefront/component/product/card/action.html.twig
{% block component_product_box_action_buy %}
{% if product.calculatedMaxPurchase > 0 %}
{{ parent() }}
{% endif %}
{% endblock %}
If the user somehow manages to add the product in the cart Shopware will throw a default error message:
The product "Test" is not available any more

Rendering a component inside another in Nunjucks & Fractal

I'm working on a design system and just getting my head around the component way of thinking.
We're using Nunjucks and Fractal.
We have an existing component, an accordion which gets it's data from a JSON object. The props being title and content.
I've built a component, like a table of contents, which displays a list of styled links, using a simple loop, pulling in from a ToC.config.js file.
I need to include that new component within the accordion component, the ToC has a title and an array containing urls and text for each link.
At present I've just copied the HTML from the accordion's view in Fractal, but that's probably not the way to go, but visually it's as the designer requires.
I can also render the accordion correctly if I put all the links, HTML and all in the config, as a string, but that's not the way it should work either.
What I want to do, which is probably the proper way, is pull that accordion in and populate it with my ToC component.
{% render '#my-accordion', 'accordion: items' %} doesn't do what I want and I can't seem to figure out how to achieve what I need to do.
Something like so:
{% render '#my-accordion' %}
// Pass in data from ToC, somehow
{{ title: title }}
{% for item in items %}
{{ item.text etc }}
{% endfor %}
Then I would have my accordion component, where its title, links and HTML etc are those from my ToC component. Sorry for the rough pseudo above, it's more an example of what I want to do. I can't copy code to an external resource.
using render doesn't appear to be the way to go, unless I'm missing something? I can't pass the list through as a string as it has classes and aria for the current page etc and content authors will be building pages with these.
A little nudge in the right direction would be great.
You can add a render-filter that similar to include and macro.
import 'nunjucks.min.js';
var env = new nunjucks.Environment({autoescape: true});
env.addFilter('render', function (template, ctx) {
const html = env.render(template, ctx); // try-catch
return env.filters.safe(html);
});
Usage
// table.njk
<table>
{% for e in rows %}
{% 'row.njk' | render({row: e}) %}
{% endfor %}
</table>
// row.njk
<tr>
{% for c in row.cols %}
<td> {{ c.name }} </td>
{% endfor %}
</tr>

How to get article url in a given category?

I'm trying to make a scroll on products in a given category for articles in shopware 6. I've managed to extend the product-detail html.twig file to add the next and previous on the page. The problem I'm facing is how to generate the URL links in a given category.
{% sw_extends '#storefront/page/product-detail/index.html.twig' %}
{% block base_content %}
« Previous
Next »
{{parent()}}
{% endblock %}
With the twig function seoUrl, you can generate links to other pages.
After the URL you can add query strings for the right pagination, see the example:
{{ seoUrl('frontend.navigation.page', { navigationId: 'ID' }) }}

How to add active class if current url matches the given (twig)

I want to write manually a side menu for the store on opencart, and I have a problem - how to make twig add the class "active" to the link for current page
I tried to do it like this
page about something
but it doesnt work
This is exactly what the category module does so you can copy it:
{% if child.category_id == child_id %}
- {{ child.name }}
{% else %}
- {{ child.name }}
{% endif %}
You can find the file above here:
/catalog/view/theme/default/template/extension/module/category.twig
You can find its controller here:
/catalog/controller/extension/module/category.php
They way I would do it is out the route request in by the controller phone file. This would be something like the below:
$urlroute = $this->request->get['route'];
Then in the twig file you could simply check the route variable in an IF query
{% if urlroute == "something" % }
page about something
{% else %}
page about something
{% endif %}

Twig : Access to variable from outer scope in a form widget customization

I'm trying to customize a specific widget, like in the documentation : http://symfony.com/doc/current/cookbook/form/form_customization.html#how-to-customize-an-individual-field
The problem is that in this custom block, I need to use a variable from my actual template. I thought "blocks have access to variables from outer scopes", but apparently not in this case :
{% extends "CDASvBundle::layout.html.twig" %}
{% block _contact_activity1_widget %}
<select name="contact[activity1]">
{% for key, child_contact_categories in contact_categories_tab %}
<option value="{{key}}">{{child_contact_categories}}</option>
{% endfor %}
</select>
It's saying that contact_categories_tab is undefined, but outside of this block (in the normal content block for example), it works !
I tried something like :
{% use 'form_div_layout.html.twig' with contact_categories_tab as contact_categories_tab %}
But that doesn't either.. Though I'm not sure I understand if I have to use use and how !
I see one other solution that I haven't tried yet : put this customization in another template. But I don't really want to do that (few lines in a new template), there should be a way to do that in only ONE template ?!
Finally found the answer in a previous post :
Each symfony form type extents AbstractType class.
AbstactType class has method:
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->set('img_src', '120x100.jpg');
$view->set('my_variable', $foo);
}
You can create this method on your form type and next in your twig:
{{ asset(img_src) }}
Source : How to get entity or pass variable to Symfony2 twig form widget?

Resources