-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for the Blaze rendering engine. Also added a more flexible... #26
base: master
Are you sure you want to change the base?
Changes from 1 commit
96df0a2
2263b2d
52b8f31
c89c656
b73d4f0
c656d8f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ ngMeteor | |
- [Creating and inserting template views](https://github.com/loneleeandroo/ngMeteor#creating-and-inserting-template-views) | ||
- [Routing](https://github.com/loneleeandroo/ngMeteor#routing) | ||
- [Module Injection](https://github.com/loneleeandroo/ngMeteor#module-injection) | ||
- [Flexible module bootstrapping](https://github.com/loneleeandroo/ngMeteor#flexistrap) | ||
|
||
### New Data-Binding to avoid conflict | ||
To prevent conflicts with Handlebars, ngMeteor has changed the default AngularJS data bindings from <code>{{foo}}</code> to <code>[[foo]]</code>. For example: | ||
|
@@ -165,14 +166,12 @@ You can render this template using handlebars as you would for any other Meteor | |
|
||
{{> foo}} | ||
|
||
Templates will also be added to the $templateCache of the ngMeteor angular module. To invoke the template in AngularJS you could use ng-view and specify the template in the $templateCache when defining your routes using the $routeProvider or your could use the ng-template directive to render your template like this: | ||
Meteor templates can also be rendered in your Angular views using the ng-template directive like this: | ||
|
||
<ANY ng-template="foo"></ANY> | ||
|
||
<!--Add the ng-controller attribute if you want to load a controller at the same time.--> | ||
<ANY ng-template="foo" ng-controller="fooCtrl"></ANY> | ||
|
||
Templates with names starting with an underscore, for example "_foo", will not be put into the $templateCache, so you will not be able to access those templates using ng-template, ng-include or ng-view. | ||
|
||
### Routing | ||
The [ngRoute](http://docs.angularjs.org/api/ngRoute) module developed by the AngularJS team is included in ngMeteor, which will satisfy those with simple routing needs. For example, if you want to call a template called 'foo' and a controller called 'TodoCtrl' when someone lands on your home page you would define your route like this: | ||
|
@@ -212,10 +211,38 @@ Using this method, additional functionality has been provided to ngMeteor in the | |
|
||
Feel free to make ngMeteor module smart packages, and please contact [loneleeandroo](https://github.com/loneleeandroo) if you would like your package to be listed here as well. | ||
|
||
### Flexible module bootstrapping (flexistrap) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added doc for the fleximodel way of bootstraping angular modules into the dom. This allows multiple modules to be bootstrapped on the same page. |
||
|
||
By default, the ngMeteor angular module is bootstrapped into the top level document on all routes. Since modules cannot be nested in angular, should you want to have parts of your DOM controlled by different modules you can do so using a flexible bootstrapping mechanism called flexistrap which is built in to the ngMeteor package. To use this mechanism you call ngMeteor.addFlexistrap() and provide a jQuery-like selector and an angular module name (or array of module names) as parameters. Fleximodel will then instruct angular to bootstrap the modules with the name (or names, if you provided an array of names) into the DOM elements matching the provided selector. | ||
|
||
Optionally, you can provide a path string (or array of path strings) as the 3rd parameter to addFlexistrap. This will apply your modules to the selected DOM elements only when the path(s) identified by the provided strings are being rendered. You can provide a value of '*' to apply your flexistrap configuration to all paths (this is the default behavior if this parameter is not provided). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed typeo ... 'infront' became 'in front' in the third line. |
||
|
||
Optionally, you can provide a boolean as the 4th parameter. If this value is true, the configuration you provide will replace any existing flexistrap configuration for the given path(s) and selector. If False, it will ONLY update EXISTING configurations. If not supplied or null, it will update existing configurations or add new ones if they don't already exist. | ||
|
||
Example: | ||
|
||
Define two new modules: 'myModule' and 'yourModule': | ||
|
||
myCoolModule = angular.module('myModule',[]); | ||
yourCoolModule = angular.module('yourModule',[]); | ||
|
||
|
||
Remove existing (default) bootstrapping of ngMeteor on the toplevel document: | ||
|
||
ngMeteor.removeFlexistrap(); // removes all existing flexistrap configurations for all paths and selectors. | ||
|
||
Bootstrap div with id 'xxx' with new module named 'myModule' | ||
|
||
ngMeteor.addFlexistrap('#xxx', 'myModule') | ||
|
||
Bootstrap div with id 'yyy' with both the new module 'yourModule' and the original 'ngMeteor' module: | ||
|
||
ngMeteor.addFlexistrap('#yyy', ['yourModule', 'ngMeteor']) | ||
|
||
|
||
<!--- | ||
### Dynamic routing | ||
Routes will automaticlly be created based on a template's name, however, you can override the dynamic routes by manually assigning a route using $routeProvider. The route will load that template and conditionally load a controller with the same name if it exists. You can prevent a template from creating a route by adding a "_" infront of the template name. Based on the URL, this is how you should name your templates: | ||
Routes will automaticlly be created based on a template's name, however, you can override the dynamic routes by manually assigning a route using $routeProvider. The route will load that template and conditionally load a controller with the same name if it exists. You can prevent a template from creating a route by adding a "_" in front of the template name. Based on the URL, this is how you should name your templates: | ||
|
||
| URL | Template / Controller name | $routeParams | | ||
| :-------------------------------- | :----------------------------- | :----------- | | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,14 @@ | ||
var ngMeteorTemplate = angular.module('ngMeteor.template', []); | ||
|
||
ngMeteorTemplate.run(['$templateCache', | ||
function($templateCache) { | ||
angular.forEach(Template, function(template, name){ | ||
if(name.charAt(0) != "_"){ | ||
var templateString = HTML.toHTML(template.render()); | ||
$templateCache.put(name, templateString); | ||
} | ||
}); | ||
} | ||
]); | ||
|
||
ngMeteorTemplate.directive('ngTemplate', ['$templateCache', '$compile', | ||
function($templateCache, $compile) { | ||
ngMeteorTemplate.directive('ngTemplate', ['$compile', | ||
function($compile) { | ||
return { | ||
restrict: 'AE', | ||
scope: true, | ||
link: function(scope, element, attributes) { | ||
var name = attributes.ngTemplate || attributes.name, | ||
template = $templateCache.get(name); | ||
if(angular.isDefined(template)){ | ||
element.html(template); | ||
var name = attributes.ngTemplate || attributes.name | ||
if(name && Template[name]){ | ||
element.html(ngMeteor.renderTemplateInContext(name, scope)); | ||
element.replaceWith($compile(element.html())(scope)); | ||
} else{ | ||
console.error("ngMeteor: There is no template with the name '" + attributes.ngTemplate + "'"); | ||
|
@@ -30,22 +18,40 @@ ngMeteorTemplate.directive('ngTemplate', ['$templateCache', '$compile', | |
} | ||
]); | ||
|
||
// Re-compiles template when rendering with Iron-Router | ||
// Configure Angular to automatically re-compile the template when rendering with Iron-Router | ||
angular.element(document).ready(function() { | ||
|
||
// Apply the default flexistrap configuration (to match the old behaviour of the module pre-flexistrap | ||
ngMeteor.addFlexistrap(document, 'ngMeteor', '*', false); | ||
|
||
if(Package['iron-router']){ | ||
var oldRun = Router.run; | ||
Router.run = function() { | ||
var runResult = oldRun.apply(this, arguments); | ||
key = this._currentController.template | ||
var oldRendered = Template[key].rendered; | ||
Template[key].rendered = function(){ | ||
angular.element(document).injector().invoke(['$compile', '$document', '$rootScope', function($compile, $document, $rootScope){ | ||
$compile($document)($rootScope); | ||
$rootScope.$digest(); | ||
oldRendered.apply(this, arguments); | ||
}]); | ||
Template[key].rendered = oldRendered; | ||
} | ||
var templateKey = this._currentController.route.options.template ? this._currentController.route.options.template : this._currentController.route.name; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re-render now forces bootstrapping (if not already bootstrapped) and element replacement happens, substituting the result of compiling the element for the element itself. I think this will work for the general case. It worked in my use case. |
||
var oldRendered = Template[templateKey].rendered; | ||
Template[templateKey].rendered = function(){ | ||
|
||
// Apply flexistrap if one has been configured. | ||
var map = ngMeteor.getFlexistrap(templateKey); | ||
$.each( map, function( key, value ) { | ||
var eleArray = $(key); | ||
_.each(eleArray, function(element){ | ||
var moduleList = _.clone(value); | ||
if (!element.bootstrapped && !angular.element(element).injector()){ | ||
angular.bootstrap(element, moduleList); | ||
element.bootstrapped = true; | ||
}else { | ||
angular.element(element).injector().invoke(['$compile', '$document', '$rootScope', function ($compile, $document, $rootScope) { | ||
element.replaceWith($compile(element)($rootScope)); | ||
$rootScope.$digest(); | ||
}]); | ||
} | ||
}); | ||
}); | ||
oldRendered.apply(this, arguments); | ||
Template[templateKey].rendered = oldRendered; | ||
}; | ||
return runResult; | ||
}; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
// Define ngMeteor and its dependencies | ||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clean up comments and removed commented code. |
||
* Define the ngMeteor angular module and its dependencies | ||
*/ | ||
ngMeteor = angular.module('ngMeteor', [ | ||
'ngMeteor.collections', | ||
'ngMeteor.template', | ||
|
@@ -11,17 +13,95 @@ ngMeteor = angular.module('ngMeteor', [ | |
'ngSanitize' | ||
]); | ||
|
||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add flexistrap mechanism and methods. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Formatting change (indentation) |
||
* Define the 'holder' for flexistrap (flexible bootstrap) configurations. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Formatting change |
||
* The intent is to have this keyed by the 'path' (in case you have multiple routes) with values being another hash object | ||
* with keys being jQuery-like selectors and values being arrays of module names to be bootstrapped into elements matching | ||
* those selectors. | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove default bootstrapping. Replaced by new flexistrap bootstrap mechanism. |
||
ngMeteor.flexistrapRegister = {}; | ||
|
||
/** | ||
* Remove a flexistrap configuration. | ||
* @param selector: JQuery-style selector to select the DOM element(s) to which the flexistrap operation will apply. If not supplied, it defaults to removing all configurations for the specified path(s). | ||
* @param angularModuleNameOrArray: The name (or array of names) of the module(s) to be added to the flexistrop configuration for the selected element(s). If not provided, it will | ||
* @param pathOrArray: The path string (or array of path strings) for which, when rendered, we wish to have a flexible bootstrap configuration (flexistrap) applied. | ||
* If not provided, it applies to all paths specifications including '*'. | ||
* If you only want it to affect the '*' flexistrap configuration, ensure you provide '*' as the value for this parameter. | ||
* @returns: ngMeteor to allow easy method chaining. | ||
*/ | ||
ngMeteor.removeFlexistrap = function(selector, angularModuleNameOrArray, pathOrArray){ | ||
return ngMeteor.addFlexistrap(selector, null, pathOrArray, true); | ||
}; | ||
|
||
/** | ||
* Add or update a flexistrap configuration. | ||
* If replaceFlag is true, replace any existing flexistrap configuration for the provided <selector>. | ||
* If false, only insert if the configuration doesn't already exist, otherwise ignore. | ||
* If null, add to existing or create new. | ||
* @param selector: JQuery-style selector to select the DOM element(s) to which the flexistrap operation will apply. If null, it defaults to an empty array. | ||
* @param angularModuleNameOrArray: The name (or array of names) of the module(s) to be added to the flexistrop configuration for the selected element(s). | ||
* If null, it defaults to an empty array. | ||
* @param pathOrArray: (optional) The url (or fragment) which, when rendered, we wish to have this flexible bootstrap configuration applied. | ||
* Note that a value of '*' will add the provided configuration to all path configurations (as a merge function at run time). | ||
* If null, it will default to '*'. | ||
* @param replaceFlag: (optional) If true, replace existing flexistrap configuration. If false, only add it if one has | ||
* not yet been registered for this selector and path. If null or not supplied, add the provided module name or names | ||
* to the existing flexistrap configuration or create a new one to bootstrap with the provided module name(s). | ||
* @returns: ngMeteor to allow easy method chaining. | ||
*/ | ||
ngMeteor.addFlexistrap = function(selector, angularModuleNameOrArray, pathOrArray, replaceFlag){ | ||
var moduleNames = angularModuleNameOrArray ? (_.isArray(angularModuleNameOrArray) ? angularModuleNameOrArray : [angularModuleNameOrArray]) : []; | ||
var paths = pathOrArray ? (_.isArray(pathOrArray) ? pathOrArray : [pathOrArray]) : ['*']; | ||
|
||
_.each(paths, function(ele){ | ||
var pathEntry = this[ele] ? this[ele] : null; | ||
if(typeof replaceFlag === 'undefined' || replaceFlag === null){ | ||
if(typeof pathEntry === 'undefined' || pathEntry === null){ | ||
pathEntry = {}; | ||
} | ||
}else{ | ||
pathEntry = {}; | ||
if(!replaceFlag){ | ||
return; | ||
} | ||
} | ||
var moduleArray = selector ? (pathEntry[selector] ? pathEntry[selector] : []) : []; | ||
moduleArray = _.union(moduleArray, moduleNames); | ||
pathEntry[selector] = moduleArray; | ||
this[ele] = pathEntry; | ||
return ngMeteor; | ||
}, ngMeteor.flexistrapRegister); | ||
}; | ||
|
||
/** | ||
* Retrieve the flexible bootstrap configuration map for the provided path. | ||
* @param path: The routing path being rendered. | ||
* @returns A map object with keys being jQuery-like selector strings and values being arrays of module names which | ||
* will be bootstrapped by angular into the elements obtained from the provided selector. | ||
*/ | ||
ngMeteor.getFlexistrap = function(path){ | ||
var flexistrap = path ? ngMeteor.flexistrapRegister[path] : null; | ||
flexistrap = flexistrap ? flexistrap : {}; | ||
var all = ngMeteor.flexistrapRegister['*'] ? ngMeteor.flexistrapRegister['*'] : {}; | ||
return _.extend(flexistrap, all); | ||
}; | ||
|
||
/** Utility method for use with the Blaze rendering engine. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A replacement for the Template.render function that we used to use. This works fairly well, actually. Watching for a more permanent solution in Meteor 1.0 but this should work and should continue to work even after 1.0. |
||
* Render the named template as HTML using the 'context' param as the source for variable substitution. | ||
*/ | ||
ngMeteor.renderTemplateInContext = function(templateOrName, context) { | ||
var template = (typeof templateOrName === 'string') ? Template[templateOrName] : templateOrName; | ||
var div = document.createElement('div'); | ||
var component = UI.renderWithData(template, context); | ||
UI.insert(component, div); | ||
return div.innerHTML; | ||
}; | ||
|
||
// Change the data-bindings from {{foo}} to [[foo]] | ||
ngMeteor.config(['$interpolateProvider', | ||
function ($interpolateProvider) { | ||
$interpolateProvider.startSymbol('[['); | ||
$interpolateProvider.endSymbol(']]'); | ||
} | ||
function ($interpolateProvider) { | ||
$interpolateProvider.startSymbol('[['); | ||
$interpolateProvider.endSymbol(']]'); | ||
} | ||
]); | ||
|
||
// Manual initilisation of ngMeteor | ||
angular.element(document).ready(function() { | ||
if (!angular.element(document).injector()){ | ||
angular.bootstrap(document, ['ngMeteor']); | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,33 @@ | ||
Package.describe({ | ||
summary: "The simplest no-conflict way to use AngularJS with Meteor, Meteorite and Atmosphere Smart Packages." | ||
summary: "The simplest, no-conflict way to use AngularJS with Meteor, Meteorite and Atmosphere Smart Packages." | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typeo fix |
||
}); | ||
|
||
Package.on_use(function (api) { | ||
api.use('templating', 'client'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add soft requirement on the templating package (references to global Template) |
||
api.use('underscore', 'client'); | ||
|
||
// Exports the ngMeteor package scope | ||
api.export('ngMeteor', 'client'); | ||
|
||
// Files to load in Client only. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. formatting. remove commented out code. |
||
api.add_files([ | ||
// Lib Files | ||
'lib/angular.js', | ||
'lib/angular-csp.css', | ||
'lib/angular-animate.js', | ||
'lib/angular-cookies.js', | ||
//'lib/angular-mocks.js', | ||
'lib/angular-resource.js', | ||
'lib/angular-route.js', | ||
//'lib/angular-scenario.js', | ||
'lib/angular-sanitize.js', | ||
'lib/angular-touch.js', | ||
'lib/angular-hash-key-copier.js', | ||
'lib/angular.js', | ||
'lib/angular-csp.css', | ||
'lib/angular-animate.js', | ||
'lib/angular-cookies.js', | ||
'lib/angular-resource.js', | ||
'lib/angular-route.js', | ||
'lib/angular-sanitize.js', | ||
'lib/angular-touch.js', | ||
'lib/angular-hash-key-copier.js', | ||
|
||
// Module Files | ||
'modules/ngMeteor-collections.js', | ||
'modules/ngMeteor-template.js', | ||
'modules/ngMeteor-collections.js', | ||
'modules/ngMeteor-template.js', | ||
|
||
// Finally load ngMeteor File | ||
'ngMeteor.js' | ||
'ngMeteor.js' | ||
|
||
], 'client'); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer need this since users only will render templates they identify with the ng-template directive. Templates are no longer pre-rendered and cached. This provides for rendering templates via meteor spacebars first and then rendering that output using angular's compile/link functionality.
Pre-rendering with render() and then caching the result was not very flexible in any case if the template was not 'static'. If you needed to generate the template contents, for example, using meteor's rendering engine, and then feed that result into the angular compile/link processor, then using the pre-rendered HTML from the templateCache would not have been helpful.