1
votes

I guess this question might have the same outcome as How do I use "Main Layout" views in a multi module Phalcon application?

My Main Layout view has the basic html structure of my entire app and I'm using the controller layout view to present the content of that controller. I believe I am doing it right so far?

But now I have a problem with needing to load specific JS and CSS files relevant to just that module controller in my Main Layout view.

Currently I am loading all CSS and JS in my Main Layout file but this completely goes against the multi module approach. Each module should be able to load css/js files without having to modify a core layout file.

Ideally I would love to follow the same approach as setting page titles

Controller: Phalcon\Tag::setStylesheetLink("http://fonts.googleapis.com/css?family=Rosario", false);

Views: echo Phalcon\Tag::getStylesheetLink();

Is there any other way I can accomplish this that I might be missing?

2

2 Answers

4
votes

At the moment there is no way to create some sort of ordering function (stylesheets are printed out with the order you set them) or a collection facility where you just add stylesheets to \Phalcon\Tag::stylesheetLink() and they can be printed out.

However you can achieve what you need with a custom class as follows:

In your config.ini you have this section

[resource]
css.bootstrap = "/public/css/bootstrap.css"
css.index     = "/public/css/index.css"
css.about     = "/public/css/about.css"
css.contact   = "/public/css/contact.css"

Create a class \MyApp\Tag

namespace MyApp;

class Tag
{
    private $_css = array();

    public function add($css)
    {
        $this->_css[$css] = true;
    }

    public function remove($css)
    {
        $this->_css[$css] = false;
    }

    public function clear()
    {
        $this->_css = array();
    }

    public function generate()
    {
        $config = \Phalcon\DI::getDefault()->get('config');
        $output = '';

        foreach ($this->_css as $css => $active)
        {
            if ($active)
            {
                if (isset($config->resource->css->$css))
                {
                    $output .= \Phalcon\Tag::stylesheetLink($config->resource->css->$css);
            }
        }

        return $output;
    }
}

Then in your controller you can just do something like:

$style = new \MyApp\Tag();
$style->add('bootstrap');
$style->add('about');

$this->view->setVar('stylesheets', $style->generate();

and in your view:

<?php echo $stylesheets; ?>
0
votes

Here is a way you can manually manipulate the order of your js and css file assets.

First, when adding css and js paths in the controllers, use the automatic Phalcon\Assets\Collection containers to store your ad-hoc assets:

$this->assets->addJs('js/bootstrap-multiselect.js');
$this->assets->addCss('css/bootstrap-multiselect.css');

In your custom BaseController from which all your controllers extend, add an afterExecuteRoute() public method:

/**
 * stuff to do after a route has been executed
 * this is where we attach standard js and css assets
 * */
public function afterExecuteRoute(){
    // wait to rebuild assets until after the dispatcher is finished
    if( ! $this->dispatcher->isFinished() ){
        return;
    }
    ...
}

Once we're sure the current route is finished executing, we can pull the ad-hoc assets from the automatic js and css collections in the Phalcon\Assets\Manager, append them to our list of common asset files, order and dedup them, and then put them into new custom collections:

// get list of js files added to the standard js collection
$append_js = array();
forEach( $this->assets->getJs() as $js){
    $append_js[] = $js->getPath();
}
// declare paths to common js assets
$js_assets = array(
    'js/jquery-2.1.1.min.js',
    'js/jquery-ui.min.js',
    'js/bootstrap.min.js',
);
// merge common paths with ad-hoc paths
$js_assets = array_merge( $js_assets, $append_js );
$js_assets = array_unique( $js_assets ); // dedup
// add js assets to a new collection
$js_collection = $this->assets->collection('header_js');
forEach( $js_assets as $js_path ){
    $js_collection->addJs( $js_path );
}

Rebuilding the css assets into a new collection works the same way:

// get list of css files added to the standard css collection
$append_css = array();
forEach( $this->assets->getCss() as $css ){
    $append_css[] = $css->getPath();
}
// declare paths to common css assets
$css_assets = array(
    'css/jquery-ui.min.css',
    'css/jquery-ui.theme.min.css',
    'css/jquery-ui.structure.min.css',
    'css/bootstrap.min.css',
    'css/bootstrap-theme.min.css',
    'css/main.css',
);
// merge common paths with ad-hoc paths
$css_assets = array_merge( $css_assets, $append_css );
$css_assets = array_unique( $css_assets ); // dedup
// add css assets to a new collection
$css_collection = $this->assets->collection('header_css');
forEach( $css_assets as $css_path ){
    $css_collection->addCss( $css_path );
}

Finally, when you output your js and css assets in your template, output your new custom collections instead of the default collections that the Phalcon\Assets\Manager automatically created:

{{ getDoctype() }}
<html>
    <head>
        {{ tag.getTitle() }}
        {{ assets.outputCss( 'header_css' ) }}
        {{ assets.outputJs( 'header_js' ) }}
    </head>