lure

a subset of AngularJS functionality re-packaged as a CommonJS compatible library.

npm install lure
60 downloads in the last week
253 downloads in the last month

lure

a subset of AngularJS functionality re-packaged as a CommonJS compatible library.

Why?

I have mixed feelings about AngularJS:

PROS:

  • models are plain old javascript objects - No proxy classes to worry about (i.e., no need for model.get/set.) They can also be arbitrarily deep, so you dont need to treat collections separately from models.
  • 2 way view/model data binding - the model (scope) is the single source of truth, which means less boilerplate to write
  • templating is HTML compliant - unlike most of the templating languages out there, angularJS syntax is valid HTML markup.

CONS:

  • Over-engineered - many people struggle with Angular's numerous design patterns, especially modules and dependency injection.
  • trying to do too much - It's trying to reinvent too many wheels: form validation, pushstate, etc
  • bad philosophy - I agree that HTML is not perfectly suited to building dynamic apps, but to introduce so many abstractions and a big heavy framework isn't the solution.
  • overloads the $ operator - angular deprecates jquery in most angular apps, but I still think it was a really bad choice to use the $ symbol. It's so heavily associated with jQuery at this point.

This library provides a very limited set of capabilities:

  • clean templates - no weird <% %> syntax, just semantic HTML
  • POJO data models - no ugly proxies for your models or struggling with nested data
  • simple view/model data binding - less boilerplate than writing Backbone

Usage

Compiling a template requires an html template (sample.html):

<ul>
  <li ng-repeat="name in names">
    Hello {{name}}!
  </li>
</ul>
<button ng-show="names.length > 0" ng-click="unshift()">unshift</button>

You also need to specify a controller, which binds a scope between the html and the data model:

var mycontroller = function(scope) {
  scope.names = [ 'Ken', 'Kendra', 'Mike' ];
  scope.unshift = function(){
      scope.names.splice(0,1);
  };
};

You may also watch expressions on the scope, and handle changes:

scope.addressChangeCount = 0;
scope.$watch('user.address.city', function (newVal, oldVal) {
  scope.addressChangeCount++;
});

Here's how you create the dom:

var lure = require('lure');
var fs = require('fs');
var template = fs.readFileSync(__dirname + '/sample.html');

result = lure.compile(mycontroller, template);
$(document.body).append(result.dom);

lure.compile returns an object with the following attributes:

  • dom the actual DOM element that has been constructed from the template. It has not been added to the window document. You can call compile with an optional scope variable, to share scopes between compiled views. lure.compile(mycontroller, template, scope)
  • scope reference to the scope that was created. You can use this to manually invoke scope.$apply() to force the model to detect any changes you may have caused.

What Features from Angular are Supported?

This library is a subset of Angular's capabilities. Listed below are all the supported features.

Expressions

You can use standard angular expressions in all of the normal ways:

in HTML tags:

<p> Hello {{name}} !</p>

in non-ng- attributes:

<li data-custom="{{name}}"> item x</li>

You can also use expressions directly in ng- attributes without the braces:

<div ng-show="books.count > 10"> … </div>

NOT supported: you cannot yet put templated code into the index document. It has to loaded from a template to work properly.

Directives

ng-checked

see angular's docs: http://docs.angularjs.org/api/ng.directive:ngChecked

ng-selected

see angular's docs: http://docs.angularjs.org/api/ng.directive:ngSelected

ng-click

see angular's docs: http://docs.angularjs.org/api/ng.directive:ngClick

ng-disabled

dynamically set if a field is disabled

<input type="text" name="email-confirmation" ng-disabled="signupMode != 'email'">

if the expression in ng-disabled evaluates to true the field is marked as disabled, otherwise it is enabled.

ng-model

see angular's docs: http://docs.angularjs.org/api/ng.directive:ngModel

ng-required

dynamically set if a field is required

<input type="text" name="email" ng-required="signupMode == 'email'">

if the expression in ng-required evaluates to true the field is marked as required, otherwise it is optional.

ng-submit

allows you to handle form submission events

<form ng-submit="submit()">
 ...
 <input type="submit"/>
</form>

if the expression in ng-submit evaluates to true the form is submitted, otherwise it is prevented.

ng-show

see angular's docs for full details: http://docs.angularjs.org/api/ng.directive:ngShow

ng-repeat

see angular's docs for full details: http://docs.angularjs.org/api/ng.directive:ngRepeat

NOT supported: ng-repeat-start and ng-repeat-end

Todo

npm loves you