Magento 2 - Display Custom Product Attributes in Product Details Tab - magento2

I have created several custom product attributes and I need them to display on the Product Details tab if data has been entered in the Magento Admin. There are three in total and on a lot of occasions all three will have data but there will be around 20% of products where one or two of the have data.
I have created the attributes easily enough but I am struggling to get them to display on the frontend. I have pasted the code for the layout file and the phtml file for the attributes.
The result I am getting is a blank product screen with no info at all. Definitely an error somewhere but after hours of looking I am missing it.
Below is the custom catalog_product_view.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page layout="2columns-right" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<move element="product.info.stock.sku" destination="product.info.price" after="product.price.final"/>
<move element="page.main.title" destination="product.info.main" before="-"/>
<referenceBlock name="product.info.overview" remove="true"/>
<referenceBlock name="product.info.details">
<block class="Magento\Catalog\Block\Product\View\Description" name="product.info.description." template="Magento_Catalog::product/view/product_attributes.phtml" group="detailed_info">
<arguments>
<argument name="at_call" xsi:type="string">getDescription</argument>
<argument name="at_code" xsi:type="string">description</argument>
<argument name="css_class" xsi:type="string">description</argument>
<argument name="at_label" xsi:type="string">none</argument>
<argument name="title" translate="true" xsi:type="string">Product Details</argument>
</arguments>
</block>
<block class="Magento\Catalog\Block\Product\View" name="deliveryinfo.tab" as="deliveryinfo" template="product/view/delivery_info.phtml" group="detailed_info" >
<arguments>
<argument translate="true" name="title" xsi:type="string">Delivery</argument>
</arguments>
</block>
</referenceBlock>
<referenceContainer name="sidebar.main">
<block class="Magento\Cms\Block\Block" name="sidebar_delivery" after="-">
<arguments>
<argument name="block_id" xsi:type="string">sidebar_delivery</argument>
</arguments>
</block>
<block class="Magento\Cms\Block\Block" name="sidebar_instructions" after="-">
<arguments>
<argument name="block_id" xsi:type="string">sidebar_instructions</argument>
</arguments>
</block>
<block class="Magento\Cms\Block\Block" name="sidebar_brochures" after="-">
<arguments>
<argument name="block_id" xsi:type="string">sidebar_brochures</argument>
</arguments>
</block>
<block class="Magento\Cms\Block\Block" name="sidebar_blog" after="-">
<arguments>
<argument name="block_id" xsi:type="string">sidebar_blog</argument>
</arguments>
</block>
</referenceContainer>
</body>
</page>
Below is product_attributes.phtml called in the Layout file
<?php
$_helper = $this->helper('Magento\Catalog\Helper\Output');
$_product = $block->getProduct();
$_code = $block->getAtCode();
$_className = $block->getCssClass();
$_attributeLabel = $block->getAtLabel();
$_attributeType = $block->getAtType();
$_attributeAddAttribute = $block->getAddAttribute();
if ($_attributeLabel && $_attributeLabel == 'default') {
$_attributeLabel = $_product->getResource()->getAttribute($_code)->getFrontendLabel();
}
$_attributeValue =$_product->getResource()->getAttribute($_code)->getFrontend()->getValue($_product);
?>
<?php if ($_attributeValue): ?>
<div>
<?php if ($_attributeLabel != 'none'): ?><strong class="type"><?php echo $_attributeLabel?></strong><?php endif; ?>
<div class="value" <?php echo $_attributeAddAttribute;?>><?php echo $_attributeValue; ?></div>
</div>
<?php endif; ?>
<?php
$dimensions = $_product->getResource()->getAttribute('dimensions')->getFrontend()->getValue($_product);
$features_benefits = $_product->getResource()->getAttribute('features_benefits')->getFrontend()->getValue($_product);
$flooring_specification = $_product->getResource()->getAttribute('flooring_specification')->getFrontend()->getValue($_product);
if (!empty($dimensions) || !empty($features_benefits) || !empty($flooring_specification) {
?>
<?php
if (!empty($dimensions)) {
?>
<h2>Dimensions</h2>
<?php echo $dimensions; ?>
<?php
}
if (!empty($features_benefits)) {
?>
<h2>Features & Benefits</h2>
<?php echo $features_benefits; ?>
<?php
}
if (!empty($flooring_specification)) {
?>
<h2>Specification</h2>
<?php echo $flooring_specification; ?>
<?php
}
?>
<?php
}
?>
It is probably something laughably simple I have done wrong but I can't for the life of me find it.
The site is on Community Edition 2.2.5 and the server is running PHP 7.1
Any suggestions appreciated.
Kev

Solved the issue in the end. I missed out a closing bracket.
This line:
if (!empty($dimensions) || !empty($features_benefits) || !empty($flooring_specification) {
Should have been:
if (!empty($dimensions) || !empty($features_benefits) || !empty($flooring_specification)) {
I knew it would have been something simple. Works perfectly now.

Related

Magento 2 // Show "Offer Label" on category pages // Amasty Special Promotions

We have a Magento 2 site running Amasty Special Promotions, the "offer label" is showing on the product pages as expected however, it's not showing on the category pages at all. How could this be added, I came across this code in the Amasty extension:
In catalog_product_view.xml
<referenceContainer name="product.info.media">
<block before="-" class="Amasty\BannersLite\Block\Banner" name="amasty.banners.lite.label" template="label.phtml">
<action method="setPosition">
<argument name="position" xsi:type="string">2</argument>
</action>
</block>
</referenceContainer>
In label.phtml:
<?php foreach ($block->getBanners() as $banner) : ?>
<?php if ($block->isEnableBannerPosition() && $img = $block->getImage($banner)) : ?>
<img class="am-banners-lite-label"
alt="<?= $block->escapeHtml($block->getAlt($banner)) ?>"
src="<?= $block->escapeUrl($img) ?>">
<?php endif;?>
<?php endforeach; ?>
"catalog_product_view" fie is layout file for product page.
if you want to display on category page add file in your theme design folder "catalog_category_view.xml" :
<referenceContainer name="content">
<block before="-" class="Amasty\BannersLite\Block\Banner"
name="amasty.banners.lite.label" template="label.phtml">
<action method="setPosition">
<argument name="position" xsi:type="string">2</argument>
</action>
</block>
</referenceContainer>

Checkout Steps Mixed

I have created a step in checkout between shipping step and payment step according to magento documentation Add a new checkout step
But when I display the checkout, step 1 and step 2 are vissible in the same view, how can I make it to show step 1 first and step 2 later?
I'm using Magento 2.1.
Here is my code:
layout/checkout_index_index.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<!-- The new step you add -->
<item name="contacts" xsi:type="array">
<item name="component" xsi:type="string">CloudMobile_Contacts/js/view/contacts</item>
<!--To display step content before shipping step "sortOrder" value should be < 1-->
<!--To display step content between shipping step and payment step 1 < "sortOrder" < 2 -->
<!--To display step content after payment step "sortOrder" > 2 -->
<!--<item name="sortOrder" xsi:type="string">2</item>-->
<item name="children" xsi:type="array">
<!--add here child component declaration for your step-->
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
web/js/view/contacts.js
define(
[
'ko',
'uiComponent',
'underscore',
'Magento_Checkout/js/model/step-navigator',
'Magento_Customer/js/model/customer',
'jquery'
],
function (
ko,
Component,
_,
stepNavigator,
customer,
$
) {
'use strict';
/**
*
* mystep - is the name of the component's .html template,
* <Vendor>_<Module> - is the name of the your module directory.
*
*/
return Component.extend({
defaults: {
template: 'CloudMobile_Contacts/contacts'
},
//add here your logic to display step,
isVisible: ko.observable(true),
/**
*
* #returns {*}
*/
initialize: function () {
this._super();
// register your step
stepNavigator.registerStep(
//step code will be used as step content id in the component template
'contacts',
//step alias
null,
//step title value
'Contacto',
//observable property with logic when display step or hide step
this.isVisible,
_.bind(this.navigate, this),
/**
* sort order value
* 'sort order value' < 10: step displays before shipping step;
* 10 < 'sort order value' < 20 : step displays between shipping and payment step
* 'sort order value' > 20 : step displays after payment step
*/
15
);
this.getContacts(this);
return this;
},
/**
* The navigate() method is responsible for navigation between checkout step
* during checkout. You can add custom logic, for example some conditions
* for switching to your custom step
*/
navigate: function () {
},
/**
* #returns void
*/
navigateToNextStep: function () {
this.saveContact();
stepNavigator.next();
},
/**
* Obtiene la lista de contactos relacionados a la cuenta
* #param {Object} scope
* #returns void
*/
getContacts: function(scope){
var url = 'some_url';
$.ajax({
url: url,
type: 'GET',
crossDomain: true,
jsonpCallback: 'jsonCallback',
dataType: 'jsonp',
data: {
accountnum: customer.customerData.custom_attributes.sfdc_id.value
}
})
.success(function(response){
scope.contacts = response;
});
},
/**
* Guarda en la orden al contacto que realizó el pedido
* #param void
* #returns void
*/
saveContact: function(){
console.log($('select#contact').val());
}
});
}
);
web/js/template/html.js
<li id="contacts" data-bind="fadeVisible: isVisible">
<div class="step-title" data-bind="i18n: 'Contacto'" data-role="title"></div>
<div id="checkout-step-title"
class="step-content"
data-role="content">
<form data-bind="submit: navigateToNextStep" novalidate="novalidate">
<select name="contacto" id="contact">
<!-- ko foreach: contacts -->
<option data-bind="value: Id,
text: Name"></option>
<!-- /ko -->
</select>
<div class="actions-toolbar">
<div class="primary">
<button data-role="opc-continue" type="submit" class="button action continue primary">
<span><!-- ko i18n: 'Next'--><!-- /ko --></span>
</button>
</div>
</div>
</form>
</div>
</li>
Screenshot:
Checkout
Solved!
To avoid mixed steps views, I just changed this:
isVisible: ko.observable(true)
For this:
isVisible: ko.observable(false)

Top rated products magento 2

I want to display top rated products in magento 2
My block Toprated.php
public function getTesting()
{
$collection = $this->_productCollectionFactory->create();
foreach($collection as $eachColl)
{
$storeId = $eachColl->getStore()->getId();
$reviewSum = $this->reviewSummaryFactory->create()->setStoreId($storeId)->load($eachColl->getId());
$rated[] = array(
'rating' => $reviewSum['rating_summary'],
'name' => $eachColl->getName(),
'url' => $eachColl->getUrlPath(),
'product_sku' => $eachColl->getSku()
);
$rateds[$eachColl->getSku()] = $reviewSum['rating_summary'];
}
arsort($rateds);
$rateds = array_slice($rateds, 0, 3);
$collection = $this->_productCollectionFactory->create();
$collection->addAttributeToFilter('status', '1');
$collection->addAttributeToFilter('rating', array('in' => implode(",", $rateds)));
return $collection;
}
my template toprated.phtml file
<?php
$_productCollection = $this->getTesting();
$_helper = $this->helper('Magento\Catalog\Helper\Output');
$_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
?>
but phtml file not calling any data.what i did mistake here
Where do you want to show the new block ?
It is possible by edit/add a layout file in view/frontend/layout/
<?xml version="1.0" encoding="UTF-8"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<referenceContainer name="content">
<block
template="[your template]"
class="[your class]"
name="[your name]"/>
</referenceContainer>
create layout file in view -> frontend -> templates -> layout ,
file name should be your routname_controllernamespace_controllername (controller->Index->index.php)
ex. blog_index_index file should be look like this
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="Demo\Blog\Block\PostList" name="demo.list" template="Demo_Blog::list.phtml" />
</referenceContainer>
</body>
</page>

Show category with images in homepage Magento2

Show category with images in homepage Magento2
http://ibnab.com/en/blog/magento-2/magento-2-frontend-how-to-call-category-collection-on-home-page
This article working fine but I need to show category image.How to fetch category images also
I am using $category->getImageUrl();
but its not working
I was able to get this to show on the homepage by combining the tutorial and R T's answer. Because i didn't have a _objectManager (and the page was kicking an error when i tried R T's code) working on that page, I included the category model in the block file (Collection.php)
protected $_categoryHelper;
protected $categoryFlatConfig;
protected $topMenu;
protected $categoryView;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Catalog\Helper\Category $categoryHelper,
\Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState,
\Magento\Theme\Block\Html\Topmenu $topMenu,
\Magento\Catalog\Model\Category $categoryView
) {
$this->_categoryHelper = $categoryHelper;
$this->categoryFlatConfig = $categoryFlatState;
$this->topMenu = $topMenu;
$this->categoryView = $categoryView;
parent::__construct($context);
}
I then added a method to call in the phtml at the bottom of the block file.
public function getCategoryView() {
return $this->categoryView;
}
In the phtml (storecategories.phtml) I changed up the code to work like this.
<?php
$categories = $this->getStoreCategories(true,false,true);
$categoryHelper = $this->getCategoryHelper();
?>
<ul>
<?php
foreach($categories as $category):
if (!$category->getIsActive()) {
continue;
}
?>
<li><a href="<?php echo $categoryHelper->getCategoryUrl($category) ?>">
<?php
$catId = $category->getId();
$categoryAgain = $this->getCategoryView()->load($catId);
$_outputhelper = $this->helper('Magento\Catalog\Helper\Output');
$_imgHtml = '';
if ($_imgUrl = $categoryAgain->getImageUrl()) {
$_imgHtml = '<img src="' . $_imgUrl . '" />';
$_imgHtml = $_outputhelper->categoryAttribute($categoryAgain, $_imgHtml, 'image');
/* #escapeNotVerified */
echo $_imgHtml;
}
?>
<?php echo $category->getName() ?></a></li>
<?php endforeach; ?>
</ul>
And then i added the new call into the di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Ibnab\CategoriesSide\Block\CategorisCollection">
<arguments>
<argument name="deleteorderAction" xsi:type="array">
<item name="context" xsi:type="string">\Magento\Framework\View\Element\Template\Context</item>
<item name="helper" xsi:type="string">\Magento\Catalog\Helper\Category</item>
<item name="flatstate" xsi:type="string">\Magento\Catalog\Model\Indexer\Category\Flat\State</item>
<item name="menu" xsi:type="string">\Magento\Theme\Block\Html\Topmenu</item>
<item name="categoryview" xsi:type="string">\Magento\Catalog\Model\Category</item>
</argument>
</arguments>
</type>
I've managed to do this as below in template:
$category = $this->_objectManager->create('Magento\Catalog\Model\Category')->load($item->getId());
$_outputhelper = $this->helper('Magento\Catalog\Helper\Output');
$_imgHtml = '';
if ($_imgUrl = $category->getImageUrl()) {
$_imgHtml = '<img src="' . $_imgUrl . '" />';
$_imgHtml = $_outputhelper->categoryAttribute($category, $_imgHtml, 'image');
/* #escapeNotVerified */
echo $_imgHtml;
}
hope it helps

Magento Checkout Comment

i'm still a beginner at Magento and try to learn how to create Modules. Right now i'm working on a module, which allows the customer to add a comment during the checkout.
Now i got a problem to implement the textarea, i created a new file called "practice" under app/design/frontend/base/default/layout and under app/design/frontend/base/default/template. I upload the new layout-file in the config.xml file of my module. But there isnt any textarea during the checkout, even though the right template is uploaded (i activated the template path hint option to see the path of each Block).
app/code/local/Practice/CheckoutComments/etc/config.xml
<frontend>
<layout>
<updates>
<checkoutcomments>
<file>practice/checkoutcomments.xml</file>
</checkoutcomments>
</updates>
</layout>
</frontend>
Here is the code of the layout.xml file and the phtml.file i override:
app/design/frontend/base/default/layout/practice/checkoutcomments.xml
<?xml version="1.0" encoding="UTF-8"?>
<layout>
<checkout_onepage_review translate="label">
<reference name="checkout.onepage.agreements">
<action method="setTemplate">
<template>practice/checkoutcomments/onepage/comment-agreements.phtml
</template>
</action>
</reference>
</checkout_onepage_review>
</layout>
app/design/frontend/base/default/template/practice/checkoutcomments/onepage/comment-agreements.phtml
<?php
/**
*
* #see Mage_Checkout_Block_Agreements
*/
?>
<!-- Start of CheckoutComments module code -->
<form action="" id="checkout-agreements" onsubmit="return false;">
<ol class="checkout-agreements">
<div>
<br /> <label for="checkoutcomments"><?php echo Mage::helper('core')->__('Add your Comment for this Order') ?></label>
<textarea name="checkoutcomments" id="checkoutcomments"
style="width: 450px; height: 100px;"></textarea>
</div>
<!-- End of CheckoutComment module -->
<?php if ($this->getAgreements()) : ?>
<?php foreach ($this->getAgreements() as $_a): ?>
<li>
<div class="agreement-content"
<?php echo ($_a->getContentHeight() ? ' style="height:' . $_a->getContentHeight() . '"' : '')?>>
<?php if ($_a->getIsHtml()):?>
<?php echo $_a->getContent()?>
<?php else:?>
<?php echo nl2br($this->escapeHtml($_a->getContent()))?>
<?php endif; ?>
</div>
<p class="agree">
<input type="checkbox" id="agreement-<?php echo $_a->getId()?>"
name="agreement[<?php echo $_a->getId()?>]" value="1"
title="<?php echo $this->escapeHtml($_a->getCheckboxText()) ?>"
class="checkbox" /><label for="agreement-<?php echo $_a->getId()?>"><?php echo $_a->getIsHtml() ? $_a->getCheckboxText() : $this->escapeHtml($_a->getCheckboxText()) ?></label>
</p>
</li>
<?php endforeach ?>
<?php endif; ?>
</ol>
</form>
I deactivated my module and overrode the code of app/design/frontend/base/default/template/checkout/onepage/agreements.phtml with my customized pthml.file from above, then the textarea appears! I guess that something is wrong with my configurationsfiles, but i reference to the right block, since the block is uploaded but there isnt any textarea.
I hope you can help me
Regards
I solved the question by accident:
In
app/design/frontend/base/default/layout/practice/checkoutcomments.xml
i changed the line
<template>practice/checkoutcomments/onepage/comment-agreements.phtml
</template>
to:
<template>practice/checkoutcomments/onepage/comment-agreements.phtml</template>
it seems that i choose a wrong autoformat in eclipse, but i'm wondering, that this makes such a huge difference
Regards