In a previous episode a Zend Framework 2 vendor module was created in the Orinoco River project. We left the module rather empty so now is the time to give it some content. Front-end content. And any content will do because the main concern for this recap is asset management. A periodic table then.

A fundamental issue with modules is the location of the assets. Assets in the context of web applications are vague. In Symfony doctrine assets are “things like CSS, JavaScript and image files that make the frontend of your site look and work great

In technical terms a requirement is that any asset must be stored somewhere in the public directory. In our universe this public folder is called public_html. Of course in ZF2 the main application already has a public_html folder so there is no point in creating another one in any of the modules added to it. The technical solutions are:
* move all the assets from the modules to the main application. Disadvantage: clutter!
* from the main application symlink to all modules. Tempting? Tempting!
* Use CDN where possible
* deploy an asset manager. Asset manager?

RWOverdijk/AssetManager is an asset manager especially built for Zf2. What it does is handling all files that would otherwise generate a 404, for example /mymodule/public_html/css/style.css. If this style.css file is not found the asset manager is handed a list of alternative directories in which to search. It determines the content type, add headers and then serves the file as if it originated from the official public directory. The asset manager is added to composer as:

 "require": {
       ...........
        "kriswallsmith/assetic":"*",
        "rwoverdijk/assetmanager":"*",
    ..........     
    },

and it works like a charm. Two disadvantages though:
* a security risk: do not leave any sensitive files in any of the modules public folders
* loading time for a file is poor! May be remedied with caching

In any case, back to the original purpose of this procedure check / challenge: display a periodic table. For the raw data (elements, atomic numbers and the like) we will rely on diniska/chemistry conveniently located at github. It is added as a repository of the type “package”.

 {
            "type": "package",
            "package": {
                "name": "diniska/chemistry",
                "version": "1.0",
                "dist": {
                    "url": "https://github.com/diniska/chemistry/archive/master.zip",
                    "type": "zip"
                }
            }
        }     

Now if we want to access the main file periodicTable.json in the PeriodicalTable (no time for chemical nitpicking here people, move on) directory as an asset define this directory in the asset_manager array of the module configuration as:

 'asset_manager' => array(
        'resolver_configs' => array(
            'prioritized_paths' => array(
                array(
                    "path" => __DIR__ . '/../public_html',
                    "priority" => 100
                ),
                array(
                    "path" => __DIR__ . '/../../../diniska/chemistry/PeriodicalTable',
                    "priority" => 50
                )
            ),
        ),
    ),

Back to the periodic table then. The rendering of the page will be left to Angular. Angularjs is a javascript framework library designed for creating single-page web applications. Additional tool: the CSS3 addition called Flexbox. In terms of assets we then have to deal with the angular javascript files and local .js and .css files. In this demo angular is loaded via CDN:



 <script src="https://code.angularjs.org/1.4.2/angular.min.js"></script>
        <script src="https://code.angularjs.org/1.4.2/angular-route.min.js"></script>
        <script src="https://code.angularjs.org/1.4.2/angular-sanitize.min.js"></script>      

The other files are loaded as if they were present in the actual public_html directory:


$viewModel = new ViewModel;
$renderer = $this->serviceLocator->get('Zend\View\Renderer\RendererInterface');    
$renderer->headScript()->appendFile('/js/periodic.js');
$renderer->headLink()->appendStylesheet('/css/periodic.css');
$viewModel->setTemplate('chemical/index/index.phtml');
return $viewModel;

As for the json file, in the Angular code it can simply be stated:


 chemicalApp.factory('TableData', function($http) {
    return {
        periodicData: function(callback) {
            $http.get('periodicTable.json').success(callback);
        }
    };
});

Periodic table here:
periodic table

and here. Big advantage: next time a change is made to the periodic table 🙂 the website can be automatically updated from Github.

Complete code here.

Advertisements