Mar 31, 2017

Angular 2 Components

Component consisted of two part one is component class which is like any other TS class and the other is meta data (@Component). Here you define selector, template , style etc.

Communicating with child component can be done by creating input property in child component and from parent component html pass this as attribute with square bracket

Communication with parent component

  • Template variable - Using template variable you can reference any child component output property within the template.
  • EventEmitter - Using output property of type EventEmitter, you can emit any event which you can bind in the parent component using parenthesis. In the event you can pass any data from the child component.


CSS is encapsulated within component, meaning css used in parent component will not affect child component and visa versa. You can still define global css which will be applied to all the components. 

Binding

Interpolation is used when you need to display the data {{}}. The text between braces is evaluated and then converted as string to display data. You can use javascript expression here, which do not have or promote side effects, for example  binding cannot contain assignment; {{ title='test' }} is not allowed. It can also invoke method of host component. Though inside method you can do some assignment, for which angular will not throw error but you will get unexpected result and this should be strongly avoided.

Refer following example, here we are assigning title property of host component to the value attribute of the input DOM element. This will be one way, meaning value property of component will be evaluated every time change detection cycle is triggered and string conversion of that will be assigned to the value attribute of the element
<input type="text" value="{{title}}">

Similarly in the following case div element will display title property of the component
<div>{{title}}</div>

Property binding [] is used when you want to bind data to property of dom element. For example in the following case value property of input DOM element is assigned with title property of host component. This will again be one way meaning value property will be eveluated eveytime change detection cycle is triggered
<input type="text" [value]="title" >

Event binding are used to bind event of the element. The expression used in this can have side effect. In the following example I am calling handleClick function on the host component on click event.
<input type="button" (click)="handleClick()">

I can also do assignment here as in following case in case of input event I am assigning value of target element to the title property of host component.
<input type="text" (input)="title=$event.target.value">


Structural Directive - This is indicated by *, which indicates that they can upadate DOM element.
*ngFor -
*ngIf- Render content only if expression is true. Its not just hiding by css, but the dom element is not rendered. In case you want to hide the element you can use hidden property([hidden]="some expression")
*ngSwitchCase used along with non structural directive ngSwitch

For evaluating expression you should use ? against the object property which can be null, This will short circuit evaluation of the expression.

Styling
[ngStyle] return class and style. Using this you can style multiple properties of element.
[ngStyle]="{'background-color': 1===2?'green':'blue', 'font-weight': 'bold'}"     -> style="background-color: blue; font-weight: bold;"

You can also use [style.background-color]="'blue'". Here we directly accessing style property of the element. Refer above for property binding


[ngClass] - This allows to update classed on the element. It is specified as key and boolean expression value
<div [ngClass]="{'small-text': 1===1, 'red'}"> => class="small-text red"

Property and Attribute

Property and Attribute are more often used interchangeably. When defining an html element you can specify its attribute and when browser parses code, a corresponding DOM object will be created, which will have its properties. For example the following element has three attributes id, type and value.

<input id="myElement" type="text" value="something" >

Once browser create DOM, this object will contain multiple properties like attributes, className, disabled, hidden, width, id, innerText, innerHtml, value, type, style etc. Write following javascript and inspect different properties on the element. You will notice attribute property which will include add the attribute defined in the html element.

let input1 = document.getElementById("3");

Property and attributes doesn't have one to one relationship, but more often many of the properties relates to attributes.

Projection

This enables to build reusable component by giving option to injecting mark up by consumer of the component. Here we saying that my-component will show <h4> tag as it is in this component and will be shown everywhere where we use my-component. The consumer also has option of passing content which will replace ng-content. You can multiple ng-contect and have selector which will give option to inject multiple content.

@Component({
    selector: "my-component",
    template: `
    <h4>something which will be shown everywhere</h4>
<div (click)="toggelContent()" class="well thubnail">
        <ng-content select=".title"></ng-content>
        <ng-content select="[body]"></ng-content>
    </div>

`,
})


You can use this component like this.

<my-component>
<div class="title">
my title
</div>
<div body>
my body
</div>
</my-component>

Mar 17, 2017

Angular 2 High level overview

Angular 1 was based on MVC framework which has a View/Template which can have one or more controller, which expose modal.

In Angular 2, you have a component which has associated template and as with angular 1 you have model which represent data. Component and template has 1-1 relation. Any angular 2 application has root application component that is loaded first and then the angular router load the appropriate component by looking at the url. The component template is then displayed in the browser and the component may then load some data from the server and give it to the template to display. Component can be composed of other components which is the typical case in any complex page. This can be considered as a tree like structure, when you load to a new page your root app component remains same and below that, router loads the corresponding component and its sub component, by looking at the new route. As your application gets bigger, this can become a lot of stuff to load into memory. This is where angular module (ngModule) comes in picture, which are the container that groups all these routes and component trees. Modules can be loaded independent of each other. Browser will load only the module which is being accessed.

Angular Module (ngModule) file has following main pieces.

The imports array
The module's imports array appears exclusively in the @NgModule metadata object. It tells Angular about specific other Angular modules — all of them classes decorated with @NgModule — that the application needs to function properly.

The JavaScript import statements give you access to symbols exported by other files so you can reference them within this file.

The declarations array
This tells which component belongs in this module

Bootstrap array
The bootstrapping process creates the component listed in the bootstrap array and insert each one on the browser DOM.


Refer this for good high level overview of angular2.

Refer this for quick start project. Also you can use angular cli tool to get started with the angular project.

Feb 18, 2017

Insecure Direct Object References

Insecure Direct Object References allow attackers to bypass authorization and access resources directly by modifying the value of a parameter used to directly point to an object. This is caused by the fact that the application takes user supplied input and uses it to retrieve an object without performing sufficient authorization checks.

Example will be changing query string (by guessing number/string) in url after user is authenticated. If server does not verify if user is authorized to access requested data, then user can easily gain access to unauthorized data, by just changing the input parameter. (getdetail?userName=Mike)

So the most important thing to mitigate this will be verify if user is authorized to access data which user is requesting, meaning implementing access control check. If possibly mask input parameter with key which is valid only for that session like session id. This way you not directly exposing something which can be guessed directly. 

Jan 6, 2017

HTML Import

HTML5 Import provides a standard way of importing html from a separate file onto the page, in the similar way we reference JavaScript and CSS. This can also be used to bundle JS, CSS and HTML. Without bundling you will have to have style and script referenced on all your pages, and also in a particular order. This way you can bundle everything for your custom element so that consumer don't have to worry about referencing necessary CSS/JS. HTML from external file must be added to the head of the page. 

<link rel="import" href="myimport.html" id="myimport">

JavaScript and CSS from the imported file get executed and applied immediately where as html is inert, meaning it's loaded in the browser but is not rendered. So if you have console.log('i am coming from myimport.html') javascript in the myimport.html, this will get executed by just putting above link. But to render html from the imported page you need to do following

     <script>
         var content = document.getElementById('myimport').import;
         var markupimportedfromfile = content.getElementById('fromimportedfile');
         document.body.appendChild(markupimportedfromfile);
     </script>
With the template tag, everything inside (markup or JS or CSS) is inert until cloned and this will still be the case if it is in the import file, but any CSS and JS directly defined in the import file will be executed\applied immediately. CORS rule will be applied for importing html.

Imported file can also have import within it. You can use this for importing JS/CSS library, this way sub-import file will have these libraries and you will import this file in all your custom element file. This can help in avoiding different custom element using different version of those libraries.

Referencing Owner Document
If you use selector on document object (document.querySelector) in the import file, it will search through the DOM defined in the file where it is imported. To get reference from the import file, you must use selector on document.currentScript.ownerDocument

Events
The link element has two events, onload and onerror. Script for that need to be added before adding the link

<script>
function loaded(event)  {
  console.log('import loaded');
}
 
function error(event)  {
  console.log('could not load ' + event.target.href);
}
     
    </script>
    
    <link rel="import" id="myimport" href="myimport.html" onload="loaded(event)" onerror="error(event)">`

Jan 4, 2017

Table of Content

Shadow DOM

Shadow DOM encapsulates DOM sub tree and their style. It creates a boundary, so that it maintains a separation from the main document. This avoids leaking of styles from the main DOM to shadow DOM and visa versa. Markup is also protected as they cannot be accessed through standard selectors. In past people have used iframe to achieve short of similar feature, but that comes with extra baggage as iframe is mainly designed to host separate web page. Also interaction between iframe and its host may not be straight forward.

How to Create Shadow DOM
                   var host = document.createElement('div');                   
                   var root = host.createShadowRoot();
                   root.innerHTML = "<h1>This is shadow DOM</h1>";

Terminologies

  • Light DOM - DOM which is not within shadow DOM is called Light DOM. In other words it the DOM which people refer prior to concept of shadow..
  • Logicl DOM - Together Light DOM and Shadow DOM are referred as logical DOM.
  • Shadow Host - Its the element in the Light DOM which host shadow DOM
  • shadow-root - This contains the shadow dom, and will be a child to the main DOM. Anything underneath this cannot be accessed through standard selector like this (document.querySelector('h1')),rather you have to use selector on shadow root object. All following methods are supported shadow root
    • getElementById()
    • getElementByClassName()
    • getElementByTagName()
    • getElementByTagNameNS()
    • querySelector()
    • querySelectorAll()

java script
js within shadow dom is not encapsulated. js defined in template tag will still be attached to windows object, but since markup will not be accessible across shadow boundary through standard selector, chances of accidentally impacting mark up across boundary is very less.

Content Insertion Points
Content tag provides a way through which mark up defined in the Light DOM can be distributed in Shadow DOM. You can provide selector that specify the markup which you want to distribute. You can have multiple content tag and the first content tag which match selector and is not already inserted will display it. If you create empty content tag, it will insert everything which is not already inserted. If there is no empty content tag, then only selected markup will be displayed, rest will be ignored.

Content create an insertion point. Elements inserted (which comes from Light DOM) at this insertion point is called distributed node. Distributed nodes are just displayed at the insertion point and they are not actually inserted into the Shadow DOM. Distributed node remains part of Light DOM and you can still user standard selector (document.querySelector('h1')) for distributed node, whereas selector on the root (root.querySelector('content div')) will not return anything.

Following api are provided in order to access distributed node as well as insertion point
getDistributedNode 
root.querySelector('content').getDistributedInsertionNode()

getDistributedInsertionPoints Get list of all content tag where light dom is inserted
document.querySelector('h1').getDistributedInsertionPoints()

Supported Content Selector
<content select="h1"> match all h1 element from light DOM
<content select=".myclass">
<content select=".myid">
<content select="input type=[text]">
<content select=":not(#test1)">

Shadow Insertion Points
You can create multipe shadow root for a host, but only the last one (referred as youngest) will be displayed. To include the previous shadow root, you need to include shadow tag in the displayed shadow root.

var host = document.getElementById('myshadowhost');
var root1 = host.createShadowRoot();
var root2 = host.createShadowRoot();
var root3 = host.createShadowRoot();
root1.innerHTML = '<div>Shadow DOM root1</div>';
root2.innerHTML = '<div>Shadow DOM root2</div> <shadow></shadow>'; // This will display older shadowRoot which in this case is root1
root3.innerHTML = '<div>Shadow DOM root3</div> <shadow></shadow>'; // This will display older shadowRoot which in this case is root2

You can use following methods in javascript to get hold of shadow roots
root.olderShadowRoot
host.shadowRoot will always return youngest shadowRoot

Events
Some of shadow dom events (like click) are re targeted as if they are coming from shodow host, where as some of the events (like change) are just killed at within shadow dom and is not re targeted.

Jan 3, 2017

Custom Element

Custom element give power of defining your own custom element which can be used as native html element. You can also extend existing native HTML element, which can add more features to it, based on your requirement.

Currently most of the web pages looks like this, this may not be easy to understand/maintain as div is just a generic container and which does not indicate about the item which it contains.

<div>
<div>
<div></div>
<div></div>
</div>
</div>

With the use of custom element you can transform it like this. By element's name itself its clear what it contains.

<product-item>
<product-review>
<user-avatar></user-avatar>
<user-comment></user-comment>
</product-review>
</product-item>

Registering and utilizing a custom element

  • Define a prototype for the custom element

                 var MyElementPrototype = Object.create(HTMLElement.prototype);

                 var MyButtonPrototype = Object.create(HTMLButtonElement.prototype);


  • Add callback function in which you create element


               MyElementPrototype.createdCallback = function(){
                              this.innerHTML = "<h2>My Element</h2>";
                       }

              MyButtonPrototype.createdCallback = function(){
     this.style.color='red';
     this.innerHTML = "test";
      }

  • Register the element

             var MyElement = document.registerElement('my-element',{
                                   prototype:MyElementPrototype
                     });

             var MyButtonPrototype = document.registerElement('my-button',{
                                  prototype:MyButtonPrototype,
                  extends: 'button'
     });

Instantiate Custom element

  • Markup

 <my-element/>


  • new operator

    var myElement = new MyElement();
    document.getElementById('someid').innerHTML = '<my-element/>'


  • create element

     var myElement = document.createElement('my-element');
     document.getElementById('someid').appendChild(myElement);


  • Inner HTMLElement

     document.getElementById('someid').innerHTML = '<my-element/>'

Life cycle callback

  • createdCallback - Instance is created
  • attachedCallback - Instance inserted to DOM
  • detachedCallback - Instance detached from DOM
  • attributeChangedCallback - Any attribute update