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:
+
+
+ - A selector that specifies a simple CSS selector for an HTML element that represents the component.
+ - A template that tells Angular how to render the component's view.
+
+
+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:
+
+
+ - animations - list of animations of this component.
+ - changeDetection - change detection strategy used by this component.
+ - encapsulation - style encapsulation strategy used by this component.
+ - entryComponents - list of components that are dynamically inserted into the view of this component.
+ - exportAs - name under which the component instance is exported in a template.
+ - host - map of class property to host element bindings for events, properties and attributes.
+ - inputs - list of class property names to data-bind as component inputs.
+ - interpolation - custom interpolation markers used in this component's template.
+ - moduleId - ES/CommonJS module id of the file in which this component is defined.
+ - outputs - list of class property names that expose output events that others can subscribe to.
+ - providers - list of providers available to this component and its children.
+ - queries - configure queries that can be injected into the component.
+ - selector - css selector that identifies this component in a template.
+ - styleUrls - list of urls to stylesheets to be applied to this component's view.
+ - styles - inline-defined styles to be applied to this component's view.
+ - template - inline-defined template for the view.
+ - templateUrl - url to an external file containing a template for the view.
+ - viewProviders - list of providers available to this component and its view children.
+
+
+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
+
+
+ - exportAs - name under which the component instance is exported in a template.
+ - host - map of class property to host element bindings for events, properties and attributes.
+ - inputs - list of class property names to data-bind as component inputs.
+ - outputs - list of class property names that expose output events that others can subscribe to.
+ - providers - list of providers available to this component and its children.
+ - queries - configure queries that can be injected into the component.
+ - selector - css selector that identifies this component in a template.
+
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
+}