10/28/17

Rxjs - Discovering Subject and Subject Behavior

In frameworks like angular and react we have this behavior that tracks every change of model (a javascript variable which stores state of some ui component) and immediately projects all the model changes to ui.
lets say we want to mimic this behavior without using any framewok.
For example: we have person object in our application that has a boolean "isMale" field (among other fields).

let person = {
  name:"Holden",
  lname:"Colfield",
  isMale:"true"
}

Lets say we need UI to react to change of this "isMale" field, and change checkbox caption accordingly
here is when rxjs can be useful:
One of the options to achieve the desired behavior with rxjs - is to define person object as Behavior Subject

let bSubject = new Rx.BehaviorSubject(person); 

Behavior subject is an observable sequence which makes you able to notify everyone of its subscribers when some change occurs.
Only thing you do is call "next" method of the subject:
(In our app we will trigger change when somebody cliks on the checkbox)

Rx.Observable.fromEvent(checkBox,'change').subscribe(x=> {
   person.isMale = x.target.checked;
   bSubject.next(person);
})

Now our app changes its ui according to changes of observed "person" object...
see running code

10/17/17

Post About Rxjs

What can i say about rxjs?

Rxjs it is a different way of writing the code
For instance, instead of doing this:


document.querySelector('h1').addEventListener('click',(e)=>{
  alert()
}) 

With Rxjs you can write the same thing using this code:

Rx.Observable.fromEvent(document.querySelector('h1'),'click').subscribe((x)=>{
  alert()
})

So whats the advantage of using rxjs?

One of the advantages - is that you can use plenty of various utils which helps you:
For example if you want you code to respond not more than one events per second you can simply write this code:


Rx.Observable.fromEvent(window,'resize')
.throttleTime(1000)
.subscribe((x)=>{
  document.querySelector('h1').innerText =window.outerHeight
})

Which is nice
link to running code

10/1/17

Angular and AOT

Intro

It is a long time since i started to play with new angular (currently 5 beta). Currently i found that i know very little about AOT feature, so i think, it is good time to write a post about it.

So, What is this AOT thing about?

AOT - means Ahead Of Time Compilation, but what exactly is being compiled? after all we talking about javascript - an interpreted language which needs no compilation!
According to that it saying at angular site - the AOT is configuration that makes angular to precompile the HTML templates of components, and thus saves the the HTML processing (here is that "compilation" means in this case) from being performed at application runtime.

Sounds Like A Good Thing, So How Can I Get It In My Project?

If you use angular-cli tool for your project scaffolding it is very easy: Instead of usual


ng serve 

command, you can use

ng serve  --aot=true

command
You can see the difference in chrome dev tool:
ng serve
ng serve --aot=true
As you can see - the load time reduced to almost half size with AOT option

9/24/17

Source Maps

In this post i will talk a little about source maps - what are they and which problem they solve, and how to get them in your project.
So, if you sitting comfortably - lets begin

Minification

It pretty common that in nowadays project all javascript files are minified (or uglyfied) and concatenated into one file. Why?
Because to have project devided to many files(although it is convenient for developers) makes loading process slower (less performant).
Also it is a good practice not to expose your javascript logic to everybody...
But what about debugging the minified code? is it possible?

Source Maps

The answer is - yes, but (there is always a catch!) you must first configure the source map task to run alongside with magnification task. Source maps - are files (decorated with .map extension) which generated during uglification, which are (citing from this great guy) - links pieces of your minified bundle back to the original, unbuilt files.

How to get it work inside you project?

That is easy: Assuming that you have minification task run by Grunt-contrib-uglify task, all you need to do is to add following option:


...
uglify: {
    dist: {
        src: ['<%= src.js %>'],
        options: {
            sourceMap: true // - this will do the magic!
        },
        dest: '<%= distdir %>/js/<%= pkg.name %>.min.js'
    }
},
...

And now, after running grunt build task (which includes uplifting) you can see in your distilled folder the ".map" files and ,once you open your chrome dev tools and try to search for some line of your code - you will see the following picture:
Thats all - now you have source maps in your project...

One more trick

Of course - source maps are good as long as we talking about dev environment. In order not to create them at your production environment you can use conditional configuration:


...
uglify: {
    dev: {
        src: ['<%= src.js %>'],
        options: {
            sourceMap: true
        },
        dest: '<%= distdir %>/js/<%= pkg.name %>.min.js'
    },
    prod: {
        src: ['<%= src.js %>'],
        dest: '<%= distdir %>/js/<%= pkg.name %>.min.js'
    }
}
...
grunt.registerTask('prod', ['recess:min', 'uglify:prod', 'copy'])

Now, for production build you can simply call:

 node_modules/.bin/grunt prod

9/3/17

My Implementation For Promises.All

Recently been asked again on some interview to write my own implementation of "Promises.All", so i decided to write a post in which i'll explain all i know about promises.

What Are Promises?

According to MDN - The Promise is object that represents the completion or failure of an asynchronous operation, and its resulting value. The "asynchronous" meaning is that the time when the result will finally came is unknown. Promise can have three following statuses: pending, fulfilled and rejected
Example:


function myAsyncFunc(){
  return new Promise((reject, resolve) => {
     resolve(true);
  })
}

To get result of this function you will need to use following syntax:

myAsyncFunc().then(function(result){
  console.log(result)
})

Usually promises used to handle asynchronous ajax requests like:

fetch('https://api.github.com/users/angular/repos').then(data=>data.json())

Chaining Promises

What if you need perform some async operations consequentially (one after other)?
For example - to get all repositories of some organization and after get info of the first one?
Well you can use some nested "then" like this:


fetch('https://api.github.com/users/angular/repos')
.then(data=>data.json())
.then(data=>{
    fetch('https://api.github.com/repos/angular/angular.js')
    .then(repoData=>repoData.json())
    .then(repoData=>{
       console.log(repoData);
    });
})

This will work but code is sprayed on lot of "levels", More accurate syntax is to return values of each promise result:

fetch('https://api.github.com/users/angular/repos')
.then(data=>data.json())
.then(data=>{
   return fetch('https://api.github.com/repos/angular/angular.js')
})
.then(data=>data.json())
.then(repoData=>{
    console.log(repoData);
});

Promise.All

Sometimes you need some requests parallel way (all at once). Angular has for this case $q.all method which receives array of promises and fires callback with arguments for each result of promises list.
Important! results should be ordered in the same order as promises in the array, even if some reults came much later than preceding ones....
Here is my implementation for "promises all"


let all = (promises) => {
  //datas is object 
  let datas={};
  //must return promise
  return new Promise((resolve, reject)=>{
    //runs for each promise
    promises.forEach((promise, idx)=>{
      promise.then(p => {
        datas[idx]=p;//stores results at index property
        if(Object.keys(datas).length===promises.length) { //Object.keys(datas).length is indicator that last result received
          let  res =  Object.values(datas); 
          resolve(res) 
        }  
      })  
    });//foreach
  });
}

8/13/17

Vue Routes (Part 5)

Old School

In previous part we make a form component for "insert a new book" functionality. Since this component should be shown only when somebody wants to add a new book and pressed "Add New Book" button - we hide using v-if directive:


  <div class="row" v-if="showForm">
    <book-form v-on:book-added="onBookAdded"></book-form>
  </div>

Routing

There is a different (and more accurate) way to manage components in the application: instead of placing them straight into the markup you can load them using routes.
All you need to do for use routes is:
1. put into your code a reference to vue-router.js lib.
2. place router-view directive in place where you want your components to be loaded:


  <router-link to="/">/home</router-link>
  <router-link to="/form">/Add New Book</router-link>
  <router-view></router-view>


3. add router property to configuration of your main component:

const Home = { template: '
' } const router = new VueRouter({ mode: 'history', routes: [ { path: '/', component: Home }, { path: '/form', component: formComponent } ] }) new Vue({ el: '#app', router, data: { title: 'Pnei Kedem Book Club', books: [], loading:false, showForm:false }, .... ....
Well currently our form cannot add a new book, but we will fix it in the next part.
Look here for running code

7/7/17

Add Book Form (Part 4)

Ok, we learned how to display some items list with Vue in previous steps.
Now it is time to learn about most common for all web apps thing - the form. Lets create an "add book" component:

/* book-form component */

Vue.component('book-form', {
  data(){
    return {
        title: ''
    }
  },
  methods: {
   submitForm: function (e) {
          e.preventDefault();
          this.$emit('book-added',{title:this.title})
        }
  },
  template: `
  <div class="container text-center">
      <form>        
        <div class="form-group">
            <label for="title" class="col-sm-2 control-label">title</label>
            <div class="col-xs-10">
                <input  class="form-control" v-model="title" id="title" placeholder="title">
            </div>
        </div>
        <button class="btn btn-primary" v-on:click="submitForm">Add</button>
      </form>
  </div>
  `
});

like in angular there is v-model directive in vue which tracking user input and producing it into javascript model
see the full code on this jsfiddler

6/25/17

Loading Data From Api Vue - Part 3 (fetch)

In previous post we created the "Book Club" app home page which displays list of most popular books.
Of course all books came currently from static variable.
Now instead of display static data lets try to display data from api.

Fetch

Changes are very slight: In the "data" section we need to define books as empty array instead of static data:


new Vue({
  el: '#app',
  data: {
    title: 'Pnei Kedem Book Club',
    books: [] //<--empty
  }
})

Next step is to add "get" call to API inside "mounted" method:

new Vue({
  el: '#app',
  data: {
    title: 'Pnei Kedem Book Club',
    books: []
  },
  mounted() {
    fetch("//api.mlab.com/api/1/databases/mydb/collections/books?apiKey=myKey")
    .then(response =>response.json())
    .then(response => {
        this.books = response;
     })
   }
})

As you can see - the change is very slight...(no services, no dependency injections needed)
For running code see this jsfiddle

6/7/17

Staring With Vue.js - Part 2 (Components)

It is well known fact that it better to have your frontend code splitter into incapsulated parts - the components. Almost all js frameworks are implementing webcomponents in some way. Vue.js is not an exception.

Creating Component

When we created list of first 5 popular books we used for each book representation few html elements:


 <div class="row">
    <div class="col-xs-4 text-center"  v-for="book in books">
      <a href="#" class="thumbnail">
        <img v-bind:src="book.img" width="200" height="276" >
        <span>{{ book.title }}</span>
      </a>
    </div>
  </div>  

Instead of having all those html elements with classes styles and attributes we can have only one component element

Book Item


In Vue you can easily create component in following way
Vue.component('book-item', {
  props: ['book'],//<--property
  template: `
  <div class="col-xs-4 text-center">
      <a href="#" class="thumbnail">
        <img v-bind:src="book.img" style="height:226px" >
        <span>{{ book.title }}</span>
      </a>
  <div>
  `
}); 

Notice that this component has binding property "book" from which it gets a book object - the book the component should display
Finally we can use our book-item component inside book repeater:

  <div class="row">
    <book-item :book="b" v-for="b in books"></book-item>
  </div>  

for viewing code, please look at this jsfiddle

5/21/17

My Book Club Project or Starting With Vue.js

Motivation

I'm living in small settlement where everybody knows everybody and we have no library for children yet... Since i'm inspired by the this article, i decided to create Book Club project and also to play with vue.js

Book club project

It should be only book list where each family will be able to publish some books of they own which they allow to lend. Every book has it synopsis, rating, reader recommended age (because most of reader are children), picture, author and owner. Every resident of our settlement can land any book for 30 days period

Site Planning

Home Page will display first 15 most popular books and search & filter input, each book in the list will display picture, synopsis and rating, and also owner and current holder

Lets Start With Vue.js

My first Challenge is to display the home page book gallery. Data may come meanwhile from static javascript:
In vue we must place model into "data" property of object:


new Vue({
  el: '#app',
  data: {
    title: 'Pnei Kedem Book Club',
    books: [
      { title: 'Tom Soyer' ,author:'Mark Twein', img:'//upload.wikimedia.org/wikipedia/commons/thumb/1/1d/Tom_Sawyer_1876_frontispiece.jpg/200px-Tom_Sawyer_1876_frontispiece.jpg'},
      { title: 'Midnight Folk',author: 'John Masefield', img:'//upload.wikimedia.org/wikipedia/en/3/35/MidnightFolk.jpg'},
      { title: 'Emil From Leneberg' ,author:'Asterid Lindgren', img:'//upload.wikimedia.org/wikipedia/en/thumb/1/1c/Emil_i_L%C3%B6nneberga.jpg/190px-Emil_i_L%C3%B6nneberga.jpg'}
    ]
  }
})

Repeater

Vue has its own repeater syntax v-for:


 <div class="row">
    <div class="col-xs-4 text-center"  v-for="book in books">
      <a href="#" class="thumbnail">
        <img v-bind:src="book.img" width="200" height="276" >
        <span>{{ book.title }}</span>
      </a>
    </div>
  </div>  

Notice that for bind image source you may use v-bind syntax.
Here is running jsfiddle

5/12/17

Dockerize Your Angular CLI Project

Why docker?

Microservices

Microservices it is architecture pattern where project divided to self containing parts which can be run or test independently (as service). Docker makes you able to package parts of your projects and run them together.
Lets name some basic terminus of docker:

Image

Environment of some sort of machine (e.g. Ubuntu) with some tools preinstalled (e.g. node)

Container

One or more images composition that can be run with some parameters.
Containers can be easy moved to different environments like develop, qa or production(thats grate advantage of docker).

Example

Lets create simple container with which all members of your team will be able to start develop angular4 app with one singe command:

Lets create an image

To create an image you must add Dockerfile


# Create image based on the official Node 7.6.0 image from dockerhub
FROM node:7.6.0

# Create a directory where our app will be placed
RUN mkdir -p /usr/src/app

# Change directory so that our commands run inside this new directory
WORKDIR /usr/src/app

# Copy dependency definitions
COPY package.json /usr/src/app

# Install dependecies
RUN npm install

# Get all the code needed to run the app
COPY . /usr/src/app

# Expose the port the app runs in
EXPOSE 4200

# Serve the app
CMD ["npm", "start"]

since you don't want to copy node_modules you also need to add .dockerignore

node_modules/

After the files added to project only thing left is to run "build" command

docker build -t angular-client:dev .

after image created you can run it with following params:

docker build -t angular-client:dev .

Thats all - angular-client image created

Run the container

to get container running you can use following command:


docker run -it --volume=/Users/your-user/your-directory/your-project:/localDebugRepo -p 4200:4200  --workdir="/localDebugRepo" --memory=4g --memory-swap=4g --entrypoint=/bin/b
ash angular-client:dev

This command makes you able to log into your container machine now you can run app with following command:

npm start

Now you can view the app running on localhost:4200

4/19/17

Doing git commit --amend (first time)

Every git user get through this experience: You did commit and immediately after you realized that you forgot something embarrassing...
Thats exactly situation --amend option is built for. It is for getting new commit to be merged into previous one so in git history you will see only one entry (the last one)...

For example:

Lets say you notice that you have some extra file inside your project, that shouldn't be there, you can remove it and commit with following command:

git commit -m "removing extra files"

Lets see that commit registered in git history:
Now lets say, after have second look on your project you notice one more extra file and you need to commit again:
This time you can use amend

git commit -m "remove extra zip file" --amend

Now you can see that in history remain only one entry with latest commit message.

4/10/17

My First Video Tutorial

I decided to create some very short video about how to start program with react:

3/29/17

PostCSS - The Next Cool Thing

What is post CSS?

Is PostCSS one of Sass/Less kind things?
The one-word answer is: NO
In more than one word -
postCss it is lot of plugins under same parent node plugin clalled: postcss , which have same target - to do various things on CSS.

Which things for example?

First of all take a look on postCSS README at github page and then here to get the impression of kind of various plugin some good guys made for us... (writing this post I was inspired by this grate tutorial)

Challenge

The challenge is to play a little with postCSS and use it in react-first-steps repo, from previous posts
To make use of variables mixins and sass like postcss-nested plugins

webpack.config

First you need to install all the plugins


npm i postcss-loader postcss-import postcss-mixins postcss-nested postcss-simple-vars  --save-dev

to add postcss.config file to the project

var postCSSConfig = [
/* autoprefix for different browser vendors */
require('autoprefixer'),
/* reset inherited rules */
require('postcss-initial')({
  reset: 'inherited' // reset only inherited rules
}),
/* enable css @imports like Sass/Less */
require('postcss-import'),
/* enable mixins like Sass/Less */
require('postcss-mixins')({
  mixins: require('./src/mixins')
}),
/* enable nested css selectors like Sass/Less */
require('postcss-nested'),
/* require global variables */
require('postcss-simple-vars')({
  variables: function variables() {
    return require('./src/variables')
  },
  unknown: function unknown(node, name, result) {
    node.warn(result, 'Unknown variable ' + name)
  }
}),
/* PostCSS plugin for making calculations with math.js  */
require('postcss-math'),
/* transform W3C CSS color function to more compatible CSS. */
require('postcss-color-function')
]

// Export the PostCSS Config for usage in webpack
module.exports = postCSSConfig;

To update webpack.config file

         {
            test: /\.css$/,
            include: srcPath,
            loader: 'style!css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]&camelCase!postcss'          
         }]

for view the full code look at this repo

3/23/17

Using Animation Module With Angularjs

Hi dear dudes & dudesses!
Today we gonna speak about angular animate module,
Yes, in case you didn't noticed , alongside with "controller", "directive" and "filter" angular recipes, exists another one - "animate".
You can use it by adding "ngAnimate" module to your modules:


angular.
  module('yourApp', [
    'ngAnimate',
    ...
  ]);


Until now I didn't have a chance to really use it in some of my projects, actually I have only read about what it suppose to do in great phonecat tutorial - the "first steps" tutorial that angular guys made for us.

Challenge

So current challenge is to try to animate the dropdown directive I have created in one of my old posts, in a way to will expand when open and collapse when closed.

Get Started

Since angular animations triggered when one of angular events enter, leave, add and move takes place - we need to modify our components in a way it will use ng-if directive which cuases enter and leave events to fire:
Instead of hide/show dropdown menu by adding and remove 'open' class on its parent I will make dropdowMmenu template to listen to its parent isOpen property...


angular.module('ui.components',['ngAnimate'])
.component('dropdown',{ 
  controller:function($element,$document,$animate, $timeout) {
     $element.addClass('dropdown');
     
     var menu = $element.find('dropdown-menu')[0];
   
     $document.on('click',(evt)=>{
        if(!$element.find('dropdown-toggle')[0].contains(evt.target)){
          this.close() 
        }
     })
 
    this.close=() => {
       $timeout(()=> this.isOpen = false,1); 

    }
    this.open=() => {
       $timeout(()=> this.isOpen = true,1);
    }    
  }
})
.component('dropdownToggle',{
  require: {
    parent: '^^dropdown' 
  },
  controller:function($element) {
    $element.addClass('dropdown-toggle');
    $element.on('click',($event)=>{
       this.parent.isOpen ? this.parent.close() : this.parent.open();
    })     
  }
}) 
.component('dropdownMenu',{
  require: {
    parent: '^^dropdown' 
  },
  transclude:true,
  template:'<div class="dropdown-menu" ng-if="$ctrl.parent.isOpen" ng-transclude></div>'//IMPORTANT: hide menu with ng-if directive
})

Important!
Since now we use ng-if to hide and show menu we must remove display:none rule from CSS of .dropdown-menu class.

Animation Module

The time for use animation recipe came.


.animation('.fold-animation', ['$animateCss', function($animateCss) {
  return {
    enter: function(element, doneFn) {
      var height = element[0].offsetHeight;
      return $animateCss(element, {
        from: { height:'0px' },
        to: { height:height + 'px' },
        duration:0.25
      });
    },
    leave: function(element, doneFn) {
      var height = element[0].offsetHeight;
      return $animateCss(element, {
        from: { height:height + 'px' },
        to: { height:'0px' },
        duration:0.25
      });
    }    
  }
}]);

I copied this code from this angular example with slight modifications
See full code on this plunker.
Also you can read more about angular animations in their accurate docs

3/21/17

Angular2 and NgRx

My Challenge was to get little experience of working with ngrx .
What is NgRx?
NgRx is RxJS powered, inspired by Redux state management lib for Angular2.

Basic Philosophy

Like many state management frameworks like Redux - app skeleton must include following module types - Store, Actions and Reducers

Store

simple class or object representing the application state


import postListReducer, * as fromPostList from './post-list';
import postReducer, * as fromPost from './post';

export interface AppState {
    posts: fromPostList.PostListState;
    post: fromPost.PostState;
};

Actions

function that passes type and params of what reducer should do


    static LOAD_POSTS = '[Post] Load Posts';
    loadPosts(): Action {        
        return {
            type: PostActions.LOAD_POSTS
        };
    }

Reducers

Immutable function that returns new object containing changed current state returned


export default function (state = initialState, action: Action): PostListState {
    switch (action.type) {
        case PostActions.LOAD_POST_SUCCESS: {            
            return action.payload;
        }
    }
}

Effects

Since state actions are asynchronous - it is better to take advantage of using effects:


    @Effect() loadPosts$ = this.update$
        .ofType(PostActions.LOAD_POSTS)
        .switchMap(() => {            
            return this.svc.getAllSections();
        })
        .map(posts => this.postActions.loadPostsSuccess(posts));

Refactoring our components

Now we can replace our logic inside components:
Instead of:


   this.loadHtml.getPost(params['id']).subscribe(post => {
        this.post = post;
      })

We can now write:

  this.store.dispatch(this.postActions.getPOST(this.name));
  ...
  ...
   store.select('post').subscribe((post:Post) => {
     this.post = post;   
  })

Much more accurate, is it?

3/9/17

Learning Angular2 - Free Stuff

Hi my dear readers, hope you all well...
Wanted to publish some interesting post about angular2 form validations.
Template driven forms VS reactive forms, NgModel, NgForm etc... You know

But instead i decided it will be more useful to publish links to some angular2 tutorials/ blogs i gathered across internet:

Free online Books:
Free video tutorials:
Blogs
Github Repos


Thats not a lot, but pretty angouth to start with...
Anyway feel free to add more free useful stuff in the comments!
   

    

2/28/17

Building Stretching to the bottom Layout With Flex-Box

Layout

Everybody knows that to build the layout is complicate thing, especially when we talking about layout which should stretch to page bottom. In other words - with footer sticking to page bottom.

I'm sure there is a lot of ways around how to build this layout, but in this article i will try to show how to build it using flex-box CSS3 feature

Dividing to sections

First lets decide to how to divide our layouts to sections:
I decided that two main sections will be displayed one besides other like to columns - nav and main elements
Inside main element will be 3 other sections positioned one above the other:header,article and footer


    <div class="wrap">
      <nav>
        <ul>
          <li><a href>1 link</a></li>
          <li><a href>2 link</a></li>
          <li><a href>3 link</a></li>
        </ul>
      </nav>
      <main>
         <header>Hello Plunker!</header>
         <article>
           HellHePlunkllo Plunker! Plunk
           Hello Plunker!Hello P Plunk
           lunker Plunk!o PHello Plunker Plunk
           !lunker! Hello Plunker! Plunk
         </article>
         <footer>footer</footer>
      </main>
    </div>

VH Trick

One css feature i found very useful is VH unit. This vh represents percents of view height (e.g. browser window height) ,and thus given some element height set to 100vh makes it to stretch over the whole window from its top to its bottom


.wrap{/* root container */
  height:100vh;
  background:green;
  display:flex;
}

Nav & Main sections flow

Since we want those sections to be stick one near other (like two cells in the row) all we have to do is set the display property of their container to flex
By default flex-direction property is "row"
Since nav section has fixed width of 234px - all that left to do is to make the main section to catch all the remaining space:


nav{
  width:234px;
  background:orange;
}
main{
  flex:1   100%;/*will make it stretch over remaining space*/
}

Header Article and Footer

First thing is to set flow of main container to be column


main{
  display:flex;
  flex:1   100%;
  flex-direction:column;
}

Now the only thing left is to arrange the header above the article and make article to catch all available space between header and footer.

article{
  flex:1   100%;
  background:red;
}

See this plunker for running code

2/22/17

Building Drop Down Menu Using Angular1 Component

Challenge

To build drop down menu like angular-ui-bootstrap with angularjs using "component":

Behaviors

  1. Menu toggle button Should open hidden menu when clicked, and to hide the menu if it open
  2. Menu Should Close itself when users clicks on some other place
  3. If disabled - should not show anything when clicked

Step 1 - CSS & HTML

For sake of simplicity i will copied styles from bootstrap framework:


.open > .dropdown-menu {
    display: block;
}
.dropdown-menu {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 1000;
    display: none;
    float: left;
    min-width: 160px;
    padding: 5px 0;
    margin: 2px 0 0;
    font-size: 14px;
    text-align: left;
    list-style: none;
    background-color: #fff;
    -webkit-background-clip: padding-box;
    background-clip: padding-box;
    border: 1px solid #ccc;
    border: 1px solid rgba(0, 0, 0, .15);
    border-radius: 4px;
    -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
    box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}

and the html will be following:

    <dropdown>
        <dropdown-toggle>
        <a href="">Dropdown <span class="caret"></span>
        </a>
        </dropdown-toggle>
        <dropdown-menu>
        <li>
            <a href="" ng-click="$ctrl.sayHi()">Action</a>
        </li>
        <li>
            <a href="">Another action</a>
        </li>
        <li>
            <a href="">Something else here</a>
        </li>
        <li role="separator" class="divider"></li>
        <li>
            <a href="">Separated link</a>
        </li>
        </dropdown-menu>
    </dropdown>

inside 'dropdown-toggle' container user should be able to place html of 'a' tag or button (according to his needs)
inside 'dropdown-menu' container user should be able to place html of menu items - there he should be able to attach methods from controller - like sayHi

dividing to components

I decided to divide this component to three different components:
The dropdown Parent component and dropdownToggle and dropdownMenu child components
That way logic will be splitted to its specific component

dropdown component

Should contain close and open methods


angular.module('drop',[])
.component('dropdown',{ 
  controller:function($element,$document) {
    $element.addClass('dropdown');//
    this.close=() => {
      $element.removeClass('open');
      this.isOpen = false;
    }
    this.open=() => {
      $element.addClass('open');
      this.isOpen = true;
    }    
  }
})

The mechanic here is that menu is visible when the main container (dropdown element) have "dropdown" and "open" classes, that why close and open are adding and removing 'open' classes accordingly

dropdownToggle component

Is the element that must handle the clicks and activate its parent 'open' and 'close' methods;
For be able to access its parent methods i'm using require option inside component definition:


.component('dropdownToggle',{
  require: {//<--USING REQUIRE OPTION
    parent: '^^dropdown' 
  },
  controller:function($element) {
    $element.addClass('dropdown-toggle');
    
    $element.on('click',($event)=>{
       this.parent.isOpen ? this.parent.close() : this.parent.open();
    })     
  }
})

click outside behavior

For be able to close the menu when user clicks somewhere else on the screen i'm taking advantage of $document service:
dropdown.js



 ...
  $document.on('click',(evt)=>{
    if(!$element.find('dropdown-toggle')[0].contains(evt.target)){
      this.close() 
    }
  })
...

You can see running code on this punker

2/9/17

Lazy loading - Is it possible in Angular1

What Is Lazy Loading?

Single page application, as you can see from its name - is built with one single page. In this single page javascript loads (when needed) various views. Each view may have its won modules, components, and other javascript logic inside them. Since it may happen that site user will not access some views at all - it is good practice to avoid load then every time the app accessed, istead - the ideal tactic is to load those javascript parts only when this specific view was called. But is there some way to do it in angular1?

The Answer is Yes

Actually there is a way to implement lazy loading with angularjs, for example by using ocLazyLoad angular module. You can read here how to load entire module or only some directive or service or how to load some state from a script!

Experiment

As usual lets show how to use lazy loading on some of our old good projects - the angular phonecat.
Lets start with download or clone the project to some local directory.

git clone https://github.com/angular/angular-phonecat.git


After installing dependencies (npm i) lets register the ocLazyLoad module to bower.json:

bower i oclazyload -D

After install and place reference on index.html file, we must register lazy load module in root application module:


'use strict';

// Define the `phonecatApp` module
angular.module('phonecatApp', [
  'ngAnimate',
  'ngRoute',
  'core',
  'phoneDetail',
  'phoneList',
  'oc.lazyLoad'
]);

Create About Page

For testing lazy load feature lets create "about" module which will contain "component","config","module" and "template" files

we will rester only "config" and "module" references on the index.html
Lets add about module to our root "phonecatApp" module:

angular.module('phonecatApp', [
  'ngAnimate',
  'ngRoute',
  'core',
  'phoneDetail',
  'phoneList',
  'oc.lazyLoad',
  'about' 
]);

We didn't put the reference to about.component fie on the index.html on the purpose.
The "component" file will load with lazy load module after user will access "about" route.


angular.module('about').
    config(['$locationProvider', '$routeProvider',
        function config($locationProvider, $routeProvider) {
            $routeProvider.
                when('/about', {
                    template: '<about-comp></about-comp>',
                    resolve: ['$ocLazyLoad', function ($ocLazyLoad) {
                        return $ocLazyLoad.load([{
                            files: ['about/about.component.js']
                        }])
                    }]
                });
        }
    ]);

Lets try to navigate to /about url
Wow! Now you can see the about component is loaded!
Thanks for reading

2/2/17

Using Angular2 Components Inside Angular1 Project

Dreaming About Upgrade

If you working on project that built with angular1 for historical reasons and dreaming about move to angular2 - this article is for you.
Yes, it is possible to move to angular2 make little changes step by step, without breaking the running code of your application. In this article i will take this angular-seed repo and try to make it run with some angular2 component included.

Step 1 - Bootstrap Angular Different Way

Usually the angular is attached to HTML using ng-app directive but there is another way to bootstrap angular to your application - using angular.bootstrap utility:


angular.bootstrap(document.body, ['myApp'], {strictDi: true});

You can view source at this branch

Step 2 - Migrating to Typescript

To move project to typescript you need :
1. rename all the files to end with ts instead of js (meanwhile leave files finishing with 'test' and not rename them to ts)
2. install typescript compiler:

npm i typescript -D
3.create tsconfig.json file at root directory

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "suppressImplicitAnyIndexErrors": true
  }
}

4. install type definitions for angular and other dependencies
npm install @types/angular -D
If all the installations succeed - after running
tsc -p .
command all ts files should have their ".js" and "map.js" copies - appear near them.


You can view source at this branch

Step 3 - Move application to load dependencies from node modules

Why? Mostly from reason that angular2 recommend to load dependencies this way instead of using bower. So, since node_modules directory located at project root we need to modify index.html so all the urls will stay correct:
Insert base tag inside head tag of your index.html


<base href="/app/">

Also you will need to change "start" script inside package.json:

"start": "http-server -a localhost -p 8000 -c-1 ./",

Now you can install all the dependencies like angular through NPM:

    "angular": "^1.6.1",
    "angular-route":"^1.6.1",

Don't forget to change the paths inside the index.html:

  <script src="/node_modules/angular/angular.js"></script>
  <script src="/node_modules/angular-route/angular-route.js"></script>

Now make sure that after you run
tsc -p ./
and then:
npm start
command you can see the project running:

You can view the full code on this branch

Step 4 - Install Systemjs Module Loader

Module Loader - a way to make javascript to import or export different javascript types (like classes) from one file to other. There are several javascript module loaders such as Webpack, Browserify, Systemjs - for our tutorial we will use systemjs.

npm install systemjs -D
After installation lets try to include the systems script to "index" page:

  <script src="/node_modules/systemjs/dist/system.src.js"></script>

Important: systemsjs uses its own configuration file - systems.config You may place it in the "app" directory:


/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': '/node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: '/app',

      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',      
      '@angular/upgrade/static':'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
      // other libraries
      'rxjs':                      'npm:rxjs',
      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      }
    }
  });
})(this);

This files points to system module loader where the scripts located. Lets see if it loaded now in the chrome developer tools:
After we can see everything is still working lets add angular2 dependencies to package.json:

    "@angular/common": "~2.4.0",
    "@angular/compiler": "~2.4.0",
    "@angular/core": "~2.4.0",
    "@angular/forms": "~2.4.0",
    "@angular/http": "~2.4.0",
    "@angular/platform-browser": "~2.4.0",
    "@angular/platform-browser-dynamic": "~2.4.0",
    "@angular/router": "~3.4.0",

    "angular-in-memory-web-api": "~0.2.4",
    "systemjs": "^0.20.4",
    "core-js": "^2.4.1",
    "rxjs": "5.0.1",
    "zone.js": "^0.7.4"
You also must point to systems that you main module is inside "app" directory:
index.html

    <script src="systemjs.config.js"></script>
    <script>
      System.import('/app').catch(function(err){ console.error(err); });
    </script>

Important: you must remove main.js reference from index.html
And run again:npm install and after :tsc -p .

If everything is OK you should refresh and see the app running as usual.

Little Experiment

Now lets try to import some file into main.ts file using import command:
main.ts


import './app'
declare var angular: ng.IAngularStatic;//must not override global angular
angular.bootstrap(document.body, ['myApp'], { strictDi: true });

Now you can remove app.js reference from index.html and see that app still running (since the code imported by systemjs!)

You can view full code on this branch

Step 05 - Install Angular Upgrade

Now we about to enter cherry-in-the-cake zone of this article - start using angular2 and angular1 in the same project

 npm i @angular/upgrade -D
This angular2 module makes you to be able to include angular2 modules into your angular1 project.
Lets add angular2 module named AppModule
app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static'
@NgModule({
  imports: [
    BrowserModule,
    UpgradeModule,
  ],
})
export class AppModule {
  ngDoBootstrap() {}
}

Now the only thing left is to inject your old myApp module angular2 way:
main.ts

/*angular.bootstrap(document.body, ['myApp'], {strictDi: true});*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
  const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
  upgrade.bootstrap(document.body, ['myApp']);
});

Voula! you running angular2 and angular1 together now!
You can view source code on this branch

Thanks for reading

1/25/17

Creating My First Type Definition

Typescript Main Point

One of reasons the typescript was invented is to get javascript errors to be detected in compilation step.
For example:
If you defined function myFunc and it suppose to be called without any params, and your code use its call in multipple places:


function myFunc() {
  alert('my name is Shlomo');
}
//call
myFunc()

And after some time you decided to change function code to use the parameter:

function myFunc(nm) {
  alert('my name is ' + nm);
}
//call
myFunc('Shlomo')

In case you using javascript and you forgot to change call in some place to its new shape - you will got 'nm is undefined' error when code will try to run following call.

//call
myFunc()

in typescript After you changed myFunc definition to use parameter:

myFunc(nm:string) {
  alert('my name is ' + nm);
}
//call
myFunc()//this will not compile

If there are some calls which not using parameter left- Typescript compiler will fail.

What are type definitions?

So if you use typescript and want to use some javascript library or plugin in your code - this plugin and its methods need to be defined in a way that typescript will "recognize" it.

Experiment With Selectize

For example purposes lets take our old angular-seed project which uses typescript. To demonstrate what happen when you try to use some javascript plugin inside typescript project lets install selectize.js jquery plugin

bower install selectize --save-dev

And place the call to the plugin inside View2Ctrl controller:
As you can see - trying to use the plugin as it is made vscode angry
You can see also compilation error:

Create Starter Definition File

As we can see in other definitions - the selective definition must be hosted inside node_modules/@types directory. lets add selectize directory and add index.d.ts file inside it. I will not write here about create real definition - since guys much wiser than me already created it here,
My purpose now is only to create something that make the typescript compiler calm.


/// <reference types="jquery"/>

declare namespace Selectize {
 
}
interface JQuery {
    selectize(options?: any): JQuery;
}


As you can see - i only added selectize method to Jquery interface
That is enough for get the source compiled -

Thanks For reading

1/18/17

Unit Tests In Angular2 - part 3 (Component That Uses Service)

In previous post we've learned how to test the angular2 component.
That was very nice and we have a lot of fun, but everybody knows that in real life many components may use services to bring data from server.
Lets demonstrate it on our user component:
Lets make it to display friends list of this user:



@Component({
  selector: 'my-app',
  template: `<span>name: <strong>Victor Savkin</strong></span>
   <hr/>
   <strong>Friends:</strong>
   <ul>
     <li *ngFor="let friend of friends">
       {{friend}}
     </li>
   </ul>`
})
export class App {
   
    public friends:string[]=[]
    constructor(private usersService:UsersService) {
    }
    ngOnInit(): void {
       this.usersService.getUsers().subscribe(
         users => {
           this.friends=users;
         },
         error=>console.log(error) 
       );
    }
}


And the code of UsersSerivice:

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class UsersService {
  constructor(private http:Http) { }
  
  getUsers(){
    return this.http.get('api/users.json')
      .map(response => response.json());
  }
}


So How To Test This Thing?

Lets say we want to test that request populates the "friends" section with friends names.
Since it is bad practice to make real http request for testing purposes - we need to create a mock of UsersService:


import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
  
  class MockUsersService {
    public get() {return  Observable.of(['John', 'Steve']);}
  }

Once we have the mock of UsersService -lets inject it into the module instead of usersService:

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [UserComponent], 
      providers:[// <--HERE IS THE MAGIC!!!
       { provide: UsersService, useClass: MockUsersService}
      ],
      imports: [ HttpModule,BrowserModule ]
    })
    .compileComponents();
  }));

Great, inst it?
Now we can test the component and see if friends are displayed as planned:

  beforeEach(() => {
    fixture = TestBed.createComponent(UserComponent);
    comp = fixture.componentInstance;
    comp.user = new UserModel('Vasia','Kozlov')
    de = fixture.debugElement.query(By.css('span'));
    element = fixture.nativeElement;// to access DOM element
  });

  it('should have list of friends displayed inside UL',  async(() => {
    fixture.detectChanges();
    fixture.whenStable().then(() => { 
      expect(element.querySelector('li:first-child').innerText).toBe('John');
      expect(element.querySelector('li:last-child').innerText).toBe('Steve');
    })
  }));

you can see the full code on this plunker

1/10/17

Unit Tests In Angular2 - part 2 (The Component)

Testing The Component

In previous post we've learned how to test the model (Simple javascript object) and the Service in angular2. Now I think' we ready for next step:

How To Test The Component

Lets say we have a User Component which should display the full name of some user:
(user-component.ts):


import { Component,  Input} from '@angular/core';
import {UserModel} from './user-model'
@Component({
    selector: 'user-component',
    template:   `{{ user.fullname() }}`
})
export class UserComponent {
    @Input() user:UserModel;
}

This component contains @input annotation - which means the parameter from outside (named user) should be set

The Test

As in case of Service we should start with setup the module with testBed util:
(user-component.spec.ts):



import {UserComponent} from './user-component'
import {UserModel} from './user-model'
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

describe('UserComponent tests', function () {
  let de: DebugElement;
  let comp: UserComponent;
  let fixture: ComponentFixture;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [  UserComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(UserComponent);
    comp = fixture.componentInstance;
    comp.user = new UserModel('Vasia','Kozlov')// <--here we passing the outer parameter
    de = fixture.debugElement.query(By.css('span'));
  });

  it('should create component', () => expect(comp).toBeDefined() );

  it('should have fullname of user displayed inside "span" tag', () => {
    fixture.detectChanges();
    const h1 = de.nativeElement;
    expect(h1.innerText).toMatch(/Vasia Kozlov/i,
      ' should state user Full Name');
  });
});

As you can see - the outer parameter passed using fixture.componentInstance helper
You can view the running code on the plunker

1/5/17

Unit Tests In Angular2 - part 1 (Get Started)

Get Started

Here is link to amazing tutorial for someone who wanted to learn from real angular developers...
Angular 2 has it's way for writing unit tests, it is pretty resembles the angular1. The same jasmine, only in typescript

Example of Testing Person Model

Lets start with models since they are usual javascript objects:
(person-model.ts):


export class PersonModel {

    constructor(
        public firstname: string = '',
        public lastname: string = ''
    ) {};

}

So here how the tests should look:
(person-model.spec.ts):

import {PersonModel} from './person-model';

describe('PersonModel', () => {

  it('should return the correct properties', () => {

      var person = new PersonModel();
      person.firstname = 'Shlomo';
      person.lastname = 'The King';

      expect(person.firstname).toBe('Shlomo');
      expect(person.lastname).toBe('The King');

  });

});

Nothing complicate here...

Testing Angular2 Service

Next step I want to show how to test some service.
Services are usually built for send http requests and bring data:


import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class UsersService {
  constructor(private http:Http) { }
  
  get(){
    return this.http.get('api/users.json')
      .map(response => response.json());
  }
}

The Users service has only one method - get
So, this is how the tests should look:
users.service.spec.ts

import {inject, TestBed, async} from '@angular/core/testing';
import {HttpModule} from '@angular/http';

import {UsersService} from './users.service'
describe('Service: UsersService', () => {
  let service;
  
  //setup
  beforeEach(() => TestBed.configureTestingModule({
    imports: [ HttpModule ],
    providers: [ UsersService ]
  }));
  
  beforeEach(inject([UsersService], s => {
    service = s;
  }));
  
  //specs
  it('should return available users (async)', async(() => {
    service.get().subscribe(x => { 
      expect(x).toContain('sasha');
      expect(x).toContain('vasia');
      expect(x).toContain('pasha');
      expect(x.length).toEqual(3);
    });
  }));
  

}) 

Note that I'm using TestBed utility to initiate ngModel and the service with injected Http.
here is working plunker

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...