0

I am looking for some solution to make javascript run before phtml code.

My work is sends width and height of my screen to controller, and it will send back to phtml file(because we cant check width and height with php code, we have to do it in javascript code).

But for some reason, the ajax is called after phtml code.
So it makes an issue because the data was not sended from ajax.
Here is my phtml file

C:\xampp\htdocs\magento\app\code\Aht\BannerSlider\view\frontend\templates\index.phtml

<?php /** @var Aht\BannerSlider\Block\Frontend\Index $block */ ?>
<div>
 <?php
 if($block->checkAllowedPage()):
 foreach($block->checkAllowedPage() as $rowsBannerPage):
 $banner_id = $rowsBannerPage['banner_id'];
 if(!empty($block->getBannerSlideById($banner_id))):
 ?>
 <div class="slick-custom">
 <div class="banner-slider">
 <?php
 foreach($block->getBannerSlideById($banner_id) as $rowsBannerSlide):
 ?>
 <?php
 $slide = $block->getSlideById($rowsBannerSlide['slide_id']);
 // resize img
 $image = $this->helper('Aht\BannerSlider\Helper\Image');
 $block->getResolutionScreen();
 $resolition_screen = $image->getResolutionScreen();
 $width = $resolition_screen[0];
 $height = $resolition_screen[1];
 ?>
<!-- 1366,768 = max width màn hình -->
 <div><img src="<?php echo $image->resize($slide->getImage(), $width, $height); ?>" style="width: 100%; height: auto;"></div>
 <?php
 endforeach;
 ?>
 </div>
 <div class="slick-arrows-custom">
 <i class="prev fa fa-arrow-circle-left"></i>
 <i class="next fa fa-arrow-circle-right"></i>
 </div>
 </div>
 <?php endif; ?>
 <?php
 endforeach;
 ?>
 <script>
 require([
 'jquery',
 'slick'
 ], function ($) {
 $(document).ready(function () {
 $('.banner-slider').each(function(){
 $(this).slick({
 speed: 300,
 autoplay: true,
 arrows: true,
 prevArrow: $(this).parents('.slick-custom').find('.prev'),
 nextArrow: $(this).parents('.slick-custom').find('.next'),
 responsive: [
 {
 fade: true,
 breakpoint: 480,
 settings: {
 dots: true
 }
 }
 ]
 });
 });
 $.ajax({
 url: 'http://localhost/magento/banner/slide/image',
 method: 'GET',
 data: {
 width: screen.width,
 height: screen.height
 }
 });
 });
 });
 </script>
 <?php
 endif;
 ?>
</div>

It return issue with $width and $height because it return null.

Okay so if you need more information or code to check.

Teja Bhagavan Kollepara
3,8275 gold badges33 silver badges69 bronze badges
asked Aug 16, 2018 at 6:48

3 Answers 3

1

You can put the AJAX call inside slick. Then use the event afterChange to trigger your AJAX after the slider is loaded.

<script>
 require([
 'jquery',
 'slick'
 ], function ($) {
 $(document).ready(function () {
 $('.banner-slider').each(function(){
 $(this).slick({
 speed: 300,
 autoplay: true,
 arrows: true,
 prevArrow: $(this).parents('.slick-custom').find('.prev'),
 nextArrow: $(this).parents('.slick-custom').find('.next'),
 responsive: [
 {
 fade: true,
 breakpoint: 480,
 settings: {
 dots: true
 }
 }
 ],
 init: function(){
 $.ajax({
 url: 'http://localhost/magento/banner/slide/image',
 method: 'GET',
 data: {
 width: screen.width,
 height: screen.height
 }
 });
 }
 });
 });
 });
 });
</script>

Ref: Official Github

======Update on 16 Aug 2018 15:49======

If you want to resize the slick slider on resize you can simply insert this code into JS:

$(window).resize(function() {
 $('.banner-slider').slick('resize');
});

So that the result will look like this:

<script>
 require([
 'jquery',
 'slick'
 ], function ($) {
 $(document).ready(function () {
 $('.banner-slider').each(function(){
 $(this).slick({
 speed: 300,
 autoplay: true,
 arrows: true,
 prevArrow: $(this).parents('.slick-custom').find('.prev'),
 nextArrow: $(this).parents('.slick-custom').find('.next'),
 responsive: [
 {
 fade: true,
 breakpoint: 480,
 settings: {
 dots: true
 }
 }
 ],
 init: function(){
 $.ajax({
 url: 'http://localhost/magento/banner/slide/image',
 method: 'GET',
 data: {
 width: screen.width,
 height: screen.height
 }
 });
 }
 });
 });
 $(window).resize(function() {
 $('.banner-slider').slick('resize');
 });
 });
 });
</script>

Source: Github Ticket

answered Aug 16, 2018 at 7:17
11
  • Thanks for reply :) But i thing you are misunderstood me. I want to send it before all phtml code, wasn't in slick call. Because there need an image to slick, and right now, without the ajax call, i dont have any image to make a slick slider. :) Commented Aug 16, 2018 at 7:27
  • How about using init? It will run your AJAX call before the slider load Commented Aug 16, 2018 at 7:30
  • Okay so, right now, it need at least 1 img to run into slick slider right? But right now i dont have any image because the ajax is not called success. Commented Aug 16, 2018 at 7:31
  • So i cant do anything with slick slider right now. Commented Aug 16, 2018 at 7:31
  • You don't need to load the 1st image to get the screen width and height. It can calculate automatically Commented Aug 16, 2018 at 7:33
0

Now a days we have option in CSS to detect window width .

you can check this here : https://web-design-weekly.com/2014/11/18/viewport-units-vw-vh-vmin-vmax/

vw : means view width

100 vw means 100% of width .

This will surely solve your issue very efficiently and in optimized speedy way. Try and let me know your feedback . Thanks

answered Aug 16, 2018 at 7:27
8
  • hold up, so how to send my screen solution from css to php code? Commented Aug 16, 2018 at 7:29
  • create a "class" in html tag and pass in ajax or any front end html element. class can be added in style css file . thanks Let me know if any confusion. Commented Aug 16, 2018 at 7:36
  • so we still have to use ajax to send information? Commented Aug 16, 2018 at 7:40
  • So what's the diffrence? :'( Commented Aug 16, 2018 at 7:41
  • your query : "But for some reason, the ajax is called after phtml code." You need to know that server side code will run first then client side javascript code will run or execute . Hence to make it more appropriate you must try to call complete block or controller in ajax . Hope that will surely solve ur issue . Commented Aug 16, 2018 at 8:17
0

Ok so my leader give me the answer, and also, thanks for helping of @Ramesh Chauhan and @PY Yick, they helped me a lot :')

So here is the idea:
Instead of find the solution to make javascript run before all phtml code, we will make 2 file phtml, the first one use ajax to send data to a new action, and we have to create 1 new action to catch that ajax data.
And then, we do stuff in that new action with the data we passed throught ajax.(do stuff here is hard to explain, so please look at my code to understand that :'< , sorry about that)
After that, we create a new div and call success function() in ajax and append the html to that new div we just created before.

So here is the code i've done and success:

C:\xampp\htdocs\magento\app\code\Aht\BannerSlider\view\frontend\templates\index.phtml

This file is the first phtml file and also, it the one who have ajax.

<?php
$check = $this->helper('Aht\BannerSlider\Helper\Check');
if ($check->checkAllowedPage() != false):
 $full_route = $check->checkAllowedPage();
 ?>
 <div id="banner_slide_after_ajax_loaded"></div>
 <script>
 require([
 'jquery'
 ], function ($) {
 $(document).ready(function () {
 $.ajax({
 url: 'http://localhost/magento/banner/slide/image',
 method: 'GET',
 dataType: 'html', // muốn render html thì cần phải có dòng này.
 data: {
 width: screen.width,
 height: screen.height,
 full_route: '<?php echo $full_route; ?>'
 },
 success: function (response) {
 response = $.parseJSON(response);
 // if (response.error) {
 // alert('failed');
 // } else {
 $('#banner_slide_after_ajax_loaded').append(response.html);
 // }
 }
 });
 });
 });
 </script>
<?php endif; ?>

You see the url: 'http://localhost/magento/banner/slide/image', right? Its the new action that i mentioned.
So here is it:

C:\xampp\htdocs\magento\app\code\Aht\BannerSlider\Controller\Slide\Image.php

This is controller of the new action, which catch the ajax data and do stuff, and then return $respone. And ajax use that respone in the success function(), take a look at my ajax code.
The key in here is this code:

$html = $resultPage->getLayout()
 ->createBlock('Aht\BannerSlider\Block\Frontend\Slide')
 ->setTemplate('Aht_BannerSlider::slide.phtml')
 ->toHtml();


This code call to a new block and new phtml file, which will be the content of response.html which i've call in success function in ajax

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 17/07/2018
 * Time: 4:35 CH
 */
namespace Aht\BannerSlider\Controller\Slide;
class Image extends \Magento\Framework\App\Action\Action
{
 protected $_pageFactory;
 protected $coreRegistry;
 protected $resultJsonFactory;
 public function __construct(
 \Magento\Framework\App\Action\Context $context,
 \Magento\Framework\Registry $coreRegistry,
 \Magento\Framework\View\Result\PageFactory $pageFactory,
 \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
 )
 {
 $this->coreRegistry = $coreRegistry;
 $this->_pageFactory = $pageFactory;
 $this->resultJsonFactory = $resultJsonFactory;
 return parent::__construct($context);
 }
 public function execute()
 {
// gửi width,height và full_route qua block bằng register
 $width = $this->getRequest()->getParam('width');
 $height = $this->getRequest()->getParam('height');
 $full_route = $this->getRequest()->getParam('full_route');
 $resolution_screen = array($width,$height);
 $this->coreRegistry->register('resolution_screen', $resolution_screen);
 $this->coreRegistry->register('full_route', $full_route);
 $resultPage = $this->_pageFactory->create();
 $html = $resultPage->getLayout()
 ->createBlock('Aht\BannerSlider\Block\Frontend\Slide')
 ->setTemplate('Aht_BannerSlider::slide.phtml')
 ->toHtml();
 $resultJson = $this->resultJsonFactory->create();
 $error = false;
 $respone = $resultJson->setData(['html' => $html, 'error' => $error]);
// $result = ['html' => $html, 'error' => false];
// if(true) {
// $result['error'] = true;
// }
 return $respone;
 }
}



Okay, that's all you need to know to make this works. And if you want to know more about the slide.phtml and block that i mentioned up there, please let me know.

Thanks for helping me, happy coding :')

answered Aug 17, 2018 at 3:30

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.