Tag

javascript

Browsing

I recently ran into an issue where I have a fairly nested directive and within the directive itself has an input that requires a decorator type directive such as for validation. As far as the title of the blog post, I figure that with each Angular 1.x release (2 in the near future) it’s probably best to tag these posts accordingly since each version introduces new syntax, etc and might not work if you’re still on the earlier version.

The problem

I’ll be using TypeScript for my example. For simplification, let’s say that you have a directive that validates an input. The directive is called, "validateInputInner" and we would like to use this in another directive.

return <ng.IDirective>{
    restrict: 'A',
    require: 'ngModel',
    link: link
};

function link($scope, $element, $attrs, ctrl) {
    var validateInput = (inputValue)=> {

        // some validation logic goes here...
        ctrl.$setValidity('validateInputInner', isValid);

        return inputValue;
    };

    ctrl.$parsers.unshift(validateInput);
    ctrl.$formatters.push(validateInput);

    // Observe attribute change
    attrs.$observe('validateInputInner', (comparisonModel)=> {
        return validateInput(ctrl.$viewValue);
    });
}

From a normal usage, the directive can be simply be used as:

<input type="text" validate-input-inner="{{vm.someModel}}" />

It gets a little more complex when you embed the same directive within another directive such as.

<test-component data-ng-model="vm.someModel" validate-input-inner="vm.secondaryModel"></test-component>

The second directive called testComponent will be using the previous directive as part of the component’s validation. The code for the testComponent is below. Please note the placement of the validate-input-inner.

Solution

We would like to use the testComponent directive as a wrapper component that exposes a scope property that feeds into the validation directive. We also could have re-used the existing model but for this example, we’ll assume that the validate-input-inner needs to validate another model in addition to the model.

testComponent.$inject = ['$compile'];
function testComponent(
    $compile: ng.ICompileService): ng.IDirective {
    return <ng.IDirective>{
        restrict: 'E',
        replace: true,
        require: 'ngModel',
        scope: {
            model: '=ngModel',
            validateInputInner: '=?',
        },
        link: link,
        template: `<div>
            <input type="text" class="form-control" 
            data-ng-model="model" validate-input-inner="{{validateInputInner}}"  /></div>`
    };
    // more code...

You might assume that this will work "as is" since the testComponent is using the same approach as it was by itself, and the scope property gets funneled down the directive itself.

Surprisingly enough, it doesn’t. The validate-input-inner works by itself but it but becomes unaware when inside a template based directive. The validate-input-inner could have been re-written another way perhaps to use $watch as opposed to $observe but given the scenario that we’re in, one way that I found to make it work is to use a $watch insite the testComponent itself.

We will need to inject $compile which is an Angular way to dynamically compile a string into a usable DOM element. In our case, the input element is nested within a div which is why need a reference to it using jqLite.

function link($scope, $element, $attrs) {
    var $input = $element.children('input');

    $scope.$watch('validateInputInner',(val) => {
        $input.attr('validate-input-inner', val);
        $compile($input)($scope);
    });
}

I added $scope.$watch and call $compile to refresh the validateInputInner‘s state. Please keep in mind that this operation is DOM intensive and is not always the best solution. This is one way out of (I’m sure) hundreds of ways of solving this. I’ll be exploring more ways to solve this and expand on this scenario in the future.

In the mean time, if you have suggestions or other ways to solve this, please feel free to comment or contact me.

I’ve been interested in Node.JS for quite some time now but I haven’t really realized its potential or find a use case. The
extent of my experience was basically creating a quick Express.JS app and see it run in the browser. No formal development whatsoever.
I have come across Sails.JS in the past but that’s when Node was just in its early stages, or at least before I was interested
in the platform. Sails.js coincides with or sits on top of Express.JS using the same MVC pattern as Rails.

I watched the introduction video again for Sails.JS today and was amazed at how powerful it is. The ease at creating a Model, JSON API
end point and by default and Socket IO are the main selling points for me. At the moment, there’s not a whole lot of examples in the
web so I’m going to share a few things that I’ve learned regarding the framework.

MVC

According to the Sails.JS documentation, the implementation is very similar to Rails and if you understand how MVC works, it should be easy
to decipher the code in their documentation. The way queries are made is functional in nature which I like but the best part of all these is that
it’s all in JavaScript.

After doing an install via NPM, I began to do some research on what the deployment strategy can be. Since I’m still new to Git and Heroku, I
picked up a few commands that are integral to the Sails.JS and Heroku deployment workflow (setting up Git in any case).

Git commands

Set global GitHub config.

$ git config --global github.user your_user_name

Create new Git repo and commit.

$ cd project_name && git init && git add . && git commit

Get the remote projects.

$ git remote -v

Push latest commit to Heroku.

$ git push heroku master

Heroku commands

Create a project (within the project directory).

$ heroku create or $ heroku create app_name`

Authenticate with Heroku server.

$ heroku login

Add your public key to Heroku.

$ heroku keys:add .ssh/id_rsa.pub

Add key automatically.

$ heroku keys:add

Get all projects in Heroku.

$ heroku list

Open the Heroku app in the browser.

$ heroku open

Log.

$ heroku log

Heroku issues on deployment

The two main issues that I’ve encountered while deploying are highlighted below. The application immediately throws a generic error
in which I have to use the command heroku logs to inspect the events.

H14 No web processes running. This is the error that shows when the web dynos is set to 0. Fixing it is a matter of scaling it
to 1 according to the Error Codes page.

$ heroku ps:scale web=1

Immediately after issuing that command, I was faced with another issue in which it complains about a non-existent web type.

No such type as web. This issue took me a while to figure out and after doing some research, I resolved it by adding a "Procfile"
to the root of my Sails JS application with the following code.

web: node app.js

Changing the /config/application.js to a port that Heroku understands (1337 being the default).

port: process.env.PORT || 1337,

After making those changes and issuing a git push heroku master, I had to issue the heroku ps:scale web=1 once again after the changes
has been formally deployed to Heroku.

Pushing to GitHub and Heroku repo simultaneously

Another helpful strategy is instead of issuing a separate git push master to Heroku and
Github is to push it all at once. The .git/config can be modified to do this.

[remote "heroku"]
    url = git@heroku.com:<heroku_repo>.git
    fetch = +refs/heads/*:refs/remotes/heroku/*

[remote "github"]
    url = git@github.com:<github_username>/<github_project>.git
    fetch = +refs/heads/*:refs/remotes/github/*

[remote "all"]
    url = git@github.com:<github_username>/<github_project>.git
    url = git@heroku.com:<heroku_repo>.git
    fetch = +refs/heads/*:refs/remotes/origin/*

Conclusion

After the SSH keys has been added to Heroku and Github (see GitHub and
Heroku documentations on generating a new key), everything is working great.
I also realized that you only need a single key for both accounts.

Many hours after setting up the source control environment later is when learning Sails JS/Node and fun begins.

Today, I was looking for a way to automatically save any emails that are labeled “Articles” to [Evernote][1] on my [Gmail][3] account.
I have filters to specifically target the email addresses that I’ve specified and automatically label them with “Articles”. This makes it
convenient for me so everything is in one place when I have time to read them. I’ve been using [Evernote][1] lately and happen to like
how it takes a snapshot of articles that I want to be saved and read it (even if the original source goes away).

There’s [Zapier][4] and [IFTTT][5] which I use for automating my Instagram, and other online services. I realized soon that
the emails being forwarded are in plain text which makes the articles unreadable and useless.

So the hunt continues for that service that will automate the archiving of articles from [Gmail][3] to [Evernote][1].
While searching, I encountered this [article][2] in which he use [Google Drive][7] to create [Google App scripts][6] to interact
with [Gmail][3]. I’ve seen several people used the [script][6] before but never had an opportunity to play around with it until now.
I decided to give it a shot and seems to be a perfect opportunity to play with something new ;-).
It basically uses JavaScript to call [Gmail classes][6] and the [Google script][8] interface allows you to debug and build projects
so it can be automated on a scheduled basis.

The script below was taken from this [article][2] and modifying a few parameters should work out of the box. The “Misc/Articles” is
a nested label that I use to tag incoming emails from specific sources identified by a filter that I created. The “special_evernote_email”
is a special email that [Evernote][1] assigned to you for convenience so you can send an email as a note to their service. You can find
this in your [Evernote settings][1] page. The last two strings are the hash tags that I want to use to identify those items in [Evernote][1].

The ‘forwardEmails’ function is the entry point on the script which then calls the ‘forwardThreads’ function passing in the custom parameters.
The only issue that I’ve had was regarding the label. The label that is provided has to exist, otherwise, ‘labels.getThreads()’ will receive
a null which terminates the execution of the script.

#### Steps
1. Go to your [Google Drive][7] and Create>Script (if Script is not available, you have to choose “connect more apps”).
2. This will open up the [Google Script][8] page which then you’ll create a new “Blank Project”.
3. Paste the code below and pick “forwardEmails” as the function to execute, then hit run to test that it works properly.
4. Click on the clock icon to create a trigger to schedule the function to run at specific times (hourly, etc).

#### The script

“`javascript
function forwardEmails() {
forwardThreads(“Misc/Articles”, “special_evernote_email@m.evernote.com”, “@Articles/Subscriptions #archived #articles”);
}

function forwardThreads(label, addr, subjSuffix) {
var maxSubjLength = 250;
var applylabel = GmailApp.getUserLabelByName(“EN_Archive”);

// Send individual and threaded emails.
var msgs, msg, i, j, subject, options, labels, page;
labels = GmailApp.getUserLabelByName(label);
var threads = labels.getThreads();
for (i=0; i < threads.length; i++) { msgs = threads[i].getMessages(); for (j=0; j < msgs.length; j++) { msg = msgs[j]; subject = msg.getSubject(); if (subject.length + subjSuffix.length > maxSubjLength) {
subject = subject.substring(0, maxSubjLength – subjSuffix.length);
}

options = { htmlBody: msg.getBody(), attachments : msg.getAttachments() };

GmailApp.sendEmail(addr, subject +” “+ subjSuffix, msg.getBody(), options);
}
}

while(!page || page.length == 100) {
/* Get the threads anywhere from 0 to 100. */
page = labels.getThreads(0, 100);

//pause to keep rates to gmail down (Goog apps errors)
Utilities.sleep(1000);

// Apply new label; move the thread out of other label
applylabel.addToThreads(page);
labels.removeFromThreads(page);
}
}
“`

[1]: https://evernote.com/
[2]: http://www.gavinadams.org/blog/2012/08/20/archiving-gmail-to-evernote/
[3]: http://gmail.com
[4]: https://zapier.com/
[5]: https://ifttt.com
[6]: https://developers.google.com/apps-script/reference/gmail/
[7]: https://drive.google.com
[8]: https://script.google.com

I did a trial for [WebStorm 6][webstorm] a week and a half ago and immediately fell in love with it after playing with it for a couple days.
I purchased a license for it right away during the trial period. The main feature that sold me to the IDE was the fact that it has components
and workflow to work with modern JavaScript frameworks such as [jQuery][jQuery], [Modernizr][modernizr], etc. For instance, you can have several
JavaScript frameworks and have it reusable across multiple projects. By setting a library to “global”, it makes it available for
auto completion for all projects (meaning every project will automatically inherit it). Beforehand, I use [Notepad++][nplus] and
[Web Matrix 2][webmatrix] as an alternative to [Visual Studio][vs] for fast web development debugging and code writing. I never really cared much
about code completion (slows me down sometimes) but it helps for accessing third-party libraries. [WebStorm][webstorm] is a very light IDE but
yet still powerful — not to mention, it also supports multiple version control repositories such as Git, Mercurial, among many others.

[WebStorm 6][webstorm] has a little bit of [Resharper][resharper] flavor on it having used [Visual Studio][vs] for a few years now.
In addition, it’s also packed with many features to target modern web development workflows such as testing, support for
dynamic languages such as [LESS][less], [SASS][sass], [CoffeeScript][cs], [TypeScript][ts], etc. Similar to [Visual Studio][vs], there’s
predefined project templates when creating new projects (HTML5 boilerplates) as a starting point which generates boiler plate code that uses
HTML5 boilerplates project. With this idea in mind, it inspired me to look at [Yeoman][yo] once again and make it part of my web development
workflow.

[Yeoman][yo] is basically a scaffolding tool that works with [Grunt][grunt] and [Bower][bower] to complete a modern web development
work flow (ie brings in configuration to make your application work nicely with [Grunt][grunt] and [Bower][bower]). [Bower][bower] is
a dependency management tool similar to [Node Package Management or NPM][npm] which automatically pulls the library as well as its dependencies.

[Grunt][grunt] on the other hand is a test runner, build tool (generates a deployment folder which contains a production ready version of your
application), and a whole lot of automation types of tasks. [Grunt][grunt] and [Bower][bower] are powerful tools in their own rights and does
a lot more things that I mentioned above but [Yeoman][yo] sorta brings them together. Playing with these three tools for a few days,
I’ve come up with steps/commands to accomplish certain steps. I’ll provide a list of commands that I have put together meant as a sticky note
so I can reference them over and over again easily.

As a side note, the commands used are in Windows OS and command line (either the default command line or Node.js command prompt
works good). If you don’t have [NodeJS][node] installed on your system already, you can check out the website and need to have it installed. It will
include [NPM][npm] which is an indispensable tool and is very popular in the open source community.

#### To install the tools:
Install Yeoman.

\> npm install yo -g // The -g attribute installs the component globally

Install Bower.

\> npm install bower -g

Installing Grunt according to their documentation requires a few steps. When working with a new project, you can execute the following
commands.

\> npm uninstall grunt -g // Only if you have Grunt previously installed

\> npm install grunt-cli -g

For existing projects that already has package.json and Gruntfile.json (task configurations, plugins, etc):

\> npm install grunt –save-dev

#### Yeoman commands:
To scaffold a new generic app.

\> yo webapp

To list all the Yeoman generators.

\> npm search yeoman-generator

Once you find a generator that you want to install, you can install it via NPM by

\> npm install -g generator-angular // Angular JS for example.

\> npm install -g generator-backbone generator-backbone-amd // Backbone JS

You can then scaffold a new project using the generator. (You have to do CD to and be at the root of your project directory).

\> yo angular

#### Bower commands:
Bower is similar to NPM where it manages libraries and dependencies as packages that can be installed globally or per project
based.
To install a library such as angular.

\> bower install angular // Gets the latest version

To install a specific version of a library.

\> bower install angular\#1.1 // This will install a specific version

To install from a GitHub repo.

\> bower install git://github.com/components/jquery.git // Installs from GitHub

To update a package.

\> bower update angular

To list all installed packages.

\> bower list

To search the Bower repository for specific packages.

\> bower search [name]

#### Grunt commands:
Grunt can do a lot of things such as starting up a web server for testing, running test, executing tasks, etc.

To perform a project build and compiles a project for deployment (JS minification, CSS minification, etc).

\> grunt –force // The force parameter ignores warning and will continue the build.

To perform a test

\> grunt test

To run a server instance

\> grunt server

The commands above are the most common usage of the [Yeoman][yo], [Bower][bower] and [Grunt][grunt]. There’s a lot
more things that weren’t covered but for starters, this should be a good base line when trying to make these tools
part of your web development work flow.

[node]: http://nodejs.org/
[npm]: https://npmjs.org/
[yo]: http://yeoman.io/
[grunt]: http://gruntjs.com/
[bower]: https://github.com/bower/bower
[modernizr]: http://modernizr.com
[jQuery]: http://www.jquery.com
[webstorm]: http://www.jetbrains.com/webstorm/
[vs]: http://www.microsoft.com/visualstudio/
[resharper]: http://www.jetbrains.com/resharper/
[sass]: http://sass-lang.com/
[less]: http://lesscss.org/
[cs]: http://coffeescript.org/
[ts]: http://www.typescriptlang.org/
[backbone]: http://backbonejs.org/
[underscore]: http://underscorejs.org/
[webmatrix]: http://www.microsoft.com/web/webmatrix/
[nplus]: http://notepad-plus-plus.org/

Most of the code samples that you’ll find regarding bootstrapping Angular JS is to do it declarative such as `html ng-app=””`

You can name your app or leave it blank if you only have 1 app (I find that in most cases, 1 app is enough although you can have multiple controller if needed).
What if you want to get away from the declarative approach and do all the App bootstrapping in JavaScript? I find that the code above works but is not flexible
especially on large-scale applications where you have a “layout” template and you know ahead of time that you’re not going to use Angular JS on every single page.

If you want more flexibility when bootstrapping your Angular JS app, here’s a code sample to accomplish that. Take note though that there’s tons of other ways
to bootstrap an Angular JS app aside what I have here.

“`javascript
window.app = {};

/** Bootstrap on document load and define the document along with optional
modules as I have below.*/
angular.element(document).ready(function () {
// Attach to namespace, bootstrap document, and inject modules.
app.ang = angular.bootstrap(document, [‘ngResource’, ‘ngSanitize’]);

// OR simply, this works similarly.
angular.bootstrap(document, []);
});

/** Define Angular Controller */
app.myController= function ($scope, $resource, $timeout) {
….
};
“`

Hope this helps some lost soul.