├── .gitignore ├── .versions ├── LICENSE ├── README.md ├── layout.coffee ├── package.js ├── root.coffee └── root.html /.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | .idea 3 | -------------------------------------------------------------------------------- /.versions: -------------------------------------------------------------------------------- 1 | babel-compiler@7.3.4 2 | babel-runtime@1.3.0 3 | base64@1.0.11 4 | blaze@2.3.3 5 | blaze-tools@1.0.10 6 | caching-compiler@1.2.1 7 | caching-html-compiler@1.1.3 8 | check@1.3.1 9 | coffeescript@2.4.1 10 | coffeescript-compiler@2.4.1 11 | deps@1.0.12 12 | diff-sequence@1.1.1 13 | dynamic-import@0.5.1 14 | ecmascript@0.12.7 15 | ecmascript-runtime@0.7.0 16 | ecmascript-runtime-client@0.8.0 17 | ecmascript-runtime-server@0.7.1 18 | ejson@1.1.0 19 | fetch@0.1.1 20 | html-tools@1.0.11 21 | htmljs@1.0.11 22 | id-map@1.1.0 23 | inter-process-messaging@0.1.0 24 | jquery@1.11.11 25 | kadira:blaze-layout@2.3.0 26 | meteor@1.9.3 27 | modern-browsers@0.1.4 28 | modules@0.13.0 29 | modules-runtime@0.10.3 30 | mongo-id@1.0.7 31 | observe-sequence@1.0.16 32 | ordered-dict@1.1.0 33 | peerlibrary:assert@0.3.0 34 | peerlibrary:base-component@0.17.1 35 | peerlibrary:blaze-components@0.23.0 36 | peerlibrary:blaze-layout-component@0.3.0 37 | peerlibrary:computed-field@0.10.0 38 | peerlibrary:data-lookup@0.3.0 39 | peerlibrary:reactive-field@0.6.0 40 | promise@0.11.2 41 | random@1.1.0 42 | reactive-dict@1.3.0 43 | reactive-var@1.0.11 44 | spacebars@1.0.15 45 | spacebars-compiler@1.1.3 46 | templating@1.3.2 47 | templating-compiler@1.3.3 48 | templating-runtime@1.3.2 49 | templating-tools@1.1.2 50 | tracker@1.2.0 51 | underscore@1.0.10 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, The PeerLibrary Project 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the PeerLibrary Project nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Blaze Layout Component 2 | ====================== 3 | 4 | A simple [Blaze Component](https://github.com/peerlibrary/meteor-blaze-components) for use with 5 | [Flow Router](https://github.com/kadirahq/flow-router)'s [layout manager](https://github.com/kadirahq/blaze-layout). 6 | 7 | Adding this package to your [Meteor](http://www.meteor.com/) application adds `BlazeLayoutComponent` class 8 | into the global scope. It also configures the root Blaze Component to serve as the root of the components' tree. 9 | 10 | Alternatively, you can also use our [fork of Flow Router](https://github.com/peerlibrary/flow-router), which 11 | adds [ignoring links](https://github.com/peerlibrary/flow-router#ignoring-links) feature to it. 12 | 13 | Client side only. 14 | 15 | Installation 16 | ------------ 17 | 18 | ``` 19 | meteor add peerlibrary:blaze-layout-component 20 | ``` 21 | 22 | Usage 23 | ----- 24 | 25 | Define your layout component: 26 | 27 | ```handlebars 28 | 45 | ``` 46 | 47 | ```javascript 48 | class ColumnsLayoutComponent extends BlazeLayoutComponent { 49 | renderFirst(parentComponent) { 50 | return this._renderRegion('first', parentComponent); 51 | } 52 | 53 | renderSecond(parentComponent) { 54 | return this._renderRegion('second', parentComponent); 55 | } 56 | 57 | renderThird(parentComponent) { 58 | return this._renderRegion('third', parentComponent); 59 | } 60 | } 61 | 62 | ColumnsLayoutComponent.register('ColumnsLayoutComponent'); 63 | ``` 64 | 65 | Then you can define a route using this layout: 66 | 67 | ```javascript 68 | FlowRouter.route('/post/:_id', { 69 | name: 'Post.display' 70 | action: function (params, queryParams) { 71 | BlazeLayout.render('ColumnsLayoutComponent', { 72 | first: 'FirstComponent', 73 | second: 'SecondComponent', 74 | third: 'ThirdComponent' 75 | }); 76 | } 77 | }); 78 | ``` 79 | 80 | Alternatively, you can restrict regions' names to catch possible errors: 81 | 82 | ```javascript 83 | class ColumnsLayoutComponent extends BlazeLayoutComponent { 84 | renderFirst(parentComponent) { 85 | return this._renderRegion(this.constructor.REGIONS.FIRST, parentComponent); 86 | } 87 | 88 | renderSecond(parentComponent) { 89 | return this._renderRegion(this.constructor.REGIONS.SECOND, parentComponent); 90 | } 91 | 92 | renderThird(parentComponent) { 93 | return this._renderRegion(this.constructor.REGIONS.THIRD, parentComponent); 94 | } 95 | } 96 | 97 | ColumnsLayoutComponent.REGIONS = { 98 | FIRST: 'first', 99 | SECOND: 'second', 100 | THIRD: 'third' 101 | }; 102 | 103 | ColumnsLayoutComponent.register('ColumnsLayoutComponent'); 104 | ``` 105 | 106 | A good pattern to access the `_id` parameter from the URL is something like: 107 | 108 | ```javascript 109 | class FirstComponent extends BlazeComponent { 110 | onCreated() { 111 | super.onCreated(); 112 | 113 | this.currentPostId = new ComputedField(() => { 114 | return FlowRouter.getParam('_id'); 115 | }); 116 | 117 | this.autorun((computation) => { 118 | postId = this.currentPostId(); 119 | if (postId) this.subscribe('Comments', postId); 120 | }); 121 | } 122 | 123 | comments() { 124 | return Comments.find({ 125 | 'post._id': this.currentPostId() 126 | }); 127 | } 128 | } 129 | 130 | FirstComponent.register('FirstComponent'); 131 | ``` 132 | -------------------------------------------------------------------------------- /layout.coffee: -------------------------------------------------------------------------------- 1 | class BlazeLayoutComponent extends BlazeComponent 2 | onCreated: -> 3 | super 4 | 5 | @regions = {} 6 | 7 | # If set of regions is restricted, then check them. 8 | if @constructor.REGIONS 9 | @autorun (computation) => 10 | unknownRegions = _.difference _.keys(@data()), _.values(@constructor.REGIONS) 11 | 12 | throw new Error "Unknown layout region(s) requested: #{unknownRegions.join ', '}." if unknownRegions.length 13 | 14 | # To make it easier to use region values in methods and minimize reactivity. 15 | _regionToComponentName: (regionName) -> 16 | if @constructor.REGIONS and regionName not in _.values @constructor.REGIONS 17 | throw new Error "Unknown layout region '#{regionName}'." 18 | 19 | # Computed fields by default use use current view's autorun. Regions might be accessed 20 | # inside render() method, where it is forbidden to use view's autorun. So we temporary 21 | # hide the fact that we are inside a view to make computed field use normal autorun. 22 | Blaze._withCurrentView null, => 23 | # Initialize if we are requesting region for the first time. 24 | @regions[regionName] ?= new ComputedField => 25 | # The data context is mapping between region names and region getters. 26 | @data()?[regionName]?() or null 27 | , 28 | # Referential equality, so that possible component classes are equal. 29 | (a, b) => a is b 30 | 31 | @regions[regionName]() 32 | 33 | _renderRegion: (regionName, parentComponent) -> 34 | return null unless regionName 35 | 36 | componentName = @_regionToComponentName regionName 37 | 38 | return null unless componentName 39 | 40 | if _.isString componentName 41 | component = BlazeComponent.getComponent componentName 42 | else 43 | # Otherwise we assume it is already a component. 44 | component = componentName 45 | 46 | throw new Error "Unknown component '#{componentName}'." unless component 47 | 48 | parentComponent ?= @currentComponent() 49 | 50 | # To force no data context in rendered region component. 51 | new Blaze.Template => 52 | Blaze.With null, => 53 | component.renderComponent parentComponent 54 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'peerlibrary:blaze-layout-component', 3 | summary: "A simple Blaze Component for use with Flow Router's layout manager", 4 | version: '0.3.0', 5 | git: 'https://github.com/peerlibrary/meteor-blaze-layout-component.git' 6 | }); 7 | 8 | Package.onUse(function (api) { 9 | api.versionsFrom('METEOR@1.8.1'); 10 | 11 | // Core dependencies. 12 | api.use([ 13 | 'coffeescript@2.4.1', 14 | 'underscore' 15 | ]); 16 | 17 | // 3rd party dependencies. 18 | api.use([ 19 | 'peerlibrary:blaze-components@0.23.0', 20 | 'kadira:blaze-layout@2.3.0', 21 | 'peerlibrary:computed-field@0.10.0', 22 | 'peerlibrary:assert@0.3.0' 23 | ]); 24 | 25 | api.export('BlazeLayoutComponent'); 26 | 27 | api.addFiles([ 28 | 'layout.coffee' 29 | ]); 30 | 31 | api.addFiles([ 32 | 'root.html', 33 | 'root.coffee' 34 | ], 'client'); 35 | }); 36 | -------------------------------------------------------------------------------- /root.coffee: -------------------------------------------------------------------------------- 1 | class RootComponent extends BlazeComponent 2 | @register 'RootComponent' 3 | 4 | BlazeLayout.setRoot '#__blaze-root' 5 | -------------------------------------------------------------------------------- /root.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | {{> RootComponent}} 7 | 8 | --------------------------------------------------------------------------------