Archive for 'AngularJS'

ZIP a Folder in NodeJS

Here is a simple way to archive and pipe a folder in NodeJS.
First, get the fstream and tar modules:
  • npm install fstream
  • npm install tar
Do something like this on your server:
var fstream = require('fstream'),
    tar = require('tar'),
    zlib = require('zlib');

    res.writeHead(200, {
      'Content-Type'        : 'application/octet-stream',
      'Content-Disposition' : 'attachment; filename=myArchive.zip', 
      'Content-Encoding'    : 'gzip'
    });

    var folderWeWantToZip = '/foo/bar';

    /* Read the source directory */
    fstream.Reader({ 'path' : folderWeWantToZip, 'type' : 'Directory' })
        .pipe(tar.Pack())/* Convert the directory to a .tar file */
        .pipe(zlib.Gzip())/* Compress the .tar file */
        .pipe(response); // Write back to the response, or wherever else...
This solution is based on an answer on StackOverflow

The Javascript Echosystem – Slides Available

I’ve recently added a set of slides I have been developing and using to teach courses around building modern web applications. Topics include:
  • World Wide Web Technologies – An introduction to http, browsers, html and css.
  • Javascript – Prototype-based programming language that is dynamic, loosely typed and has first-class functions.
  • Document Object Model – Manipulating the live HTML.
  • JQuery – Library for working with the DOM.
  • RequireJS – JavaScript file and module loader.
  • AngularJS – Application development framework for the browser.
  • HTML5 – Semantic markup, canvas, CSS3 etc…
  • Debugging – Common tools used for debugging web applications.
  • Performance – Best practices for a fast website.
  • Bootstrap – Front-end framework for the web
  • KnockoutJS – Declarative data-binding framework

Please take a look and let me know what you think: http://roubenmeschian.com/tuts/
The source for this project is available on github.

It’s common for developers to want to run angular’s compilation over some piece of html inside a directive. However, if you are not careful, you can easily cause memory leaks.

Here is an example of code that may leave behind unneeded child scopes:
// in your directive's link function, you do something like this
var content = $compile(template)(scope); // compile and link to the current scope
element.append(content); // add to the DOM

// ... the later, we want to update the content of the element ...

var newContent = $compile(template2)(scope);
content.replaceWith(newContent);

// While replaceWith does remove the old html, it does not remove any of the scopes that may have been added the first time we did compile/link on the old template.
This is a better way to do it:
var newScope = scope.$new(); // create a new scope from the current scope
var content = $compile(template)(newScope); // compile and link to the new scope
element.append(content); // add to the DOM

// .. then later, we want to update the content of the element ...

newScope.$destroy(); // destroy the scope and all child scopes
var newScope2 = scope.$new(); // create a new scope
var content2 = $compile(template2)(newScope2); // compile and link
content.replaceWith(content2); // replace the html content with the new content
Also, note that if you want to know when a directive is destroyed to do any kind of additional cleanup, you can add a destroy listener to the element the directive’s link function is called with:
element.on('$destroy', function() {
 .. unhook whatever ..
});

Just remember that you won’t need to unhook jquery events that have been attached on or below the target element, since angular calls .remove() on it, thereby removing all listeners.

Lazy Loading in Angular

AngularJS does not yet have a way to load objects asynchronously, but you can use RequireJS to do it yourself. First, you need to wrap all controllers, factories, etc with AMD modules. They should look something like this:
define([
    // your dependencies
], function () {
    return ["myController", ["$scope", function($scope) {
       $scope.data = { label: "my data" };
    }]];
});
When initializing your application, do something like this:
var compileProvider,
        controllerProvider,
        filterProvider,
        provide;

    // create your application module and store references to the compileProvider, controllerProvider, filterProvider, and provider
    var module = angular.module('myApp', [], function ($compileProvider, $controllerProvider, $filterProvider, $provide) {
        compileProvider = $compileProvider;
        controllerProvider = $controllerProvider;
        filterProvider = $filterProvider;
        provide = $provide;
    });

     var lazyAngular = {
            registerFactoryProvider: function(factory) {
                provide.factory.apply(null, factory);
            },
            registerFilterProvider: function(filter) {
                filterProvider.register.apply(null, filter);
            },
            registerDirective  : function (directive) {
                compileProvider.directive.apply(null, directive);
            },
            registerController : function (controller) {
                controllerProvider.register.apply(null, controller);
            }
        };

    // Now, register a factory you can use to register lazily loaded controllers, directives, filters and factories
    module.factory("lazyAngular", function () {
        return lazyAngular ;
    });
    // Note that you can also reference the lazyAngular object directly, without dependency injection if you wish.
You can now load things asynchronously, for example:
// Make sure that you have lazyAngular in the current context (load it with dependency injection).
// Note that I have also seen developers put the registration methods in a global namespace, to easily reference the registration capability from everywhere without worrying about dependency injection.
// How you reference the lazyAngular object is up to you.
require(["myController"], function(myCtrl) {
    lazyAngular.registerController (myCtrl); // register the lazily loaded controller

   // you can now use this lazy loaded controller
});