Is it possible to reuse somehow magentos 2 add to cart form in a custom module? I have in tab all child products of current product and I want to allow customers to add to cart products so thats how looks my code at this status
<?php
if ($currentProduct = $block->getCurrentProduct()) {
$variants = $block->getVariants($currentProduct);
if($variants) { ?>
<ul id="product-variants">
<?php foreach ($variants as $_product) : ?>
<li>
<form>
<?php echo $_product->getName(); ?>
SKU: <?php echo $_product->getSku(); ?>
Brutto: <?php echo $_product->getPrice(); ?>
<input type="text" placeholder="Stück">
<button>Add to cart</button>
</form>
</li>
<?php endforeach; ?>
</ul>
<?php };
}
?>
you can add button in custom phtml file as follow, I have done this in custom module
In your block file
use Magento\Catalog\Block\Product\ListProduct;
<?php
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
\Magento\Catalog\Block\Product\ListProduct $listProductBlock,
array $data = []
) {
parent::__construct($context, $data);
$this->_productCollectionFactory = $productCollectionFactory;
$this->listProductBlock = $listProductBlock;
}
public function getProductCollection()
{
/** #var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */
$collection = $this->_productCollectionFactory->create()->addAttributeToSelect('*')->load();
return $collection;
}
public function getAddToCartPostParams($product)
{
return $this->listProductBlock->getAddToCartPostParams($product);
}
?>
get productlist in view file
<?php
const PARAM_NAME_BASE64_URL = 'r64';
const PARAM_NAME_URL_ENCODED = 'uenc';
use Magento\Framework\App\Action\Action;
$_productCollection = $block->getProductCollection();
?>
<?php foreach ($_productCollection as $_product): ?>
<?php $postParams = $block->getAddToCartPostParams($_product); ?>
<?php echo $_product->getName()?>
<form data-role="tocart-form" action="<?php /* #escapeNotVerified */ echo $postParams['action']; ?>" method="post">
<input type="hidden" name="product" value="<?php /* #escapeNotVerified */ echo $postParams['data']['product']; ?>">
<input type="hidden" name="<?php /* #escapeNotVerified */ echo Action::PARAM_NAME_URL_ENCODED; ?>" value="<?php /* #escapeNotVerified */ echo $postParams['data'][Action::PARAM_NAME_URL_ENCODED]; ?>">
<?php echo $block->getBlockHtml('formkey')?>
<?php $storeManager = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Store\Model\StoreManagerInterface'); ?>
<button type="submit"
title="<?php echo $block->escapeHtml(__('Add to Cart')); ?>"
class="action tocart primary">
<span><?php /* #escapeNotVerified */ echo __('Add to Cart') ?></span>
</button>
</form>
<?php endforeach;?>
Related
magento 2 get store id php
I need to show something based on store id
for exapmle;
<?php if ($store == "2") {?>
<div class="block-bottom">
<a class="button-sticky-bottom" href="<?php echo $this->getUrl('') ?>">
<i class="fa fa-flag" style="font-size: 18px;"></i>
<span><?php echo __('Language'); ?></span>
</a>
</div>
<?php } else { ?>
<div class="block-bottom">
<a class="button-sticky-bottom" href="<?php echo $this->getUrl('') ?>">
<i class="fa fa-flag" style="font-size: 18px;"></i>
<span><?php echo __('Language1'); ?></span>
</a>
</div>
<?php } ?>
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$storeManager = $objectManager->create('\Magento\Store\Model\StoreManagerInterface');
$storeId = $storeManager->getStore()->getId();
if($storeId == 1){
echo 'Store Id 1 code here';
}else{
echo 'other stores code here';
}
?>
$storeManager = \Magento\Framework\App\ObjectManager::getInstance()->get('\Magento\Store\Model\StoreManagerInterface');
if ($storeManager->getStore()->getStoreId() == 1) {
echo 'Hello';
} else {
echo 'Thanks';
}
The use of object manager is not recommended. It is better to arrange this code for the class of the block using the constructor
I would recommend injecting the StoreManagerInterface in your construct and avoid using the object manager.
Example
/**
* #var \Magento\Store\Model\StoreManagerInterface
*/
protected $storeManager;
public function __construct(Context $context,
\Magento\Store\Model\StoreManagerInterface $storeManager)
{
parent::__construct($context);
$this->storeManager = $storeManager;
}
public function myFunction()
{
$storeId = $this->storeManager->getStore()->getId();
if ($storeId == 1) {
echo 'Store Id 1 code here';
} else {
echo 'other stores code here';
}
}
It didnt worked. What is wrong?
<?php
$storeManager = \Magento\Framework\App\ObjectManager::getInstance()->get('\Magento\Store\Model\StoreManagerInterface');
if ($storeManager->getStore()->getStoreId() == 1) { ?>
<div class="block-bottom">
<a class="button-sticky-bottom" href="<?php echo $this->getUrl('') ?>">
<i class="fa fa-flag" style="font-size: 18px;"></i>
<span><?php echo __('Language'); ?></span>
</a>
</div>
<?php } else { ?>
<div class="block-bottom">
<a class="button-sticky-bottom" href="<?php echo $this->getUrl('') ?>">
<i class="fa fa-flag" style="font-size: 18px;"></i>
<span><?php echo __('Language1'); ?></span>
</a>
</div>
<?php }
?>
I'm doing slick slider with ul li, and it doesn't work well.
What i mean is it take 2-5 second to load succesfully the slider (some time it take more than that). In that loading time, it look like this:
https://i.stack.imgur.com/kdte5.png
So here is the normal ul li, with out slick slider.
https://i.stack.imgur.com/ebF9m.png
And here is what after i put slick slider in:
https://i.stack.imgur.com/kdte5.png
Sorry because i cant post the direct image in here. I don't have enough reputaion to do that.
So here is the code:
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// #codingStandardsIgnoreFile
?>
<?php
/**
* Template for displaying products list widget
*
* #var $block \Gssi\ProductsSlider\Block\Product\ProductsList
*/
?>
<?php if ($exist = ($block->getProductCollection() && $block->getProductCollection()->getSize())):?>
<?php
$type = 'widget-product-grid';
$mode = 'grid';
$image = 'new_products_content_widget_grid';
$title = $block->getTitle() ? __($block->getTitle()) : '';
$items = $block->getProductCollection()->getItems();
$showWishlist = true;
$showCompare = true;
$showCart = true;
$templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::DEFAULT_VIEW;
$description = false;
?>
<div class="block widget block-products-list <?php /* #escapeNotVerified */ echo $mode; ?>">
<?php if ($title):?>
<div class="block-title">
<strong><?php /* #escapeNotVerified */ echo $title; ?></strong>
</div>
<?php endif ?>
<div class="block-content">
<?php /* #escapeNotVerified */ echo '<!-- ' . $image . '-->' ?>
<div class="products-<?php /* #escapeNotVerified */ echo $mode; ?> <?php /* #escapeNotVerified */ echo $mode; ?>">
<ul class="slick-custom product-items <?php /* #escapeNotVerified */ echo $type; ?>">
<?php $iterator = 1; ?>
<?php foreach ($items as $_item): ?>
<?php /* #escapeNotVerified */ echo($iterator++ == 1) ? '<li class="product-item">' : '</li><li class="product-item">' ?>
<div class="product-item-info">
<a href="<?php /* #escapeNotVerified */ echo $block->getProductUrl($_item) ?>" class="product-item-photo">
<?php echo $block->getImage($_item, $image)->toHtml(); ?>
</a>
<div class="product-item-details">
<strong class="product-item-name">
<a title="<?php echo $block->escapeHtml($_item->getName()) ?>"
href="<?php /* #escapeNotVerified */ echo $block->getProductUrl($_item) ?>"
class="product-item-link">
<?php echo $block->escapeHtml($_item->getName()) ?>
</a>
</strong>
<?php
echo $block->getProductPriceHtml($_item, $type);
?>
<?php if ($templateType): ?>
<?php echo $block->getReviewsSummaryHtml($_item, $templateType) ?>
<?php endif; ?>
<?php if ($showWishlist || $showCompare || $showCart): ?>
<div class="product-item-actions">
<?php if ($showCart): ?>
<div class="actions-primary">
<?php if ($_item->isSaleable()): ?>
<?php if ($_item->getTypeInstance()->hasRequiredOptions($_item)): ?>
<button class="action tocart primary"
data-mage-init='{"redirectUrl":{"url":"<?php /* #escapeNotVerified */ echo $block->getAddToCartUrl($_item) ?>"}}'
type="button" title="<?php /* #escapeNotVerified */ echo __('Add to Cart') ?>">
<span><?php /* #escapeNotVerified */ echo __('Add to Cart') ?></span>
</button>
<?php else: ?>
<?php
$postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper');
$postData = $postDataHelper->getPostData($block->getAddToCartUrl($_item), ['product' => $_item->getEntityId()])
?>
<button class="action tocart primary"
data-post='<?php /* #escapeNotVerified */ echo $postData; ?>'
type="button" title="<?php /* #escapeNotVerified */ echo __('Add to Cart') ?>">
<span><?php /* #escapeNotVerified */ echo __('Add to Cart') ?></span>
</button>
<?php endif; ?>
<?php else: ?>
<?php if ($_item->getIsSalable()): ?>
<div class="stock available"><span><?php /* #escapeNotVerified */ echo __('In stock') ?></span></div>
<?php else: ?>
<div class="stock unavailable"><span><?php /* #escapeNotVerified */ echo __('Out of stock') ?></span></div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if ($showWishlist || $showCompare): ?>
<div class="actions-secondary" data-role="add-to-links">
<?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow() && $showWishlist): ?>
<a href="#"
data-post='<?php /* #escapeNotVerified */ echo $block->getAddToWishlistParams($_item); ?>'
class="action towishlist" data-action="add-to-wishlist"
title="<?php /* #escapeNotVerified */ echo __('Add to Wish List') ?>">
<span><?php /* #escapeNotVerified */ echo __('Add to Wish List') ?></span>
</a>
<?php endif; ?>
<?php if ($block->getAddToCompareUrl() && $showCompare): ?>
<?php $compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare');?>
<a href="#" class="action tocompare"
data-post='<?php /* #escapeNotVerified */ echo $compareHelper->getPostDataParams($_item);?>'
title="<?php /* #escapeNotVerified */ echo __('Add to Compare') ?>">
<span><?php /* #escapeNotVerified */ echo __('Add to Compare') ?></span>
</a>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php echo($iterator == count($items)+1) ? '</li>' : '' ?>
<?php endforeach ?>
</ul>
</div>
<?php echo $block->getPagerHtml() ?>
</div>
</div>
<script>
require([
'jquery',
'slick'
], function ($) {
$(document).ready(function () {
$('.slick-custom').slick({
slidesToShow: 5,
speed: 300,
autoplay: true
});
});
});
</script>
<?php endif;?>
I've try put this in slick slider option, but doesn't work at all:
slide: 'li',
track: function() { return $(this).children('product-item'); },
EDIT 1:
After 6 hours looking for the answer, i've found the reason (or atleast i thing its the reason :D ).
Okay, so i guest its because Magento wasn't load the javascript in time. I mean it take a while to load this slick slider javascript.
Right now, it take about 1-2 seconds for slick slider called successfully. And in that 1-2 seconds, it will render that problem out (just like in picture 2).
Ok so the problem is still there, if you guys have any suggestion, please tell me. Thanks alot :)
EDIT 2:
I'm follow #HoangHieu solution, but doesn't seem to work
Here is what i've done :
<div class="products-<?php /* #escapeNotVerified */ echo $mode; ?> <?php /* #escapeNotVerified */ echo $mode; ?>" data-mage-init='{ "slick": {} }'>
<ul class="slick-custom product-items <?php /* #escapeNotVerified */ echo $type; ?>">
// some li
<li>...</li>
</ul>
</div>
I've added data-mage-init='{ "slick": {} }' in the . I called "slick" because that is what i define slickSlider in requirejs-config.js
var config = {
map: {
'*': {
slick: 'Gssi_ProductsSlider/js/lib/slick',
}
}
};
EDIT 3:
Okay so here is what i've done til now after #HoangHieu solution:
<ul class="slick-custom product-items <?php /* #escapeNotVerified */ echo $type; ?>" data-mage-init='{ "callSlick": {} }'>
//some li
</ul>
call-slick.js
define(['jquery', 'slick'], function ($) {
"use strict";
return function (config, element) {
let defaultConfig = {
infinite: true,
slidesToShow: 4,
speed: 300,
autoplay: true,
arrows: false,
dots: false,
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 4
}
},
{
breakpoint: 600,
settings: {
slidesToShow: 3
}
},
{
breakpoint: 480,
settings: {
slidesToShow: 2
}
}
]
};
$(element).slick($.extend({}, defaultConfig, config));
};
});
requirejs-config.js
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
var config = {
map: {
'*': {
slick: 'Gssi_ProductsSlider/js/lib/slick',
callSlick: 'Gssi_ProductsSlider/js/call-slick'
}
}
};
Some widget will load after the page loaded. By if you search in HTML about <!-- BLOCK -- that is https://devdocs.magento.com/guides/v2.1/extension-dev-guide/cache/page-caching/private-content.html
Flow here
Html loaded --> KnoutJs UIComponent get Prefix BLOCK to load --> Load Block HTML using AJAX --> Append to BODY.
that means you can't apply Slick Slider by using simple ways. Using Component instead
<div data-mage-init="{'slickSlider':{}}">
<ul>
<li></li>
</ul>
</div>
See more here: https://devdocs.magento.com/guides/v2.0/javascript-dev-guide/javascript/js_init.html
Update 2: I think you didn't read my related documents. I will give you an example.
1: My Product List Widget Template.
<ol class="product-items <?= /* #escapeNotVerified */ $type ?>" data-mage-init='{"callSlick":{}}'>
<?php $iterator = 1; ?>
<?php foreach ($items as $_item): ?>
<?= /* #escapeNotVerified */ ($iterator++ == 1) ? '<li class="product-item">' : '</li><li class="product-item">' ?>
<div class="product-item-info">
<a href="<?= /* #escapeNotVerified */ $block->getProductUrl($_item) ?>" class="product-item-photo">
<?= $block->getImage($_item, $image)->toHtml() ?>
</a>
<div class="product-item-details">
<strong class="product-item-name">
<a title="<?= $block->escapeHtml($_item->getName()) ?>"
href="<?= /* #escapeNotVerified */ $block->getProductUrl($_item) ?>"
class="product-item-link">
<?= $block->escapeHtml($_item->getName()) ?>
</a>
</strong>
</div>
</div>
<?= ($iterator == count($items)+1) ? '</li>' : '' ?>
<?php endforeach ?>
</ol>
Requiejs-config.js
var config = {
map: {
'*': {
slickSlider: 'Magento_Catalog/js/slick', //Slick slider libary
callSlick: 'Magento_Catalog/js/call-slick'
}
}
};
call-slick.js
/**
* Created by Hidro Le.
* Job Title: Magento Developer
* Date: 27/08/2018
* Time: 10:16
*/
define(['jquery', 'slickSlider'], function ($) {
"use strict";
return function (config, element) {
let defaultConfig = {
infinite: true,
slidesToShow: 3,
slidesToScroll: 3
};
$(element).slick($.extend({}, defaultConfig, config));
};
});
**Update 2: ** The result exactly example.
Update 3: If you are work with your team. Please recheck page Style Sheet, Create new page content with an empty layout to make sure didn't have any custom CSS affected on your code.
Magento 2
We display product prices both with and without tax in frontend.
By default minimum price and old price is rendered including tax but I have to display minimal price WITHOUT tax.
Any ideas where or how to can change this?
There's no perfect way to do it, best solution I have found is to override the template where the price rendering is happening and use the base amount instead of full amount for "As low as".
My/Theme/Magento_Catalog/templates/product/price/amount/default.phtml
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// #codingStandardsIgnoreFile
?>
<?php /** #var \Magento\Framework\Pricing\Render\Amount $block */ ?>
<?php
if ($block->getDisplayLabel() != 'As low as') {
$price = $block->getDisplayValue();
}
else {
$price = $block->getAmount()->getBaseAmount();
}
?>
<span class="price-container <?php /* #escapeNotVerified */ echo $block->getAdjustmentCssClasses() ?>"
<?php echo $block->getSchema() ? ' itemprop="offers" itemscope itemtype="http://schema.org/Offer"' : '' ?>>
<?php if ($block->getDisplayLabel()): ?>
<span class="price-label"><?php /* #escapeNotVerified */ echo $block->getDisplayLabel(); ?></span>
<?php endif; ?>
<span <?php if ($block->getPriceId()): ?> id="<?php /* #escapeNotVerified */ echo $block->getPriceId() ?>"<?php endif;?>
<?php echo($block->getPriceDisplayLabel()) ? 'data-label="' . $block->getPriceDisplayLabel() . $block->getPriceDisplayInclExclTaxes() . '"' : '' ?>
data-price-amount="<?php /* #escapeNotVerified */ echo $price; ?>"
data-price-type="<?php /* #escapeNotVerified */ echo $block->getPriceType(); ?>"
class="price-wrapper <?php /* #escapeNotVerified */ echo $block->getPriceWrapperCss(); ?>"
<?php echo $block->getSchema() ? ' itemprop="price"' : '' ?>>
<?php /* #escapeNotVerified */ echo $block->formatCurrency($price, (bool)$block->getIncludeContainer()) ?>
</span>
<?php if ($block->hasAdjustmentsHtml()): ?>
<?php echo $block->getAdjustmentsHtml() ?>
<?php endif; ?>
<?php if ($block->getSchema()): ?>
<meta itemprop="priceCurrency" content="<?php /* #escapeNotVerified */ echo $block->getDisplayCurrencyCode()?>" />
<?php endif; ?>
</span>
I trying use zend paginator in my project.
And i have problem-when i trying use paginator in news controller, i have links in paginator on index controller!
<?php
class NewsController extends Zend_Controller_Action
{
/**
*
* #var Model_News_Gateway
*/
protected $_newsGateway;
protected $_newsPerPage = 10;
public function init()
{
$this->_newsGateway = new Model_News_Gateway();
}
public function indexAction()
{
$crit = new ExtZF_Model_Criteria();
$crit->addWhere('active', true);
$crit->addDescOrderBy('publish_date');
$paginator = new Zend_Paginator($this->_newsGateway->getPaginatorAdapter($crit));
$paginator->setCurrentPageNumber($this->_getParam('page', 0));
$paginator->setItemCountPerPage($this->_newsPerPage);
$this->view->paginator = $paginator;
}
In view
$this->paginationControl($this->paginator, 'Sliding', '_partials/paginator/default.phtml');
And in default
<?php if ($this->pageCount && count($this->pagesInRange) > 1): ?>
<!--noindex-->
<div class="paginationControl">
(<?= $this->firstItemNumber ?>-<?= $this->lastItemNumber?>/<?= $this->totalItemCount ?>)
<?php if (isset($this->previous)): ?>
<a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
< <?= $this->translate('previous') ?>
</a> |
<?php else: ?>
<span class="disabled">< <?= $this->translate('previous') ?></span> |
<?php endif; ?>
<?php foreach ($this->pagesInRange as $page): ?>
<?php if ($page != $this->current): ?>
<a href="<?php echo $this->url(array('page' => $page)); ?>">
<?php echo $page; ?>
</a> |
<?php else: ?>
<?php echo $page; ?> |
<?php endif; ?>
<?php endforeach; ?>
<?php if (isset($this->next)): ?>
<a href="<?php echo $this->url(array('page' => $this->next)); ?>">
<?= $this->translate('next') ?> >
</a>
<?php else: ?>
<span class="disabled"><?= $this->translate('next') ?> ></span>
<?php endif; ?>
</div>
<!--/noindex-->
<?php endif; ?>
I am trying use one default paginator for don't same controllers, but i always have links in paginator like /index/index/page/2.
I need links like /news/index/page/2
But i always have links /index/index/page/2
And i in news controller now. I don't understand why it don't work.
<?
//Ужасный хак, мне стыдно за него
$controller = Zend_Controller_Front::getInstance()->getRequest()->getControllerName();
function replaceController ($search, $replace, $text)
{
$pos = strpos($text, $search);
$secondPos =strpos ($text, $search, $pos+1);
if ($secondPos !== false) {
return $pos !== false ? substr_replace($text, $replace, $pos, strlen($search)) : $text;
} else {
return $text;
}
}
?>
So I want to handle two forms on one single page, and I've got some problems to do it; I've got a module named 'contact', here is the indexSucces.php
<div id="registerForm">
<form action="<?php echo url_for('contact'); ?>" method="post" id="loginForm">
<?php foreach ($loginForm as $widget): ?>
<?php if(!$widget->isHidden()) { ?>
<?php echo $widget->renderRow(); ?>
<?php } else { ?>
<?php echo $widget->render() ?>
<?php } ?>
<?php endforeach; ?>
<br/><input type="submit" id="loginSubmit" class="btn primary" value="<?php echo __('Envoyer'); ?>" />
</form>
</div>
<div id="registerForm">
<form action="<?php echo url_for('contact'); ?>" method="post" id="registerForm">
<?php foreach ($registerForm as $widget): ?>
<?php if(!$widget->isHidden()) { ?>
<?php echo $widget->renderRow(); ?>
<?php } else { ?>
<?php echo $widget->render() ?>
<?php } ?>
<?php endforeach; ?>
<br/><input type="submit" id="registerSubmit" class="btn primary" value="<?php echo __('Envoyer'); ?>" />
</form>
</div>
Is it possible to handle that in a single action page ? I need to know the way on how to it, I'm stuck since yesterday. For exemple, when I want to submit the first form, it wants to submit the second form with.
Someone can provide me an exemple ? I can post my sh** action page if you want to see how I tried to handle that.
Thanks in advance !
EDIT:
I made this code according to your advice :
public function executeIndex(sfWebRequest $request)
{
$this->loginForm = new loginForm();
$this->registerForm = new registerForm();
$this->processForm($request, $this->loginForm, $this->registerForm);
}
public function processForm(sfWebRequest $request, sfForm $loginForm, sfForm $registerForm)
{
if($request->hasParameter('login'))
{
if($request->isMethod('post'))
{
$loginForm->bind($request->getParameter($loginForm->getName()));
if($loginForm->isValid())
{
$this->redirect('payement');
}
}
} elseif ($request->hasParameter('register'))
{
if($request->isMethod('post'))
{
$registerForm->bind($request->getParameter($registerForm->getName()));
if($registerForm->isValid())
{
$this->redirect('payement');
}
}
}
}
The registerForm is submitting correctly, I can see the errors I've made in the form etc, and if it's correct, it is correctly redirected. But when I submit the loginForm, here is the error :
Argument 1 passed to sfForm::bind() must be an array, string given : on this line
$loginForm->bind($request->getParameter($loginForm->getName()));
Why ?
Yes, you can.
Add a name attribute to your buttons (i.e. login and register), and modify your action to:
if ($request->hasParameter("login")) {
// handle login
}
elseif ($request->hasParameter("register")) {
// handle register
}