Magento 2 Training : Unit 6 – Lesson A

Before create the template file, we have to create routes, and controller of our module. Our block will have new methods, and our templates will be dynamical !

File : routes.xml

Create the file:
app/code/Maxime/Jobs/etc/frontend/routes.xml

With this content:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="jobs" frontName="jobs">
            <module name="Maxime_Jobs" />
        </route>
    </router>
</config>

Frontend Controller creation

You guess the filename is :
app/code/Maxime/Jobs/Controller/Job/Index.php

Which contains :

<?php
namespace Maxime\Jobs\Controller\Job;
class Index extends \Magento\Framework\App\Action\Action
{
    public function execute()
    {
        $this->_view->loadLayout();
        $this->_view->getLayout()->initMessages();
        $this->_view->renderLayout();
    }
}

Layout creation

The path of the file is :
app/code/Maxime/Jobs/view/frontend/layout/jobs_job_index.xml

With this content :

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" layout="2columns-right">
    <body>
        <referenceContainer name="content">
            <block class="Maxime\Jobs\Block\Job\ListJob" name="jobs_list" template="jobs/list.phtml" />
        </referenceContainer>
    </body>
</page>

Block creation

This part is more interesting 🙂
Create the file
app/code/Maxime/Jobs/Block/Job/ListJob.php

We have to put ListJob because List is a keyword for PHP

Put this content, I will explain it later :

<?php
namespace Maxime\Jobs\Block\Job;
class ListJob extends \Magento\Framework\View\Element\Template
{

    protected $_job;

    protected $_department;

    protected $_resource;

    protected $_jobCollection = null;

    /**
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param \Maxime\Jobs\Model\Job $job
     * @param \Maxime\Jobs\Model\Department $department
     * @param \Magento\Framework\App\ResourceConnection $resource
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Maxime\Jobs\Model\Job $job,
        \Maxime\Jobs\Model\Department $department,
        \Magento\Framework\App\ResourceConnection $resource,
        array $data = []
    ) {
        $this->_job = $job;
        $this->_department = $department;
        $this->_resource = $resource;

        parent::__construct(
            $context,
            $data
        );
    }

    /**
     * @return $this
     */
    protected function _prepareLayout()
    {
        parent::_prepareLayout();


        // You can put these informations editable on BO
        $title = __('We are hiring');
        $description = __('Look at the jobs we have got for you');
        $keywords = __('job,hiring');

        $this->getLayout()->createBlock('Magento\Catalog\Block\Breadcrumbs');

        if ($breadcrumbsBlock = $this->getLayout()->getBlock('breadcrumbs')) {
            $breadcrumbsBlock->addCrumb(
                'jobs',
                [
                    'label' => $title,
                    'title' => $title,
                    'link' => false // No link for the last element
                ]
            );
        }

        $this->pageConfig->getTitle()->set($title);
        $this->pageConfig->setDescription($description);
        $this->pageConfig->setKeywords($keywords);


        $pageMainTitle = $this->getLayout()->getBlock('page.main.title');
        if ($pageMainTitle) {
            $pageMainTitle->setPageTitle($title);
        }

        return $this;
    }

    protected function _getJobCollection()
    {
        if ($this->_jobCollection === null) {

            $jobCollection = $this->_job->getCollection()
                ->addFieldToSelect('*')
                ->addFieldToFilter('status', $this->_job->getEnableStatus())
                ->join(
                    array('department' => $this->_department->getResource()->getMainTable()),
                    'main_table.department_id = department.'.$this->_job->getIdFieldName(),
                    array('department_name' => 'name')
                );

            $this->_jobCollection = $jobCollection;
        }
        return $this->_jobCollection;
    }


    public function getLoadedJobCollection()
    {
        return $this->_getJobCollection();
    }

    public function getJobUrl($job){
        if(!$job->getId()){
            return '#';
        }

        return $this->getUrl('jobs/job/view', ['id' => $job->getId()]);
    }

    public function getDepartmentUrl($job){
        if(!$job->getDepartmentId()){
            return '#';
        }

        return $this->getUrl('jobs/department/view', ['id' => $job->getDepartmentId()]);
    }
}

prepareLayout method create the breadcrumbs and set metas datas of the page.
_getJobCollection method retrieve the collection to get. If it’s already loaded, we return the class attribute. For the addFieldToFilter and join call, we will see that more precisly on the next lesson.
getLoadedJobCollection is public, this is the one will be called on the template file.
getJobUrl method allow us to retrieve the job’s URL
getDepartmentUrl method is the same for departments.

List template creation

Create the file :
app/code/Maxime/Jobs/view/frontend/templates/jobs/list.phtml

With this content :

<?php
    $jobCollection = $this->getLoadedJobCollection();
    $iterator = 1;
    $total = $jobCollection->count();
?>

<div class="job-wrapper">
    <ol class="jobs list">
<?php foreach($jobCollection AS $job): ?>
    <li class="item<?php echo ($iterator == 1) ? ' first' : ''; ?><?php echo ($total == $iterator) ? ' last' : ''; ?>">
        <div class="title">
            <a href="<?php echo $this->getJobUrl($job); ?>" title="<?php echo $job->getTitle(); ?>">
                <?php echo $job->getTitle(); ?>
            </a>
        </div>
        <div class="department_name">
            <?php echo __('Department : '); ?>
            <a href="<?php echo $this->getDepartmentUrl($job); ?>" title="<?php echo $job->getDepartmentName(); ?>">
                <?php echo $job->getDepartmentName(); ?>
            </a>
        </div>
        <div class="type"><?php echo $job->getType(); ?></div>
        <div class="location"><?php echo $job->getLocation(); ?></div>
        <div class="date"><?php echo $this->formatDate($job->getDate()); ?></div>
        <div class="description"><?php echo $job->getDescription(); ?></div>
    </li>
    <?php $iterator++; ?>
<?php endforeach; ?>
    </ol>
</div>

Nothing difficult with this code, you can see the formatDate which convert the date with the format setted on Magento configuration for the store. For example, english date format and french date format are different.
We create the HTML structure with some class which can be useful for the CSS rules.

We should have this render :

rendupage

On the HTML code, meta-datas are present :

<meta name="description" content="Look at the jobs we have got for you"/>
<meta name="keywords" content="job,hiring"/>
<title>We are hiring</title>

Next step, I will explain how to use Magento collections and Zend selects.

Continue training
Return to previous lesson
Create the frontend HTML of your Magento 2 module
Share on FacebookTweet about this on TwitterShare on Google+Email this to someone
Tagged on:     

2 thoughts on “Create the frontend HTML of your Magento 2 module

  • 12/04/2017 at 08:57
    Permalink

    Hi,
    it’s a great tutorial, the only one which helped me to get through with well understanding.
    I’ve now displayed the html, but what I would like to know is: how can I get for example all department names dislayed in a dropdown ON THE FRONTEND?

    Reply
  • 05/14/2018 at 13:58
    Permalink

    Hii,
    please can you provide zip file of this module. Actually i didn’t get Database table,

    Thank you

    Reply

Leave a Reply to Nessi Cancel reply

Your email address will not be published. Required fields are marked *

We use cookies to ensure that we give you the best experience on our website.
Ok