diff --git a/.jsbeautifyrc b/.jsbeautifyrc new file mode 100644 index 0000000..ce92d56 --- /dev/null +++ b/.jsbeautifyrc @@ -0,0 +1,9 @@ +{ + "end_with_newline": true, + "indent_char": " ", + "indent_size": 2, + "preserve_newlines": true, + "max_preserve_newlines": 2, + "brace_style": "collapse,preserve-inline", + "space_after_anon_function": false +} diff --git a/.vscode/settings.json b/.vscode/settings.json index f1a7e0e..b77d489 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ // Place your settings in this file to overwrite default and user settings. { "editor.tabSize": 2, - "editor.renderWhitespace": true, + "editor.renderWhitespace": "boundary", "editor.insertSpaces": true, "editor.detectIndentation": true } \ No newline at end of file diff --git a/cms/articles/1480153229/article-1480153229.component.js b/cms/articles/1480153229/article-1480153229.component.js new file mode 100644 index 0000000..6f39b75 --- /dev/null +++ b/cms/articles/1480153229/article-1480153229.component.js @@ -0,0 +1,127 @@ +import { Component } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; +import highlight from 'highlight.js'; + +import { xblogTableContentService } from 'xblog-cores/modules'; +import { resourceUtils } from 'xblog-cores/utils'; + +export var article1480153229Component = Component({ + selector: 'article', + templateUrl: './templates/article-1480153229.html', + host: { + '[class.xblog-article-1480153229]': 'true' + } +}).Class({ + constructor: [ + DomSanitizer, + xblogTableContentService, + + function(sanitizer, tableContentService) { + this.id = 1480153229; + this.sanitizer = sanitizer; + this.tableContentService = tableContentService; + } + ], + + ngOnInit: function() { + this.tableContents = this.tableContentService + .getBuilder() + .addHeadings([{ + id: 'What is Component?', + name: 'What is Component?' + }, + { + id: 'Component\'s Metadata Properties', + name: 'Component\'s Metadata Properties' + }, + { + id: 'What is Directive?', + name: 'What is Directive?' + }, + { + id: 'Directive\'s Metadata Properties', + name: 'Directive\'s Metadata Properties' + } + ]) + .addSubHeadings([{ + headingId: 'my-heading', + id: 'my-subheading', + name: 'My subheading' + }, ]) + .build(); + + this.components = { + simpleComponent: { + sourceCode: { + name: 'A Simple Component', + link: resourceUtils.getGithubArticleFileLink(this.id, 'ng-on-changes/example.component.js') + }, + codeBlocks: this.getCodeBlock(getSimpleComponent) + }, + complexComponent: { + sourceCode: { + exampleComponent: { + name: 'Component has some attributes' + } + }, + codeBlocks: this.getCodeBlock(getComplexComponent) + }, + simpleDirective: { + sourceCode: { + name: 'A Simple Directive', + link: resourceUtils.getGithubArticleFileLink(this.id, 'ng-on-changes/example.component.js') + }, + codeBlocks: this.getCodeBlock(getSimpleDirective) + }, + }; + }, + + getCodeBlock: function(getter, lang) { + var _langs = lang ? [lang] : ['javascript', 'html', 'css']; + + var _codeBlock = highlight.highlightAuto(getter().replace('', '').replace(/^ /gm, ''), _langs).value; + + return this.sanitizer.bypassSecurityTrustHtml(_codeBlock); + } +}); + +function getSimpleComponent() { + return ` + import { Component } from '@angular/core'; + + export const AppComponent = Component({ + selector: 'my-app', + template: '

My First Component

' + }) + .Class({ + constructor: function(){ } + });`; +} + +function getComplexComponent() { + return ` + import { Component } from '@angular/core'; + + export const HeroListComponent = Component({ + ... + inputs: ['hero'], + outputs: ['heroUpdated'], + styles: ['h1 { color: "red" }'] + }) + .Class({ + constructor: function(){ } + });`; +} + +function getSimpleDirective() { + return ` + import { Directive } from '@angular/core'; + + export const HightLight = Directive({ + selector: '[hightlight]', + inputs: ['color'] + }) + .Class({ + constructor: function(){ } + });`; +} diff --git a/cms/articles/1480153229/index.js b/cms/articles/1480153229/index.js new file mode 100644 index 0000000..93a138f --- /dev/null +++ b/cms/articles/1480153229/index.js @@ -0,0 +1,15 @@ +import { resourceUtils } from 'xblog-cores/utils'; +import { article1480153229Component } from './article-1480153229.component'; + +export var article1480153229 = { + id: 1480153229, + title: 'Components Directives in Angular 2', + postedDate: 'Sat Nov 26 2016 16:40:28 GMT+0700 (ICT)', + author: 'Thanh Tran', + cover: resourceUtils.getImg('xblog-home-cover.jpg'), + routeLink: resourceUtils.getArticleRouteLink('components-directives-1480153229.html'), + relatedArticles: [], + tags: [], + description: 'Angular 2 applications are made of components. A component is the combination of an HTML template and a component class that controls a portion of the screen.', + content: article1480153229Component, +}; diff --git a/cms/articles/1480153229/templates/article-1480153229.html b/cms/articles/1480153229/templates/article-1480153229.html new file mode 100644 index 0000000..b1135ef --- /dev/null +++ b/cms/articles/1480153229/templates/article-1480153229.html @@ -0,0 +1,138 @@ +

Full sources code example

+

Version: Angular 2.4

+ + + +
Table of Contents
+
+
+ +

What is Component?

+ +

In Angular 2, components are the main way we build and specify elements and logic on the page.

+ +
+ +

Components are the most basic building block of an UI in an Angular application. An Angular application is a tree of Angular components. Angular components are a subset of directives. Unlike directives, components always have a template and only one component + can be instantiated per an element in a template. A component controls a portion of the screen—a view—through its associated template.

+ +
+ +

A component must belong to an NgModule in order for it to be usable by another component or application. To specify that a component is a member of an NgModule, you should list it in the declarations field of that NgModule.

+ +
+ +

In addition to the metadata configuration specified via the Component, components can control their runtime behavior by implementing various Life-Cycle hooks.

+ +
+ + + {{components.simpleComponent.sourceCode.name}} + Full Code + + + +

+ +

We use Component to add some metadata to AppComponent:

+ + + +

Also, we have component Class that controls the appearance and behavior of a view through its template. Here, we only have the root component, AppComponent. Since we don't need any application logic in the simple example, it's empty. +

+
+ +

We export the AppComponent class so that we can import it into the application.

+ +
+ +

Note: We are using angular 2 by Javascript, so we need at least constructor function. If we don't have the logic for component, we need to create empty constructor function as above component.

+ +
+ +

Component's Metadata Properties

+ +

A component needs at least 2 metadata properties: selector and template. So, it can have a lot of metadata properties to handle logic and behavior.

+ +
+ +

Here is a component using inputs to list of class property names to data-bind as component inputs and outputs to list of class property names that expose output events that others can subscribe to.

+ +
+ + + {{components.complexComponent.sourceCode.name}} + + + +

+ +

In addition, a component has many others metadata properties:

+ + + +

What is Directive?

+ +

Directive allows you to mark a class as an Angular directive and provide additional metadata that determines how the directive should be processed, instantiated and used at runtime.

+ +
+ +

Directives allow you to attach behavior to elements in the DOM..

+ +
+ +

A directive must belong to an NgModule in order for it to be usable by another directive, component, or application. To specify that a directive is a member of an NgModule, you should list it in the declarations field of that NgModule.

+ +
+ +

In addition to the metadata configuration specified via the Directive, directives can control their runtime behavior by implementing various Life-Cycle hooks.

+ +
+ +

This is a HightLight directive to hight light a text with dynamic color.

+ +
+ + + {{components.simpleDirective.sourceCode.name}} + Full Code + + + +


+ +

Directive's Metadata Properties

+ +

The directive does not have template and style, but it has a lot of the metadata properties to handle behavior

+ + diff --git a/cms/articles/index.js b/cms/articles/index.js index e1aafe3..1221af6 100644 --- a/cms/articles/index.js +++ b/cms/articles/index.js @@ -1,7 +1,13 @@ -import { Class } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; +import { + Class +} from '@angular/core'; +import { + BrowserModule +} from '@angular/platform-browser'; -import { ngxGridModule } from 'ngx-framework/modules'; +import { + ngxGridModule +} from 'ngx-framework/modules'; import { xblogCodePanelModule, @@ -13,20 +19,24 @@ import { xblogTableContentService } from 'xblog-cores/modules'; -var _ARTICLES = []; +import { + article1480153229 +} from './1480153229'; +var _ARTICLES = [ + article1480153229 +]; export var ARTICLE_STORE = _init(); -var _ARTICLE_COMPONENTS = ARTICLE_STORE.LIST.map(function(article){ +var _ARTICLE_COMPONENTS = ARTICLE_STORE.LIST.map(function(article) { return article.content; }); - export var cmsArticlesModuleMetadata = Class({ - constructor: function cmsArticlesModuleMetadata(){ + constructor: function cmsArticlesModuleMetadata() { Object.assign(this, { - imports: [ + imports: [ BrowserModule, ngxGridModule, @@ -39,7 +49,7 @@ export var cmsArticlesModuleMetadata = Class({ xblogPostModule ], declarations: _ARTICLE_COMPONENTS, - providers: [ + providers: [ xblogTableContentService ], entryComponents: _ARTICLE_COMPONENTS, @@ -48,14 +58,13 @@ export var cmsArticlesModuleMetadata = Class({ } }); - function _init() { let _list = []; let _map = {}; _ARTICLES.forEach((article, index) => { - if(_validate(article, index)){ - if(!_map[article.id]){ + if (_validate(article, index)) { + if (!_map[article.id]) { _map[article.id] = article; _list.push(article); } @@ -64,28 +73,50 @@ function _init() { _list.sort((article1, article2) => article2.id - article1.id); - return { LIST: _list, MAP: _map }; + return { + LIST: _list, + MAP: _map + }; } function _validate(article, index) { let _message = `Article ${article.id} is missing`; try { - if(!article.id){ throw `Article is at index ${index} missing id`; } - if(!article.title){ throw `${_message} title`; } - if(!article.postedDate){ throw `${_message} postedDate`; } - if(!article.author){ throw `${_message} author`; } - if(!article.cover){ throw `${_message} cover`; } - if(!article.routeLink){ throw `${_message} routeLink`; } - if(!article.relatedArticles){ throw `${_message} relatedArticles`; } - if(!article.tags){ throw `${_message} tags`; } - if(!article.description){ throw `${_message} description`; } - if(!article.content){ throw `${_message} content`; } - } - catch(ex){ + if (!article.id) { + throw `Article is at index ${index} missing id`; + } + if (!article.title) { + throw `${_message} title`; + } + if (!article.postedDate) { + throw `${_message} postedDate`; + } + if (!article.author) { + throw `${_message} author`; + } + if (!article.cover) { + throw `${_message} cover`; + } + if (!article.routeLink) { + throw `${_message} routeLink`; + } + if (!article.relatedArticles) { + throw `${_message} relatedArticles`; + } + if (!article.tags) { + throw `${_message} tags`; + } + if (!article.description) { + throw `${_message} description`; + } + if (!article.content) { + throw `${_message} content`; + } + } catch (ex) { console.log(ex); - return false; + return false; } return true; -} \ No newline at end of file +}