8

I am doing a web app on Yii2 framework. Defined (extended) new AssetBundle

class NeonAsset extends AssetBundle {
   public $sourcePath = '@app/themes/neon/';

   public $css = [
    'css/font-icons/entypo/css/entypo.css',
    '...',
    '...'        
   ];

   public $js = [
      'js/be_in_head_tag.js',
      '...',
      '...',
   ];
}

When rendered, CSS files are being published in <head> tag, and JS files at the bottom of <body> tag. It is ok.
But I want a single be_in_head_tag.js file to be published in <head> tag. And when I use $jsOptions it moves all JS files into the <head> tag.
Is it possible to make options only for one file?

3 Answers3

9

One of the variants make that file into a separate asset class:

class HeadPublishAsset extends AssetBundle {
    public $sourcePath = '@app/themes/neon/';
    public $js = ['js/be_in_head_tag.js'];
    public $jsOptions = ['position' => \yii\web\View::POS_HEAD];
}

And add a dependency to your base class like:

class NeonAsset extends AssetBundle {
    ...
    public $depends = ['app\assets\HeadPublishAsset'];
    ...
}
iamawebgeek
  • 2,713
  • 1
  • 18
  • 34
  • I thought it can be configured in the base class itself. But seems it is the only way. Thanks for your answer –  Jun 02 '15 at 05:17
2

I'm pleased to say that the ability to do this at the file level has been added to Yii2 at some point. It doesn't however appear in any of the documentation examples. I've tested and confirmed...

class NeonAsset extends AssetBundle {
   public $sourcePath = '@app/themes/neon/';

   public $css = [
    'css/font-icons/entypo/css/entypo.css',
    '...',
    '...'        
   ];

   public $js = [
      ['js/be_in_head_tag.js', 'position' => \yii\web\View::POS_HEAD],
      '...',
      '...',
   ];
}

Options included in the $js array are now passed to the relevant method and result in the file being included in the selected part of the html file.

Harry B
  • 2,864
  • 1
  • 24
  • 44
0

I don't know if there's an official way of doing it (probably not as it would make the specification of the options object overly complicated), however there's another easier way compared to the accepted answer which doesn't require you to create another AssetBundle.

All you need to do is create another array, for example:

public $head_js =
[
  "path/to/src.js"
];

Then override the registerAssetFiles function like so:

public function registerAssetFiles($view)
{
  foreach($this->head_js as $js)
  {
    $options = [];
    $options["position"] = \yii\web\View::POS_HEAD;
    $url = Url::to($this->baseUrl . "/" . $js);
    $view->registerJsFile($url, $options);
  }

  parent::registerAssetFiles($view);
}
Hayko Koryun
  • 1,214
  • 2
  • 12
  • 30