{"id":13702197,"url":"https://github.com/feimosi/frameworks-code-comparison","last_synced_at":"2025-12-27T08:12:02.789Z","repository":{"id":80586559,"uuid":"78942202","full_name":"feimosi/frameworks-code-comparison","owner":"feimosi","description":":vs: :fire: Code comparison of modern web frameworks, based on React, Angular and Vue.js","archived":false,"fork":false,"pushed_at":"2018-01-22T14:50:34.000Z","size":159,"stargazers_count":89,"open_issues_count":2,"forks_count":29,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-13T09:40:43.316Z","etag":null,"topics":["angular","angularjs","comparison","frameworks","javascript","react","vuejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/feimosi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-01-14T13:35:44.000Z","updated_at":"2024-07-11T12:00:46.000Z","dependencies_parsed_at":"2023-03-12T11:27:57.140Z","dependency_job_id":null,"html_url":"https://github.com/feimosi/frameworks-code-comparison","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feimosi%2Fframeworks-code-comparison","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feimosi%2Fframeworks-code-comparison/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feimosi%2Fframeworks-code-comparison/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feimosi%2Fframeworks-code-comparison/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/feimosi","download_url":"https://codeload.github.com/feimosi/frameworks-code-comparison/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252439435,"owners_count":21748005,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angularjs","comparison","frameworks","javascript","react","vuejs"],"created_at":"2024-08-02T21:00:32.271Z","updated_at":"2025-12-27T08:12:02.781Z","avatar_url":"https://github.com/feimosi.png","language":"JavaScript","readme":"[angular.js]: ./assets/logos/angularjs-small.svg\n[angular]: ./assets/logos/angular-small.svg\n[react]: ./assets/logos/react-small.svg\n[vue]: ./assets/logos/vue-small.svg\n\n\u003ch1 align=\"center\"\u003eFrontend Frameworks Code Comparison\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n![./assets/logos/angular.svg](./assets/logos/angular.svg)\n![./assets/logos/react.svg](./assets/logos/react.svg)\n![./assets/logos/vue.svg](./assets/logos/vue.svg)\n\n\u003c/div\u003e\n\n[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Code%20comparison%20of%20modern%20web%20frameworks%2C%20based%20on%20React%2C%20Angular%20and%20Vue.js\u0026url=https://github.com/feimosi/frameworks-code-comparison)\n\nComparison of different approaches in writing web applications. Based on React, Angular, AngularJS and Vue.js. It is especially useful when migrating between frameworks or switching projects often.\n\nAll examples follow the current best practices and conventions that are used inside the community of a given framework. Angular code is written in TypeScript.\n\n\u003ch3 align=\"center\"\u003e :warning: Work in progress! PRs and Feedback are welcome :warning: \u003c/h3\u003e\n\n\u003e Note regarding framework naming:\n\u003e - AngularJS refers to Angular v1.x\n\u003e - Angular refers to Angular v2+\n\u003e\n\u003e See: http://angularjs.blogspot.com/2017/01/branding-guidelines-for-angular-and.html\n\n\u003ch1 align=\"center\"\u003eTable of contents\u003c/h1\u003e\n\n  * [Table of contents](#table-of-contents)\n  * [Simple component](#simple-component)\n  * [Dependency injection](#dependency-injection)\n  * [Templates](#templates)\n  * [Interpolation](#interpolation)\n  * [Handling DOM Events](#handling-dom-events)\n  * [Inputs and Outputs](#inputs-and-outputs)\n  * [Default inputs](#default-inputs)\n  * [Lifecycle methods](#lifecycle-methods)\n  * [Conditional rendering](#conditional-rendering)\n  * [Lists](#lists)\n  * [Filters](#filters)\n  * [Child nodes](#child-nodes)\n  * [Transclusion and Containment](#transclusion-and-containment)\n  * [Inject HTML template](#inject-html-template)\n  * [Class toggling](#class-toggling)\n  * [Data binding](#data-binding)\n  * [Forms](#forms)\n  * [Styling](#styling)\n\n# Simple component\n\n## ![angular.js] AngularJS\n\nSince AngularJS 1.5 we have a new syntax (backported from Angular 2) to built [component-based applications](https://docs.angularjs.org/guide/component#component-based-application-architecture) using `component` type.\n\n```js\nexport class ChangePasswordController {\n  constructor($log, Auth, Notification) {\n    'ngInject';\n\n    this.$log = $log;\n    this.Auth = Auth;\n    this.Notification = Notification;\n  }\n\n  $onInit() {\n    this.password = '';\n  }\n\n  changePassword() {\n    this.Auth.changePassword(this.password).then(() =\u003e {\n      this.Notification.info('Password has been changed successfully.');\n    }).catch(error =\u003e {\n      this.$log.error(error);\n      this.Notification.error('There was an error. Please try again.');\n    });\n  }\n}\n```\n\nEvery component has to be declared inside a module. After that, it will be available to every other component.\n\n```js\nimport angular from 'angular';\nimport template from './changePassword.html';\nimport ChangePasswordController from './changePassword.controller.scss';\nimport './changePassword.scss';\n\nconst component = {\n  bindings: {},\n  template,\n  controller: ChangePasswordController,\n};\n\nexport const module = angular\n  .module('app.changePassword', [])\n  .component('changePassword', component);\n```\n\n:link: https://docs.angularjs.org/guide/component\n\n## ![angular] Angular\n\n```ts\nimport { Component } from '@angular/core';\nimport { Logger } from 'services/logger';\nimport { Auth } from 'services/auth';\nimport { Notification } from 'services/notification';\n\n@Component({\n  selector: 'change-password',\n  templateUrl: './ChangePassword.component.html',\n  styleUrls: ['./ChangePassword.component.scss'],\n})\nexport class ChangePasswordComponent {\n  password: string = '';\n\n  constructor(\n    private logger: Logger,\n    private auth: Auth,\n    private notification: Notification,\n  ) {}\n\n  changePassword() {\n    this.auth.changePassword(this.password).subscribe(() =\u003e {\n      this.notification.info('Password has been changes successfully');\n    }).catch(error =\u003e {\n      this.logger.error(error);\n      this.notification.error('There was an error. Please try again');\n    });\n  }\n}\n```\n\nEvery component has to be declared inside a module in order to be used within this module's other components (it's not available outside of).\n\n```ts\nimport { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nimport { ChangePasswordComponent } from './change-password.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [ChangePasswordComponent],\n})\nexport class ChangePasswordModule {}\n```\n\n:link: https://angular.io/api/core/Component\n\n## ![react] React\n\n```jsx\nimport Logger from 'utils/logger';\nimport Auth from 'actions/auth';\nimport Notification from 'utils/notification';\n\nexport class ChangePassword {\n  state = {\n    password: '',\n  };\n\n  changePassword() {\n    Auth.changePassword(this.state.password).then(() =\u003e {\n      Notification.info('Password has been changed successfully.');\n    }).catch(error =\u003e {\n      Logger.error(error);\n      Notification.error('There was an error. Please try again.');\n    });\n  }\n\n  render() {\n    return \u003cdiv\u003e{ /* template */ }\u003c/div\u003e;\n  }\n}\n```\n\n:link: https://reactjs.org/docs/react-component.html\n\n## ![vue] Vue.js\n\n```js\nimport Vue from 'vue';\nimport Logger from 'utils/logger';\nimport Auth from 'actions/auth';\nimport Notification from 'utils/notification';\n\nVue.component('change-password', {\n  template: '\u003cdiv\u003e{{ /* template */ }}\u003c/div\u003e',\n  data() {\n    return {\n      password: '',\n    };\n  },\n  methods: {\n    changePassword() {\n      Auth.changePassword(this.state.password).then(() =\u003e {\n        Notification.info('Password has been changed successfully.');\n      }).catch(error =\u003e {\n        Logger.error(error);\n        Notification.error('There was an error. Please try again.');\n      });\n    },\n  },\n});\n```\n\n:link: https://vuejs.org/v2/guide/components.html\n\n# Dependency injection\n\n## ![angular.js] AngularJS\n\nIn AngularJS the constructor is being used to inject dependencies, which is done implicitly by the [$inject](https://docs.angularjs.org/api/auto/service/$injector) service.\n\nThe `'ngInject'` annotation can be used, which allows automatic method annotation by the ng-annotate plugin (e.g. [ng-annotate-loader](https://www.npmjs.com/package/ng-annotate-loader) for Webpack). This is essential to counter [minification problems](https://docs.angularjs.org/guide/di#dependency-annotation).\n\n```js\nexport class ChangePasswordController {\n  constructor($log, Auth, Notification) {\n    'ngInject';\n\n    this.$log = $log;\n    this.Auth = Auth;\n    this.Notification = Notification;\n  }\n\n  handleEvent() {\n    this.Notification.info('Password changed successfully');\n    this.$log.info('Password changed successfully');\n  }\n}\n```\n\n:link: https://docs.angularjs.org/guide/di\n\n## ![angular] Angular\n\nYou specify the definition of the dependencies in the constructor (leveraging TypeScript's constructor syntax for declaring parameters and properties simultaneously).\n\n```ts\nimport { Component } from '@angular/core';\nimport { Logger } from 'services/logger';\nimport { Auth } from 'services/auth';\nimport { Notification } from 'services/notification';\n\n@Component({\n  selector: 'change-password',\n  templateUrl: './ChangePassword.component.html',\n})\nexport class ChangePasswordComponent {\n  constructor(\n    private logger: Logger,\n    private auth: Auth,\n    private notification: Notification,\n  ) {}\n\n  handleEvent() {\n    this.notification.info('Password changed successfully');\n    this.logger.info('Password changed successfully');\n  }\n}\n```\n\n:link: https://angular.io/guide/dependency-injection\n\n## ![react] React\n\nThere's no special injection mechanism. ES2015 modules are used for dependency management.\n\n```jsx\nimport React, { Component } from 'react';\nimport Logger from 'utils/logger';\nimport Notification from 'utils/notification';\n\nexport class ChangePassword extends Component {\n  handleEvent = () =\u003e {\n    Notification.info('Password changed successfully');\n    Logger.info('Password changed successfully');\n  }\n\n  render() {\n    return \u003cdiv\u003e{ /* template */ }\u003c/div\u003e;\n  }\n}\n```\n\n## ![vue] Vue.js\n\nVue.js uses ES2015 modules for dependency management:\n\n```js\nimport Vue from 'vue';\nimport Logger from 'utils/logger';\nimport Notification from 'utils/notification';\n\nVue.component('change-password', {\n  template: '\u003cdiv\u003e{{ /* template */ }}\u003c/div\u003e',\n  methods: {\n    handleEvent() {\n      Notification.info('Password changed successfully');\n      Logger.info('Password changed successfully');\n    },\n  },\n});\n```\n\nThere's also [provide and inject](https://vuejs.org/v2/api/#provide-inject) mechanism which is primarily provided for advanced plugin / component library use cases:\n\nParent component:\n```js\nimport Notification from 'utils/notification';\nimport Vue from 'vue';\n\nnew Vue({\n  el: '#app',\n  provide: {\n    notification: Notification,\n  },\n});\n```\n\nChild component:\n```js\nimport Vue from 'vue';\n\nVue.component('change-password', {\n  inject: ['notification'],\n  template: '\u003cdiv\u003e{{ /* template */ }}\u003c/div\u003e',\n  methods: {\n    handleEvent() {\n      this.notification.info('Event handled successfully');\n    },\n  },\n});\n```\n\n# Templates\n\n## ![angular.js] AngularJS\n\nTemplates in AngularJS are compiled by the [$compile](https://docs.angularjs.org/api/ng/service/$compile) service.\nValues of component properties must be one of the following:\n- string binding (defined as `@`)\n- expression binding (defined as `\u003c`)\n- reference binding (defined as `\u0026`)\n\n```html\n\u003cprimary-button size=\"big\"\n                disabled=\"true\"\n                click=\"$ctrl.saveContent()\"\u003e\n  Save\n\u003c/primary-button\u003e\n```\n\n## ![angular] Angular\n\nThere are three kinds of attributes that can be passed:\n- text binding, e.g. `size=\"string\"`\n- property binding, e.g. `[disabled]=\"value\"`\n- event binding, e.g. `(click)=\"eventHandler()\"`\n\n```html\n\u003cprimary-button size=\"big\"\n                [disabled]=\"true\"\n                (click)=\"saveContent()\"\u003e\n  Save\n\u003c/primary-button\u003e\n```\n\n## ![react] React\n\nTemplates in React are written inside the JavaScript file using the [JSX language](https://reactjs.org/docs/jsx-in-depth.html). This allows us to utilize all JavaScript capabilities. JSX uses the uppercase and lowercase convention to distinguish between the user-defined components and DOM elements.\n\n```jsx\n\u003cPrimaryButton\n  size=\"big\"\n  disabled\n  onClick={ this.saveContent }\n\u003e\n  Save\n\u003c/PrimaryButton\u003e;\n```\n\n## ![vue] Vue.js\n\nComponent properties can be passed in as:\n- literal (as strings) e.g. `size=\"big\"`\n- dynamic (using [v-bind](https://vuejs.org/v2/api/#v-bind) or [`:shorthand`](https://vuejs.org/v2/guide/syntax.html#v-bind-Shorthand) with actual values) e.g. `v-bind:disabled=\"true\"`\n\nEvents can be listened to using [`v-on`](https://vuejs.org/v2/guide/events.html#Method-Event-Handlers) or [`@shorthand`](https://vuejs.org/v2/guide/syntax.html#v-on-Shorthand) combined with the event name, and a method name as the value, e.g `v-on:click=\"saveContent\"`.\n\n```html\n\u003cprimary-button\n  size=\"big\"\n  v-bind:disabled=\"true\"\n  v-on:click=\"saveContent\"\n\u003e\n    Save\n\u003c/primary-button\u003e\n```\n\n:link: https://vuejs.org/v2/guide/syntax.html\n\n# Interpolation\n\n## ![angular.js] AngularJS\n\nIn AngularJS interpolation is the process of data-binding values of the `scope` to the HTML. You can also interpolate more complicated values e.g. expressions or function invocations.\n\n\n```html\n\u003cimg ng-src=\"{{ $ctrl.image.url }}\" alt=\"{{ $ctrl.image.alt }}\" /\u003e\n```\n\nWe use [`ng-src`](https://docs.angularjs.org/api/ng/directive/ngSrc) instead of the regular `src` attribute so that AngularJS can set it up before the browser will try to load the image.\n\nAnother way to \"bind\" data is to use [`ng-bind`](https://docs.angularjs.org/api/ng/directive/ngBind). This allows us to counter the issue with a raw state being displayed before AngularJS compiles the template.\n\n```html\n\u003clabel\u003e\n    Enter name:\n    \u003cinput type=\"text\" ng-model=\"$ctrl.name\"\u003e\n\u003c/label\u003e\n\u003cspan ng-bind=\"$ctrl.name\"\u003e\u003c/span\u003e\n```\n\n:link: https://docs.angularjs.org/guide/interpolation\n\n## ![angular] Angular\n\nAngular is similar to AngularJS, so we use double curly braces (`{{ }}`) for interpolation. Since Angular offers property binding you often have a choice to use it [instead of interpolation](https://angular.io/guide/template-syntax#property-binding-or-interpolation).\n\n```html\n\u003cimg [src]=\"image.url\" alt=\"{{ image.alt }}\" /\u003e\n```\n\n`[src]` presents property binding while the `alt` attribute is being interpolated.\n\n:link: https://angular.io/guide/template-syntax#interpolation\n\n## ![react] React\n\nReact uses single curly braces for interpolation. Any JavaScript can be interpolated.\n\n```jsx\n\u003cimg src={ this.props.image.url } alt={ this.props.image.alt } /\u003e;\n```\n\n:link: https://reactjs.org/docs/introducing-jsx.html#embedding-expressions-in-jsx\n\n## ![vue] Vue.js\n\n```html\n\u003cimg :src=\"image.url\" alt=\"{{ image.alt }}\" /\u003e\n```\n\nYou can also perform one-time interpolations that do not update on data change by using the [v-once](https://vuejs.org/v2/api/#v-once) directive,\n\n```html\n\u003cspan v-once\u003eHello {{ username }}!\u003c/span\u003e\n```\n\n:link: https://vuejs.org/v2/guide/syntax.html#Interpolations\n\n# Handling DOM Events\n\n## ![angular.js] AngularJS\n\nHandlers of native events are bound using provided [built-in directives](https://docs.angularjs.org/api/ng/directive) e.g.\n[`ng-click`](https://docs.angularjs.org/api/ng/directive/ngClick), [`ng-focus`](https://docs.angularjs.org/api/ng/directive/ngFocus), [`ng-keypress`](https://docs.angularjs.org/api/ng/directive/ngKeypress).\n\n```js\nclass MenuTopbarController {\n  $onInit() {\n    this.selected = null;\n  }\n\n  handleClick(item) {\n    if (this.selected !== item) {\n      this.selected = item;\n      if (typeof item.callback === 'function') {\n        item.callback();\n      }\n    }\n  }\n}\n\nconst menuTopbar = {\n  bindings: {\n    items: '\u003c',\n  },\n  template: require('./menuTopbar.html'),\n  controller: MenuTopbarController,\n};\n\nangular.module('app')\n  .component('menuTopbar', menuTopbar);\n```\n\n```html\n\u003cul\u003e\n  \u003cli ng-repeat=\"item in $ctrl.items\"\n      ng-click=\"$ctrl.handleClick(item)\"\u003e\n    {{ item.label }}\n  \u003c/li\u003e\n\u003c/ul\u003e\n```\n\n:link: https://docs.angularjs.org/tutorial/step_12\n\n## ![angular] Angular\n\nThere's a special syntax for binding to element's events with `()`. The target inside the `()` is an event we want to listen for.\n\n```ts\nexport interface MenuItem {\n  label: string;\n  callback?: Function;\n}\n```\n\n```ts\nimport { Component, Input, Output, EventEmitter } from '@angular/core';\nimport { MenuItem } from './menu-item.interface';\n\n@Component({\n  selector: 'menu-topbar',\n  template: require('./menuTopbar.html'),\n})\nexport class MenuTopbarComponent {\n  private selected = null;\n  @Input() items: MenuItem[];\n\n  handleClick(item: MenuItem) {\n    if (this.selected !== item) {\n      this.selected = item;\n      if (item.callback) {\n        item.callback();\n      }\n    }\n  }\n}\n```\n\n```html\n\u003cul\u003e\n  \u003cli *ngFor=\"let item of items\"\n      (click)=\"handleClick(item)\"\u003e\n    {{ item.label }}\n  \u003c/li\u003e\n\u003c/ul\u003e\n```\n\nTo bind to component's host element events, you can use [`HostListener`](https://angular.io/api/core/HostListener) decorator.\n\n```ts\n@Component({\n  selector: 'menu-topbar',\n  template: require('./menuTopbar.html'),\n})\nexport class MenuTopbarComponent {\n  @HostListener('mouseenter') onMouseEnter() {\n    this.highlight('#DDD');\n  }\n  \n  @HostListener('mouseleave') onMouseLeave() {\n    this.highlight(null);\n  }\n\n  private highlight(color) {\n    /* ... */\n  }\n```\n\n## ![react] React\n\nHandling events with React elements is very similar to handling events on DOM elements. There are two syntactic differences though.\n\n- React events are named using camelCase, rather than lowercase e.g. (onClick, onFocus, onKeyPress).\n- With JSX you pass a function as the event handler, rather than a string.\n\nYour event handlers will be passed instances of [`SyntheticEvent`](https://reactjs.org/docs/events.html), a cross-browser wrapper around the browser’s native event. It has the same interface as the browser’s native event, including [`stopPropagation()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation) and [`preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault), except the events work identically across all browsers.\n\n```jsx\nimport React, { Component } from 'react';\n\nexport class MenuTopbar extends Component {\n  state = {\n    selected: null,\n  };\n\n  handleClick(item) {\n    if (this.selected !== item) {\n      this.setState({ selected: item });\n      if (item.callback) {\n        item.callback();\n      }\n    }\n  }\n\n  render() {\n    return (\n      \u003cul\u003e\n        { this.props.items.map(item =\u003e (\n          \u003cli\n            key={ item.label }\n            onClick={ () =\u003e this.handleClick(item) }\n          \u003e\n            { item.label }\n          \u003c/li\u003e\n        ))\n        }\n      \u003c/ul\u003e\n    );\n  }\n}\n```\n\n:link: https://reactjs.org/docs/handling-events.html\n\n## ![vue] Vue.js\n\nWe can use the v-on directive (or `@` shorthand) to listen to DOM events and run some JavaScript when they’re triggered.\n\nVue also provides event modifiers (directive postfixes denoted by a dot).\n\n- `.stop` - stopPropagation\n- `.prevent` - preventDefault\n- `.capture` - use capture mode\n- `.self` - only trigger handler if event.target is the element itself\n- `.once` - the event will be triggered at most once\n\n```js\nVue.component('menu-topbar', {\n  data: {\n    selected: null,\n  },\n  methods: {\n    handleClick: (item) =\u003e {\n      if (this.selected !== item) {\n        this.selected = item;\n        if (item.callback) {\n          item.callback();\n        }\n      }\n    },\n  },\n});\n```\n\n```html\n\u003cul\u003e\n  \u003cli \n    v-for=\"item in items\" \n    :key=\"item.label\"\n    @click=\"handleClick(item)\"\n  \u003e\n    {{ item.label }}\n  \u003c/li\u003e\n\u003c/ul\u003e\n```\n\n:link: https://vuejs.org/v2/guide/events.html\n\n# Inputs and Outputs\n\n## ![angular.js] AngularJS\n\nInputs are defined by either `@` (string binding) or `\u003c` (one-way binding) while outputs are defined by the `\u0026` symbol. Passing arguments requires you to use an object in a child component which is then mapped to function parameters defined in the template.\n\n```js\nclass UserPreviewComponent {\n  $onInit() {\n    this.editedUser = {\n      name: this.user.name,\n      email: this.user.email,\n    };\n  }\n\n  submitEdit() {\n    this.onEdit({ user: this.editedUser });\n  }\n}\n\nconst component = {\n  bindings: {\n    user: '\u003c',\n    onEdit: '\u0026',\n  },\n  template: require('./userPreview.html'),\n  controller: UserPreviewComponent,\n};\n\nexport default angular.module.component('userPreview', component);\n```\n\n```html\n\u003cform ng-submit=\"$ctrl.submitEdit()\"\u003e\n  \u003cinput type=\"text\" ng-model=\"$ctrl.editedUser.name\"\u003e\n  \u003cinput type=\"email\" ng-model=\"$ctrl.editedUser.email\"\u003e\n  \u003cinput type=\"submit\" value=\"Submit\" /\u003e\n\u003c/form\u003e\n```\n\nIn a parent component:\n\n```js\nclass SettingsComponent {\n  user = {\n    name: 'John Smith',\n    email: 'john.smith@example.com',\n  };\n\n  editUser(user) {\n    this.user = Object.assign({}, this.user, user);\n    console.log('Name of the edited user is', user.name);\n  }\n}\n\nconst component = {\n  template: require('./settings.html'),\n  controller: SettingsComponent,\n};\n\nexport default angular.module.component('settings', component);\n```\n\n```html\n\u003cuser-preview user=\"user\"\n              on-edit=\"editUser(user)\"\u003e\n\u003c/user-preview\u003e\n```\n\n## ![angular] Angular\n\nInputs are defined using the [@Input](https://angular.io/api/core/Input) decorator while outputs using the [@Output](https://angular.io/api/core/Output) decorator.\n\n```ts\n@Component({\n  selector: 'user-preview',\n  template: require('./userPreview.html'),\n})\nexport class UserPreviewComponent {\n  private editedUser: User;\n  @Input() user: User;\n  @Output() onEdit: EventEmitter = new EventEmitter\u003cUser\u003e();\n\n  ngOnInit() {\n    this.editedUser = {\n      name: this.user.name,\n      email: this.user.email,\n    };\n  }\n\n  submitEdit() {\n    this.onEdit.emit(this.editedUser);\n  }\n}\n```\n\n```html\n\u003cform (ngSubmit)=\"submitEdit()\"\u003e\n  \u003cinput type=\"text\" [(ngModel)]=\"editedUser.name\"\u003e\n  \u003cinput type=\"text\" [(ngModel)]=\"editedUser.email\"\u003e\n  \u003cinput type=\"submit\" value=\"Submit\" /\u003e\n\u003c/form\u003e\n```\n\nIn a parent component:\n\n```ts\n@Component({\n  selector: 'settings',\n  template: require('./settings.html'),\n})\nexport class SettingsComponent {\n  user: User = {\n    name: 'John Smith',\n    email: 'john.smith@example.com',\n  };\n\n  editUser(user: User) {\n    this.user = Object.assign({}, this.user, user);\n    console.log('User has been edited: ', user);\n  }\n}\n```\n\n```html\n\u003cuser-preview [user]=\"user\"\n              (onEdit)=\"editUser($event)\"\n\u003e\u003c/user-preview\u003e\n```\n\n:link: https://angular.io/guide/component-interaction\n\n## ![react] React\n\n```jsx\nimport React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { User } from 'utils';\n\nclass UserPreviewComponent extends Component {\n  submitEdit = () =\u003e {\n    this.props.onEdit({\n      name: this.state.name,\n      email: this.state.email,\n    });\n  };\n\n  handleInputChange({ target }) {\n    this.setState({\n      [target.name]: target.value,\n    });\n  }\n\n  render() {\n    return (\n      \u003cform onSubmit={ this.submitEdit }\u003e\n        \u003cinput\n          type=\"text\"\n          name=\"name\"\n          value={ this.state.name }\n          onChange={ this.handleInputChange }\n        /\u003e\n        \u003cinput\n          type=\"email\"\n          name=\"email\"\n          value={ this.state.email }\n          onChange={ this.handleInputChange }\n        /\u003e\n        \u003cinput type=\"submit\" value=\"Submit\" /\u003e\n      \u003c/form\u003e\n    );\n  }\n}\n\nUserPreviewComponent.propTypes = {\n  user: PropTypes.instanceOf(User),\n  onEdit: PropTypes.func,\n};\n```\n\nIn a parent component:\n\n```jsx\nimport React, { Component } from 'react';\nimport { User } from 'utils';\n\nexport class SettingsComponent extends Component {\n  state = {\n    user: {\n      name: 'John Smith',\n      email: 'john.smith@example.com',\n    },\n  };\n\n  editUser(user: User){\n    this.setState({\n      user: Object.assign({}, this.state.user, user),\n    });\n    console.log('User has been edited: ', user);\n  }\n\n  render() {\n    return (\n      \u003cUserPreviewComponent\n        user={ this.state.user }\n        onEdit={ (user) =\u003e this.editUser(user) }\n      /\u003e\n    );\n  }\n}\n```\n\n## ![vue] Vue.js\n\nChild component:\n\n```js\nVue.component('child', {\n  props: {\n    class: {\n      type: String,\n      required: true,\n    },\n    loading: Boolean,\n    message: String,\n  },\n  template: '\u003cspan v-bind:class=\"class\" v-show=\"loading\" v-text=\"message\"\u003e\u003c/span\u003e',\n});\n```\n\nUsage in the parent component:\n\n```html\n\u003cchild class=\"small\" :loading=\"true\" message=\"Busy Loading!\"\u003e\u003c/child\u003e\n```\n\n:link: https://vuejs.org/v2/guide/components.html#Props\n\n# Default inputs\n\n## ![angular.js] AngularJS\n\nThere's no built-in mechanism for default inputs, so we assign them programmatically in the `$onChanges` hook.\n\n```js\nclass CoursesListController {\n  $onChanges(bindings) {\n    if (typeof bindings.displayPurchased.currentValue === 'undefined') {\n      this.displayPurchased = true;\n    }\n    if (typeof bindings.displayAvailable.currentValue === 'undefined') {\n      this.displayAvailable = true;\n    }\n  }\n}\n\nconst component = {\n  bindings: {\n    displayPurchased: '\u003c',\n    displayAvailable: '\u003c',\n  },\n  templateUrl: './coursesList.component.html',\n  controller: CoursesListController,\n};\n\nexport default component;\n```\n\n## ![angular] Angular\n\n```ts\nimport { Component } from '@angular/core';\n\n@Component({\n  selector: 'courses-list',\n  templateUrl: './coursesList.component.html',\n})\nexport class CoursesListController {\n  displayPurchased: boolean = true;\n  displayAvailable: boolean = true;\n}\n```\n\n## ![react] React\n\n```jsx\nimport React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nexport class CoursesListController extends { Component } {\n  static propTypes = {\n    displayPurchased: PropTypes.bool,\n    displayAvailable: PropTypes.bool,\n  };\n\n  static defaultProps = {\n    displayPurchased: true,\n    displayAvailable: true,\n  };\n\n  render() {\n    return \u003cdiv\u003e{ /* template */ }\u003c/div\u003e;\n  }\n}\n```\n\n:link: https://reactjs.org/docs/typechecking-with-proptypes.html#default-prop-values\n\n## ![vue] Vue.js\n\n```js\nimport Vue from 'vue';\n\nVue.component('courses-list', {\n  template: '\u003cdiv\u003e{{ /* template */ }}\u003c/div\u003e',\n  props: {\n    displayPurchased: {\n      type: Boolean,\n      default: true,\n    },\n    displayAvailable: {\n      type: Boolean,\n      default: true,\n    },\n  },\n});\n```\n\n# Lifecycle methods\n\n## ![angular.js] AngularJS\n\n#### `$onInit()` \n\nCalled when the component has been constructed and has its bindings have been initialized.\n\n#### `$postLink()` \n\nCalled after the component and its children have been linked (mounted).\n\n#### `$onChanges(changes)`\n\nCalled whenever one-way bindings are updated.\n\n#### `$doCheck()`\n\nCalled on each turn of the digest cycle.\n\n#### `$onDestroy()`\n\nCalled when the component (a controller with its containing scope) is being destroyed.\n\n:link: https://docs.angularjs.org/api/ng/service/$compile\n\n### ![angular] Angular\n\n#### [`ngOnChanges()`](https://angular.io/guide/lifecycle-hooks#onchanges)\n\nRespond when Angular (re)sets data-bound input properties. The method receives a `SimpleChanges` object of current and previous property values.\n\nCalled before `ngOnInit()` and whenever one or more data-bound input properties change.\n\n```ts\nexport class PeekABooComponent extends PeekABoo implements OnChanges {\n  // only called for/if there is an @input variable set by parent.\n  ngOnChanges(changes: SimpleChanges) {\n    let changesMsgs: string[] = [];\n    for (let propName in changes) {\n      if (propName === 'name') {\n        let name = changes['name'].currentValue;\n        changesMsgs.push(`name ${this.verb} to \"${name}\"`);\n      } else {\n        changesMsgs.push(propName + ' ' + this.verb);\n      }\n    }\n    this.logIt(`OnChanges: ${changesMsgs.join('; ')}`);\n    this.verb = 'changed'; // next time it will be a change\n  } \n}\n```\n\n#### [`ngOnInit()`](https://angular.io/guide/lifecycle-hooks#oninit)\n\nInitialize the directive/component after Angular first displays the data-bound properties and sets the directive/component's input properties.\n\nCalled once, after the first `ngOnChanges()`.\n\n```ts\nexport class PeekABoo implements OnInit {\n  constructor(private logger: LoggerService) { }\n\n  // implement OnInit's `ngOnInit` method\n  ngOnInit() { this.logIt(`OnInit`); }\n\n  logIt(msg: string) {\n    this.logger.log(`#${nextId++} ${msg}`);\n  }\n}\n```\n\n#### [`ngDoCheck()`](https://angular.io/guide/lifecycle-hooks#docheck)\n\nDetect and act upon changes that Angular can't or won't detect on its own.\n\nCalled during every change detection run, immediately after `ngOnChanges()` and `ngOnInit()`.\n\n```ts\nexport class PeekABooComponent extends PeekABoo implements DoCheck {\n  ngDoCheck() { \n    this.logIt(`DoCheck`);\n  }\n}\n```\n\n#### [`ngAfterContentInit()`](https://angular.io/guide/lifecycle-hooks#aftercontent-hooks)\n\nRespond after Angular projects external content into the component's view.\nCalled once after the first `ngDoCheck()`.\n\n```ts\nexport class PeekABooComponent extends PeekABoo implements AfterContentInit {\n  ngAfterContentInit() { this.logIt(`AfterContentInit`);  }\n}\n```\n\n#### [`ngAfterContentChecked()`](https://angular.io/guide/lifecycle-hooks#aftercontent-hooks)\n\nRespond after Angular checks the content projected into the component.\n\nCalled after the `ngAfterContentInit()` and every subsequent `ngDoCheck()`\n\n```ts\nexport class PeekABooComponent extends PeekABoo implements AfterContentChecked {\n  // Beware! Called frequently!\n  // Called in every change detection cycle anywhere on the page\n  ngAfterContentChecked() { this.logIt(`AfterContentChecked`); }\n}\n```\n\n#### [`ngAfterViewInit()`](https://angular.io/guide/lifecycle-hooks#afterview)\n\nRespond after Angular initializes the component's views and child views.\n\nCalled once after the first `ngAfterContentChecked()`.\n\n```ts\nexport class AfterViewComponent implements  AfterViewChecked, AfterViewInit {  \n  ngAfterViewInit() {\n    // viewChild is set after the view has been initialized\n    this.logIt('AfterViewInit');\n    this.doSomething();\n  }\n}\n```\n\n#### [`ngAfterViewChecked()`](https://angular.io/guide/lifecycle-hooks#afterview)\n\nRespond after Angular checks the component's views and child views.\n\nCalled after the `ngAfterViewInit` and every subsequent `ngAfterContentChecked()`\n\n```ts\nexport class AfterViewComponent implements  AfterViewChecked, AfterViewInit \n  ngAfterViewChecked() {\n    // viewChild is updated after the view has been checked\n    if (this.prevHero === this.viewChild.hero) {\n      this.logIt('AfterViewChecked (no change)');\n    } else {\n      this.prevHero = this.viewChild.hero;\n      this.logIt('AfterViewChecked');\n      this.doSomething();\n    }\n  }\n}\n```\n\n#### [`ngOnDestroy()`](https://angular.io/guide/lifecycle-hooks#ondestroy)\n\nCleanup just before Angular destroys the directive/component. Unsubscribe Observables and detach event handlers to avoid memory leaks.\n\nCalled just before Angular destroys the directive/component.\n\n```ts\n@Directive({\n    selector: '[destroyDirective]'\n})\n\nexport class OnDestroyDirective implements OnDestroy {\n  sayHello: number;\n  constructor() {\n    this.sayHiya = window.setInterval(() =\u003e console.log('hello'),     1000);\n  }\n  ngOnDestroy() {\n     window.clearInterval(this.sayHiya);\n  }\n}\n```\n\n## ![react] React\n\n#### [`componentWillMount()`](https://reactjs.org/docs/react-component.html#componentwillmount) \n\nIs invoked just before rendering. Modifying the state here won't trigger a re-render.\n\n#### [`componentDidMount()`](https://reactjs.org/docs/react-component.html#componentdidmount) \n\nIs invoked after render. Useful for the initialization that require DOM nodes.\n\n#### [`componentWillReceiveProps(nextProps)`](https://reactjs.org/docs/react-component.html#componentwillreceiveprops) \n\nIs only called after rendering, but before receiving new props. Because React may call this method without props changing, it is recommended to manually implement a check to see if there's a difference.\n\n#### [`shouldComponentUpdate(nextProps, nextState)`](https://reactjs.org/docs/react-component.html#shouldcomponentupdate) \n\nThis method is called before receiving new props or a change of state. By default, it returns true which means re-rendering is triggered by any change. Modifying this method allows you to only re-render in intended scenarios.\n\n#### [`componentWillUpdate(nextProps, nextState)`](https://reactjs.org/docs/react-component.html#componentwillupdate) \n\nIs invoked whenever `shouldComponentUpdate` returns true before rendering. Note: You can't use `this.setState()` here.\n\n#### [`componentDidUpdate(prevProps, prevState)`](https://reactjs.org/docs/react-component.html#componentdidupdate) \n\nIs invoked after rendering, but not after the initial render. This method is useful for manipulating the DOM when updated.\n\n#### [`componentWillUnmount()`](https://reactjs.org/docs/react-component.html#componentwillunmount) \n\nIs invoked immediately before a component is unmounted and destroyed. Useful for resource cleanup.\n\n#### [`componentDidCatch(error,info)`](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html) \n\nIs invoked when Javascript throws an error anywhere in the component's tree. Useful for catching errors, showing a fallback interface, and logging errors without breaking the entire application.\n\n## ![vue] Vue.js\n\n#### [`beforeCreate`](https://vuejs.org/v2/api/#beforeCreate)\n\nCalled synchronously immediately after the instance has been initialized, but before data observation and event/watcher setup. On every Vue instance lifecycle, `this` points to the vm instance itself.\n\n```javascript\nnew Vue({\n  beforeCreate: function () {\n    console.log('this method called before instance created')\n  }\n})\n```\n\n#### [`created`](https://vuejs.org/v2/api/#created)\n\nCalled synchronously after the instance is created. At this stage, the instance has finished processing the options, which means the following have been set up: data observation, computed properties, methods, watch/event callbacks. However, the mounting phase has not been started, and the `$el` property will not be available yet.\n\n```javascript\nnew Vue({\n  created: function () {\n    console.log('this method called after instance created')\n  }\n})\n```\n\n#### [`beforeMount`](https://vuejs.org/v2/api/#beforeMount)\n\nCalled right before the mounting begins: the render function is about to be called for the first time.\n\n_This hook is not called during server-side rendering._\n\n```javascript\nnew Vue({\n  beforeMount: function () {\n    console.log('this method called before mounting an instance')\n  }\n})\n```\n\n#### [`mounted`](https://vuejs.org/v2/api/#mounted)\n\nCalled after the instance has been mounted, where [el](https://vuejs.org/v2/api/#el) is replaced by the newly created `vm.$el`. If the root instance is mounted to an in-document element, `vm.$el` will also be in-document when `mounted` is called.\n\nNote that `mounted` does not guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use [vm.$nextTick](https://vuejs.org/v2/api/#Vue-nextTick) inside of mounted:\n\n```javascript\nnew Vue({\n  mounted: function () {\n    this.$nextTick(function () {\n      // Code that will run only after the\n      // entire view has been rendered\n    })\n  }\n})\n```\n\n#### [`beforeUpdate`](https://vuejs.org/v2/api/#beforeUpdate)\n\nCalled whenever the data changes, before the virtual DOM is re-rendered and patched.\n\nYou can perform further state changes in this hook and they will not trigger additional re-renders.\n\n_This hook is not called during server-side rendering._\n\n#### [`updated`](https://vuejs.org/v2/api/#updated)\n\nCalled after a data change causes the virtual DOM to be re-rendered and patched.\n\nThe component’s DOM will have been updated when this hook is called, so you can perform DOM-dependent operations here. However, in most cases you should avoid changing state inside the hook.\n\nNote that `updated` does not guarantee that all child components have also been re-rendered. If you want to wait until the entire view has been re-rendered, you can use [vm.$nextTick](https://vuejs.org/v2/api/#Vue-nextTick) inside of `updated`:\n\n```javascript\nupdated: function () {\n  this.$nextTick(function () {\n    // Code that will run only after the\n    // entire view has been re-rendered\n  })\n}\n```\n\n#### [`activated`](https://vuejs.org/v2/api/#activated)\n\nCalled when a kept-alive component is activated.\n\n_This hook is not called during server-side rendering._\n\n#### [`deactivated`](https://vuejs.org/v2/api/#deactivated)\n\nCalled when a kept-alive component is deactivated.\n\n_This hook is not called during server-side rendering._\n\n#### [`beforeDestroy`](https://vuejs.org/v2/api/#beforeDestroy)\n\nCalled right before a Vue instance is destroyed. At this stage the instance is still fully functional.\n\n_This hook is not called during server-side rendering._\n\n#### [`destroyed`](https://vuejs.org/v2/api/#destroyed)\n\nCalled after a Vue instance has been destroyed. When this hook is called, all directives of the Vue instance have been unbound, all event listeners have been removed, and all child Vue instances have also been destroyed.\n\n_This hook is not called during server-side rendering._\n\n\n#### [`errorCaptured`](https://vuejs.org/v2/api/#errorCaptured)\n\nCalled when an error from any descendent component is captured.\n\n# Conditional rendering\n\n## ![angular.js] AngularJS\n\nAngularjs 1.x has three ways to perform conditional rendering: `ng-if`, `ng-switch` and `ng-hide/ng-show`.\n\n```js\nexport class RegistrationController {\n  registrationCompleted = false;\n  displaySpecialOffer = false;\n  displayStatus = 'Registered';\n}\n```\n```html\n\u003cdiv ng-if=\"displaySpecialOffer\"\u003e\n  \u003cspecial-offer\u003e\u003c/special-offer\u003e\n\u003c/div\u003e\n\n\u003cdiv ng-switch=\"displayStatus\"\u003e\n  \u003cdiv ng-switch-when=\"Registered\"\u003e\n     \u003cregistration-completed\u003e\u003c/registration-completed\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\n\u003cdiv ng-show=\"displaySpecialOffer\"\u003e\n  \u003cspecial-offer\u003e\u003c/special-offer\u003e\n\u003c/div\u003e\n\u003cdiv ng-hide=\"displaySpecialOffer\"\u003e\n  \u003cspecial-offer\u003e\u003c/special-offer\u003e\n\u003c/div\u003e\n```\n\n## ![angular] Angular\n\nSince Angular 4.0.0, alongside standard `ngIf`, it is possible to use `ngIf;else` or `ngIf;then;else` using `\u003cng-template\u003e` with an alias `#aliasName`.\n\n```ts\nimport { Component } from '@angular/core';\n\n@Component({\n  selector: 'registration',\n  template: '',\n})\nexport class RegistrationComponent {\n  registrationCompleted: boolean = false;\n  displaySpecialOffer: boolean = false;\n}\n```\n\n```html\n\u003cdiv *ngIf=\"displaySpecialOffer\"\u003e\n  \u003cspecial-offer\u003e\u003c/special-offer\u003e\n\u003c/div\u003e\n\n\u003cdiv *ngIf=\"registrationCompleted;else registrationForm\"\u003e\n  \u003cregistration-completed\u003e\u003c/registration-completed\u003e\n\u003c/div\u003e\n\n\u003cng-template #registrationForm\u003e\n  \u003cregistration-form\u003e\u003c/registration-form\u003e\n\u003c/ng-template\u003e\n```\n\n:link: https://angular.io/api/common/NgIf\n\n## ![react] React\n\nThe most common approach to conditional rendering is by using the ternary operator:\n`{ condition ? \u003cComponent /\u003e : null }`\n\n```jsx\nimport React, { Component } from 'react';\nimport PropTypes from 'prop-types';\n\nexport class Registration extends Component {\n  state = {\n    registrationCompleted: false,\n  };\n\n  propTypes = {\n    displaySpecialOffer: PropTypes.bool,\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        { this.props.displaySpecialOffer ? \u003cSpecialOffer /\u003e : null }\n\n        { this.state.registrationCompleted ? (\n          \u003cRegistrationCompleted /\u003e\n        ) : (\n          \u003cRegistrationForm /\u003e\n        ) }\n      \u003c/div\u003e\n    );\n  }\n}\n```\n\n## ![vue] Vue.js\n\nVue.js has three directives to perform conditional rendering: `v-if`, `v-else-if` and `v-else`.\n\n```html\n\u003ctemplate\u003e\n  \u003csection v-if=\"registrationCompleted \u0026\u0026 !displaySpecialOffer\"\u003e\n    \u003cregistration-completed /\u003e\n  \u003c/section\u003e\n  \u003csection v-else-if=\"registrationCompleted \u0026\u0026 displaySpecialOffer\"\u003e\n    \u003cspecial-offer /\u003e\n    \u003cregistration-completed /\u003e\n  \u003c/section\u003e\n  \u003csection v-else\u003e\n    \u003cregistration-form /\u003e\n  \u003c/section\u003e\n\u003c/template\u003e\n```\n\n:link: https://vuejs.org/v2/guide/conditional.html\n\n# Lists\n\n## ![angular.js] AngularJS\n\n[ngRepeat](https://docs.angularjs.org/api/ng/directive/ngRepeat)\n\n```js\nexport class BookListComponentCtrl {\n  constructor() {\n    this.books = [\n      {\n        id: 1,\n        title: 'Eloquent JavaScript',\n        author: 'Marijn Haverbeke',\n      },\n      {\n        id: 2,\n        title: 'JavaScript: The Good Parts',\n        author: 'Douglas Crockford',\n      },\n      {\n        id: 3,\n        title: 'JavaScript: The Definitive Guide',\n        author: 'David Flanagan',\n      },\n    ];\n  }\n}\n```\n\n```html\n\u003cul\u003e\n  \u003cli ng-repeat=\"book in $ctrl.books track by book.id\"\u003e\n    {{ book.title }} by {{ book.author }}\n  \u003c/li\u003e\n\u003c/ul\u003e\n```\n\n## ![angular] Angular\n\n[ngFor](https://angular.io/guide/template-syntax#ngfor)\n\n```ts\nexport interface Book {\n  id: number;\n  title: string;\n  author: string;\n}\n```\n\n```ts\nimport { Component } from '@angular/core';\nimport { Book } from './book.interface';\n\n@Component({\n  selector: 'book-list',\n  template: `\n    \u003cul\u003e\n      \u003cli *ngFor=\"let book of books; trackBy: trackById\"\u003e\n        {{ book.title }} by {{ book.author }}\n      \u003c/li\u003e\n    \u003c/ul\u003e\n  `\n})\nexport class BookListComponent {\n  this.books: Book[] = [\n    {\n      id: 1,\n      title: \"Eloquent JavaScript\",\n      author: \"Marijn Haverbeke\"\n    },\n    {\n      id: 2,\n      title: \"JavaScript: The Good Parts\",\n      author: \"Douglas Crockford\"\n    },\n    {\n      id: 3,\n      title: \"JavaScript: The Definitive Guide\",\n      author: \"David Flanagan\"\n    }\n  ];\n\n  trackById(book) {\n    return book.id;\n  }\n}\n```\n\n## ![react] React\n\n[Lists and Keys](https://reactjs.org/docs/lists-and-keys.html)\n\n```jsx\nimport React, { Component } from 'react';\n\nexport class BookList extends Component {\n  state = {\n    books: [\n      {\n        id: 1,\n        title: 'Eloquent JavaScript',\n        author: 'Marijn Haverbeke',\n      },\n      {\n        id: 2,\n        title: 'JavaScript: The Good Parts',\n        author: 'Douglas Crockford',\n      },\n      {\n        id: 3,\n        title: 'JavaScript: The Definitive Guide',\n        author: 'David Flanagan',\n      },\n    ],\n  };\n\n  render() {\n    const { books } = this.state;\n\n    return (\n      \u003cul\u003e\n        { books.map(book =\u003e {\n          return (\n            \u003cli key=\"{ book.id }\"\u003e\n              { book.title } by { book.author }\n            \u003c/li\u003e\n          );\n        }) }\n      \u003c/ul\u003e\n    );\n  }\n}\n```\n\n## ![vue] Vue.js\n\n```html\n\u003ctemplate\u003e\n  \u003cul\u003e\n    \u003cli v-for=\"book in books\" :key=\"book.id\"\u003e\n      {{ book.title }} by {{ book.author }}\n    \u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/template\u003e\n```\n\n```js\nexport default {\n  data() {\n    return {\n      books: [\n        {\n          id: 1,\n          title: 'Eloquent JavaScript',\n          author: 'Marijn Haverbeke',\n        },\n        {\n          id: 2,\n          title: 'JavaScript: The Good Parts',\n          author: 'Douglas Crockford',\n        },\n        {\n          id: 3,\n          title: 'JavaScript: The Definitive Guide',\n          author: 'David Flanagan',\n        },\n      ],\n    };\n  },\n};\n```\n\n# Filters\n\n## ![angular.js] AngularJS\n\nAngularJS provides filters to transform data. There are several [built-in filters](https://docs.angularjs.org/api/ng/filter) available and you can make your own custom filters as well.\n\nFilters can be applied to view templates using the following syntax:\n\n```html\n\u003ch1\u003e{{ price | currency }}\u003c/h1\u003e\n```\n\nChaining of filters is also possible:\n\n```html\n\u003ch1\u003e{{ name | uppercase | appendTitle  }}\u003c/h1\u003e\n```\n\nCustom Filters:\n\n```js\nangular.module('app', [])\n  .filter('reverse', function() {\n    return (input = '', uppercase = false) =\u003e {\n      const out = input.split('').reverse().join('');\n\n      return uppercase ? out.toUpperCase() : out;\n    };\n  });\n```\n\n:link: https://docs.angularjs.org/guide/filter\n\n## ![angular] Angular\n\nIn Angular filters are called [pipes](https://angular.io/guide/pipes). The built-in pipes available in Angular are: DatePipe, UpperCasePipe, LowerCasePipe, CurrencyPipe, and PercentPipe.\n\nApart from the built-in pipes, you can create your own, custom pipes.\n\nCreate a custom pipe:\nthis pipe transforms a given URL to a safe style URL, that way it can be used in hyperlinks, for example \u003cimg src\u003e or \u003ciframe src\u003e, etc..\n\n```ts\nimport { Pipe, PipeTransform } from '@angular/core';\nimport { DomSanitizer} from '@angular/platform-browser';\n\n@Pipe({ name: 'safe' })\nexport class SafePipe implements PipeTransform {\n  constructor(public sanitizer: DomSanitizer) {}\n  transform(url) {\n    return this.sanitizer.bypassSecurityTrustResourceUrl(url);\n  }\n}\n```\n\nUse the custom pipe in a template:\nThe given `someUrl` is filtered through the `safe` pipe which transforms it trough the [`DomSanitizer`](https://angular.io/api/platform-browser/DomSanitizer) function `bypassSecurityTrustResourceUrl`.\n\n```html\n  \u003ciframe [src]=\"someUrl | safe\"\u003e\u003c/iframe\u003e\n```\n\nNote: `[src]` above is an input to the component which 'lives' above the `iframe`.\n\n:link: https://angular.io/guide/pipes\n\n## ![react] React\n\nReact doesn't provide any specific filtering mechanism. This can simply be achieved by using ordinary JavaScript functions:\n\n```jsx\nexport function reverse(input = '', uppercase = false) {\n  const out = input.split('').reverse().join('');\n\n  return uppercase ? out.toUpperCase() : out;\n}\n```\n\n```jsx\nimport React, { Component } from 'react';\nimport { reverse } from 'utils';\n\nexport class App extends Component {\n  render() {\n    return (\n      \u003cdiv\u003e\n        { reverse(this.props.input) }\n      \u003c/div\u003e\n    );\n  }\n}\n```\n\nFilter chaining can be achieved using function composition:\n\n```jsx\n\u003cdiv\u003e\n  { truncate(reverse(this.props.input)) }\n\u003c/div\u003e;\n```\n\n## ![vue] Vue.js\n\nVue.js provides filters to allow for simple text formatting. The filter utilizes the `|` character which is appended to the expression followed by the filter's name. Vue does not come with any pre-built filters.\n\nFilters can be used within mustache interpolations:\n\n```html\n\u003ch1\u003e{{ name | lowercase }}\u003c/h1\u003e\n```\n\nFilters can also be used within the `v-bind` directive:\n\n```html\n\u003cdiv v-bind:slug=\"slug | formatSlug\"\u003e\u003c/div\u003e\n```\n\nWhen creating filters, the function always receives the expression's value:\n\n```js\nnew Vue({\n  el: '#app',\n  template: '\u003cp\u003e {{ message | lowercase }} \u003c/p\u003e',\n  filters: {\n    lowercase(word) {\n      return word.toLowerCase();\n    },\n  },\n  data: {\n    message: 'Hello World',\n  },\n});\n```\n\nFilters can also be chained:\n\n```html\n\u003cp\u003e{{ description | lowercase | truncate }}\u003c/p\u003e\n```\n\nFilters can be created locally like the above example and only be available within that component. Filters can also be declared globally:\n\n```js\nVue.filter('lowercase', word =\u003e word.toLowerCase());\n```\n\nFor global filters to work, they should be declared before the Vue instance.\n\n:link: https://vuejs.org/v2/guide/filters.html\n\n# Child nodes\n\n## ![angular.js] AngularJS\n\nInside a [component](https://docs.angularjs.org/guide/component), we have access to the child node by injecting `$element` to the controller. This object contains a [jqLite](https://docs.angularjs.org/api/ng/function/angular.element) wrapped instance of the DOM element. Accessing `$element[0]` will return the bare DOM element.\n\nTransclusion is also supported - using `ng-transclude` (See [Transclusion and Containment](#transclusion-and-containment) section).\n\n```js\nclass TextInputController {\n  constructor($element) {\n    'ngInject';\n\n    this.$element = $element;\n  }\n\n  // The $element can be used after the link stage\n  $postLink() {\n    const input = this.$element.find('input');\n    input.on('change', console.log);\n  }\n}\n\nconst component = {\n  controller: TextInputController,\n  template: `\n    \u003cdiv\u003e\n      \u003cinput type=\"text\" /\u003e\n    \u003c/div\u003e\n  `,\n};\n```\n\n## ![angular] Angular\n\nAngular provides two ways to deal with child nodes: `ViewChild` and `ContentChild`. They both have the same purpose, but there are different use cases for them.\n\n* [`ViewChild`](https://angular.io/api/core/ViewChild) works with the **internal DOM of your component**, defined by you in the component's template. You have to use the `@ViewChild` decorator to get the DOM element reference.\n\n* [`ContentChild`](https://angular.io/api/core/ContentChild) works with de **DOM supplied to your component by its end-user** (See [Transclusion and Containment](#transclusion-and-containment)). You have to use the `@ContentChild` decorator to get the DOM element reference.\n\n```ts\nimport {\n  Component,\n  Input,\n  ViewChild,\n  ContentChild,\n  AfterViewInit,\n  AfterContentInit,\n} from '@angular/core';\n\n@Component({\n  selector: 'child',\n  template: `\n    \u003cp\u003eHello, I'm your child #{{ number }}!\u003c/p\u003e\n  `,\n})\nexport class Child {\n  @Input() number: number;\n}\n\n@Component({\n  selector: 'parent',\n  template: `\n    \u003cchild number=\"1\"\u003e\u003c/child\u003e\n    \u003cng-content\u003e\u003c/ng-content\u003e\n  `,\n})\nexport class Parent implements AfterViewInit, AfterContentInit {\n  @ViewChild(Child) viewChild: Child;\n  @ContentChild(Child) contentChild: Child;\n\n  ngAfterViewInit() {\n    // ViewChild element is only available when the\n    // ngAfterViewInit lifecycle hook is reached.\n    console.log(this.viewChild);\n  }\n\n  ngAfterContentInit() {\n    // ContentChild element is only available when the\n    // ngAfterContentInit lifecycle hook is reached.\n    console.log(this.contentChild);\n  }\n}\n\n@Component({\n  selector: 'app',\n  template: `\n    \u003cparent\u003e\n      \u003cchild number=\"2\"\u003e\u003c/child\u003e\n      \u003cchild number=\"3\"\u003e\u003c/child\u003e\n    \u003c/parent\u003e\n  `,\n})\nexport class AppComponent { }\n```\n\n`ViewChild` and `ContentChild` only work with a **single** DOM element. You can use [`ViewChildren`](https://angular.io/api/core/ViewChildren) and [`ContentChildren`](https://angular.io/api/core/ContentChildren) in order to get **multiple elements**. Both return the elements wrapped in a [`QueryList`](https://angular.io/api/core/QueryList).\n\n## ![react] React\n\nIn React, we have two options to deal with child nodes: [`refs`](https://reactjs.org/docs/refs-and-the-dom) and [`children`](https://reactjs.org/docs/jsx-in-depth.html#children-in-jsx). With `refs`, you have access to the real DOM element. The `children` property lets you manipulate the underlying [React elements](https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html).\n\n#### refs\n\n`ref` is a special attribute we can pass to a React element that receives a callback and call it with the corresponding DOM node.\n\n```jsx\nimport React, { Component } from 'react';\n\n// In order to access child nodes from parents, we can pass the `ref` callback\n// to the children as props.\nconst TextInput = ({ inputRef }) =\u003e (\n  \u003cdiv\u003e\n    \u003cinput ref={inputRef} type=\"text\" /\u003e\n  \u003c/div\u003e\n);\n\nclass Parent extends Component {\n  componentDidMount() {\n    // Refs are only executed after mounting and unmounting. Now `this.textInput`\n    // references a real DOM node. So, we can use the raw DOM API\n    // (to focus the input, for example)\n    this.textInput.focus();\n  }\n\n  render() {\n    // The child's `inputRef` prop receives the `ref` callback.\n    // We can use the callback to store the DOM element in an instance variable.\n    return (\n      \u003cdiv\u003e\n        \u003clabel\u003eThis is my child: \u003c/label\u003e\n        \u003cTextInput\n          inputRef={node =\u003e { this.textInput = node; }} /\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\n```\n\n#### children\n\n`children` is a special prop available in all React component instances. You can use it to control _how_ and _where_ the underlying React elements will be rendered.\n\n```jsx\nimport React, { Component } from 'react';\n\n// children is just a prop. In this case, the value of `children` will be\n// what you pass to the \u003cHeading /\u003e component as a child node.\nconst Heading = ({ children }) =\u003e (\n  \u003ch1 className=\"Heading\"\u003e\n    {children}\n  \u003c/h1\u003e\n);\n\n// `this.props.children` refers to whatever is a valid node inside the \u003cLayout /\u003e element.\nclass Layout extends Component {\n  render() {\n    return (\n      \u003cdiv class=\"Layout\"\u003e\n        {this.props.children}\n      \u003c/div\u003e\n    );\n  }\n}\n\nconst App = () =\u003e (\n  \u003cdiv\u003e\n    \u003cHeading\u003eI am the child!\u003c/Heading\u003e\n    \u003cLayout\u003e\n      We are\n      {'the'}\n      \u003cstrong\u003eChildren!\u003c/strong\u003e\n    \u003c/Layout\u003e\n  \u003c/div\u003e\n);\n```\n\n## ![vue] Vue.js\n\n\u003e TODO\n\n# Transclusion and Containment\n\n## Basic\n\n## ![angular.js] AngularJS\n\n```js\nangular.module('app.layout', [])\n  .component('layout', {\n    bindings: {\n      theme: '@',\n    },\n    controller: LayoutController,\n    transclude: true,\n    template: `\n    \u003cdiv ng-class=\"'theme-' + $ctrl.theme\"\u003e\n      \u003cng-transclude\u003e\u003c/ng-transclude\u003e\n    \u003c/div\u003e\n  `,\n  }).component('pageContent', {\n    template: '\u003cdiv\u003eSome content\u003c/div\u003e',\n  }).component('pageFooter', {\n    template: '\u003cfooter\u003eSome content\u003c/footer\u003e',\n  });\n```\n```html\n\u003clayout theme=\"dark\"\u003e\n  \u003cpage-content\u003e\u003c/page-content\u003e\n  \u003cpage-footer\u003e\u003c/page-footer\u003e\n\u003c/layout\u003e\n```\n\n## ![angular] Angular\n\n```ts\n@Component({\n  selector: 'layout',\n  template: `\n    \u003cdiv\u003e\n      \u003cng-content\u003e\u003c/ng-content\u003e\n    \u003c/div\u003e\n  `,\n})\nexport class Layout {}\n\n@Component({\n  selector: 'page-content',\n  template: '\u003cdiv\u003eSome content\u003c/div\u003e',\n})\nexport class PageContent {}\n\n@Component({\n  selector: 'page-footer',\n  template: '\u003cfooter\u003eSome content\u003c/footer\u003e',\n})\nexport class PageFooter {}\n```\n```html\n\u003clayout\u003e\n  \u003cpage-content\u003e\u003c/page-content\u003e\n  \u003cpage-footer\u003e\u003c/page-footer\u003e\n\u003c/layout\u003e\n```\n\n## ![react] React\n\n```jsx\nconst Layout = ({ children, theme }) =\u003e (\n  \u003cdiv className={`theme-${theme}`}\u003e\n    {children}\n  \u003c/div\u003e\n);\n\nconst PageContent = () =\u003e (\n  \u003cdiv\u003eSome content\u003c/div\u003e\n);\n\nconst PageFooter = () =\u003e (\n  \u003cdiv\u003eSome content\u003c/div\u003e\n);\n\n\u003cLayout theme='dark'\u003e\n  \u003cPageContent /\u003e\n  \u003cPageFooter /\u003e\n\u003c/Layout\u003e;\n```\n\n## ![vue] Vue.js\n\n\u003e TODO\n\n## Multiple slots\n\n## ![angular.js] AngularJS\n\n```js\nangular.module('app.layout', [])\n  .component('landingSection', {\n    bindings: {},\n    controller: LandingSectionController,\n    transclude: {\n      contentSlot: '?content', // '?' indicates an optional slot\n      iconSlot: '?icon',\n    },\n    template: `\n    \u003cdiv\u003e\n      \u003cspan ng-transclude=\"contentSlot\"\u003e\u003c/span\u003e\n      \u003cdiv\u003e\n        \u003cspan ng-transclude=\"iconSlot\"\u003eThis is the default value\u003c/span\u003e\n      \u003c/dev\u003e\n    \u003c/div\u003e\n  `,\n  }).component('pageContent', {\n    template: '\u003cdiv\u003eSome content\u003c/div\u003e',\n  });\n```\n```html\n\u003cdiv\u003e\n  \u003ch1\u003ePage title\u003c/h1\u003e\n  \u003clanding-section\u003e\n    \u003cpage-content\u003e\u003c/page-content\u003e\n  \u003c/landing-section\u003e\n\u003c/div\u003e\n```\n\n## ![angular] Angular\n\n\u003e TODO\n\n## ![react] React\n\n```jsx\nconst Layout = ({ children, theme }) =\u003e (\n  \u003cdiv className={`theme-${theme}`}\u003e\n    \u003cheader\u003e{children.header}\u003c/header\u003e\n    \u003cmain\u003e{children.content}\u003c/main\u003e\n    \u003cfooter\u003e{children.footer}\u003c/footer\u003e\n  \u003c/div\u003e\n);\n\nconst Header = () =\u003e (\n  \u003ch1\u003eMy Header\u003c/h1\u003e\n);\n\nconst Footer = () =\u003e (\n  \u003cdiv\u003eMy Footer\u003c/div\u003e\n);\n\nconst Content = () =\u003e (\n  \u003cdiv\u003eSome fancy content\u003c/div\u003e\n);\n\n\u003cLayout theme='dark'\u003e\n  {{\n    header: \u003cHeader /\u003e,\n    content: \u003cContent /\u003e,\n    footer: \u003cFooter /\u003e,\n  }}\n\u003c/Layout\u003e;\n```\n\n## ![vue] Vue.js\n\nApp layout:\n```html\n\u003cdiv class=\"container\"\u003e\n  \u003cheader\u003e\n    \u003cslot name=\"header\"\u003e\u003c/slot\u003e\n  \u003c/header\u003e\n  \u003cmain\u003e\n    \u003cslot\u003e\u003c/slot\u003e\n  \u003c/main\u003e\n  \u003cfooter\u003e\n    \u003cslot name=\"footer\"\u003e\u003c/slot\u003e\n  \u003c/footer\u003e\n\u003c/div\u003e\n```\nParent markup:\n```html\n\u003capp-layout\u003e\n  \u003ch1 slot=\"header\"\u003eHere might be a page title\u003c/h1\u003e\n  \u003cp\u003eA paragraph for the main content.\u003c/p\u003e\n  \u003cp\u003eAnd another one.\u003c/p\u003e\n  \u003cp slot=\"footer\"\u003eHere's some contact info\u003c/p\u003e\n\u003c/app-layout\u003e\n```\nResult:\n```html\n\u003cdiv class=\"container\"\u003e\n  \u003cheader\u003e\n    \u003ch1\u003eHere might be a page title\u003c/h1\u003e\n  \u003c/header\u003e\n  \u003cmain\u003e\n    \u003cp\u003eA paragraph for the main content.\u003c/p\u003e\n    \u003cp\u003eAnd another one.\u003c/p\u003e\n  \u003c/main\u003e\n  \u003cfooter\u003e\n    \u003cp\u003eHere's some contact info\u003c/p\u003e\n  \u003c/footer\u003e\n\u003c/div\u003e\n```\n:link: https://vuejs.org/v2/guide/components.html#Named-Slots\n\n# Class toggling\n\n## ![angular.js] AngularJS\n\nThe [ng-class](https://docs.angularjs.org/api/ng/directive/ngClass) directive allows you to dynamically set CSS classes on an HTML element.\n\n```html\n\u003cmain-header\n  ng-class=\"{ 'mainNavbar--fluid': $ctrl.isFluid }\"\u003e\n...\n\u003c/main-header\u003e\n```\n\n## ![angular] Angular\n\nIn Angular, the [ngClass](https://angular.io/guide/ajs-quick-reference#ngclass) directive works similarly. It includes/excludes CSS classes based on an expression.\n\n```html\n\u003cmain-header\n  [ngClass]=\"{ 'mainNavbar--fluid': isFluid }\"\u003e\n...\n\u003c/main-header\u003e\n```\n\n## ![react] React\n\nThe React approach allows us to construct className string with JavaScript.\n\n```jsx\n\u003cMainHeader\n  className={ this.props.isFluid ? 'mainNavbar--fluid' : '' }\n/\u003e;\n```\n\nMany utility libraries have emerged - [classnames](https://github.com/JedWatson/classnames) being among the most popular.\n\n```jsx\nclass App {\n  /* ... */\n  render() {\n    const classNames = classNames({\n      'mainNavbar--fluid': this.props.isFluid,\n    });\n\n    return (\n      \u003cMainHeader\n        className={ classNames }\n      /\u003e\n    );\n  }\n}\n```\n\n## ![vue] Vue.js\n\n```html\n\u003cmain-header\n  v-bind:class=\"{ 'mainNavbar--fluid': isFluid }\"\n\u003e\n```\n\n:link: https://vuejs.org/v2/guide/class-and-style.html\n\n# Data binding\n\n## ![angular.js] AngularJS\n\nThe [ng-model](https://docs.angularjs.org/api/ng/directive/ngModel) directive binds a form control to a property in the controller. This provides two-way binding.\n\n```js\nimport angular from 'angular';\nimport template from './registration.html';\n\nclass RegistrationController {\n  $onInit() {\n    this.name = '';\n  }\n}\n\nconst component = {\n  bindings: {},\n  template,\n  controller: RegistrationController,\n};\n\nexport const module = angular\n  .module('app.registration', [])\n  .component('registration', component);\n```\n\n```html\n\u003cinput ng-model=\"$ctrl.name\" /\u003e\n\u003cp\u003eName: {{ $ctrl.name }}\u003c/p\u003e\n```\n\n## ![angular] Angular\n\nWe use [`[(ngModel)]`](https://angular.io/api/forms/NgModel) to have a two-way data binding inside our forms. The value in the UI will always be synced with the domain model in the component.\n\n```ts\nimport { Component } from '@angular/core';\n\n@Component({\n  selector: 'registration',\n  templateUrl: require('registration.component.html'),\n})\nexport class RegistrationComponent {\n  name: string = '';\n}\n```\n\n```html\n\u003cinput [(ngModel)]=\"name\" /\u003e\n\u003cp\u003eName: {{ name }}\u003c/p\u003e\n```\n\n:link: https://angular.io/guide/template-syntax#two-way-binding\n\n## ![react] React\n\n\u003e TODO\n\n## ![vue] Vue.js\n\nYou can use the `v-model` directive to create **two-way data bindings** on form `input` and `textarea` elements. It automatically picks the correct way to update the element based on the input type. Although a bit magical, `v-model` is essentially syntax sugar for updating data on user input events, plus special care for some edge cases.\n\n:link: https://vuejs.org/v2/guide/forms.html\n\n# Forms\n\n## ![angular.js] AngularJS\n\n```js\nclass SignInController {\n  constructor(Auth) {\n    'ngInject';\n\n    this.Auth = Auth;\n  }\n\n  $onInit() {\n    this.email = '';\n    this.password = '';\n  }\n\n  submit() {\n    Auth.signIn(this.email, this.password);\n  }\n}\n\n```\n\n```html\n\u003cform name=\"$ctrl.form\"\u003e\n  \u003clabel\u003e\n    Email:\n    \u003cinput type=\"text\" ng-model=\"$ctrl.email\" /\u003e\n  \u003c/label\u003e\n\n  \u003clabel\u003e\n    E-mail:\n    \u003cinput type=\"email\" ng-model=\"$ctrl.password\" /\u003e\n  \u003c/label\u003e\n  \u003cinput type=\"submit\" ng-click=\"$ctrl.submit()\" value=\"Save\" /\u003e\n\u003c/form\u003e\n```\n\n## ![angular] Angular\n\nAngular offers two ways to build forms:\n\n* [Reactive forms](https://angular.io/guide/reactive-forms)\n* [Template-driven forms](https://angular.io/guide/forms#template-driven-forms)\n\nThe former uses a reactive (or model-driven) approach to build forms. The latter allows you to build forms by writing templates in the Angular template syntax with the form-specific directives and techniques.\n\n### ![react] Reactive forms example\n\n```ts\nimport { Component, OnInit } from '@angular/core';\nimport { FormGroup, FormBuilder } from '@angular/forms';\n\n@Component({\n  selector: 'reactive-form',\n  template: `\n    \u003cdiv\u003e\n      \u003cform [formGroup]=\"form\"\n            (ngSubmit)=\"onSubmit(form.value, form.valid)\"\n            novalidate\u003e\n        \u003cdiv\u003e\n          \u003clabel\u003e\n            Name:\n            \u003cinput type=\"text\" formControlName=\"name\"\u003e\n          \u003c/label\u003e\n        \u003c/div\u003e\n        \u003cdiv\u003e\n          \u003clabel\u003e\n            Email:\n             \u003cinput type=\"email\" formControlName=\"email\"\u003e\n          \u003c/label\u003e\n        \u003c/div\u003e\n      \u003c/form\u003e\n    \u003c/div\u003e\n  `\n})\n\nexport class ReactiveFormComponent implements OnInit {\n  public form: FormGroup;\n\n  constructor(private formBuilder: FormBuilder) { }\n\n  ngOnInit() {\n    this.form = this.formBuilder.group({name: [''], email: ['']});\n  }\n}\n```\n#### Template-driven forms example\n\n```ts\nimport { Component } from '@angular/core';\n\n@Component({\n  selector: 'template-driven-form',\n  template: `\n    \u003cdiv\u003e\n      \u003cform (ngSubmit)=\"onSubmit()\" #templateDrivenForm=\"ngForm\" novalidate\u003e\n        \u003cdiv\u003e\n          \u003clabel\u003e\n            Name:\n            \u003cinput type=\"text\" [(ngModel)]=\"model.name\" required\u003e\n          \u003c/label\u003e\n        \u003c/div\u003e\n        \u003cdiv\u003e\n          \u003clabel\u003e\n            Email:\n            \u003cinput type=\"email\" [(ngModel)]=\"model.email\" required\u003e\n          \u003c/label\u003e\n        \u003c/div\u003e\n        \u003cbutton type=\"submit\" [disabled]=\"!templateDrivenForm.form.valid\"\u003eSubmit\u003c/button\u003e\n        \u003c/form\u003e\n    \u003c/div\u003e\n  `\n})\n\nexport class TemplateDrivenFormComponent {\n  public model = { name: '', email: '' };\n}\n```\n\nThe `novalidate` attribute in the `\u003cform\u003e` element prevents the browser from attempting native HTML validations.\n\n## ![react] React\n\nTwo techniques exists in React to handle form data: [Controlled Components](https://reactjs.org/docs/forms.html#controlled-components) and [Uncontrolled Components](https://reactjs.org/docs/uncontrolled-components.html). A controlled component keeps the input's value in the state and updates it via `setState()`. While in an uncontrolled component, form data is handled by DOM itself and referenced via `ref`. In most cases, it is recommended to use controlled components.\n\n```js\nimport React, { Component } from 'react';\n\nexport default class ReactForm extends Component {\n  state = {\n    email: '',\n    password:'',\n  };\n\n  handleChange = ({ name, value}) =\u003e {\n    if (name === 'email') {\n      this.setState({ email: value });\n    } else if (name === 'password') {\n      this.setState({ password: value });\n    }\n  };\n\n  render() {\n    return (\n      \u003cform\u003e\n        \u003clabel\u003e\n          Email:\n          \u003cinput\n            name=\"email\"\n            type=\"email\"\n            value= {this.state.email }\n            onChange={ this.handleChange }\n          /\u003e\n        \u003c/label\u003e\n        \u003clabel\u003e\n          Password:\n          \u003cinput\n            name=\"password\"\n            type=\"password\"\n            value={ this.state.password }\n            onChange={ this.handleChange }\n          /\u003e\n        \u003c/label\u003e\n      \u003c/form\u003e\n    );\n  }\n}\n```\n\n:link: https://reactjs.org/docs/forms.html\n\n## ![vue] Vue.js\n\n```html\n\u003ctemplate\u003e\n  \u003cform v-on:submit.prevent=\"onSubmit\"\u003e\n   \u003clabel\u003e\n       Email:\n      \u003cinput type=\"email\" v-model=\"email\"\u003e\n   \u003c/label\u003e\n   \u003clabel\u003e\n     Password:\n     \u003cinput type=\"password\" v-model=\"password\" /\u003e\n   \u003c/label\u003e\n   \u003cbutton type=\"submit\"\u003eSend\u003c/button\u003e\n  \u003c/form\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport Auth form './util/auth.js';\n\nexport default {\n  data() {\n    return {\n      email: '',\n      password: ''\n    }\n  },\n  methods: {\n    onSubmit() {\n      Auth.signIn(this.email, this.password);\n    }\n  }\n}\n\u003c/script\u003e\n```\n\n:link: https://vuejs.org/v2/guide/forms.html\n\n# Styling\n\n## ![angular.js] AngularJS\n\nGenerally you will use a preprocessor (e.g. [Sass](http://sass-lang.com/)) and assign appropriate classes to the elements.\n\nThe [`ng-style`](https://docs.angularjs.org/api/ng/directive/ngStyle) directive allows you to set custom CSS styles dynamically.\n\n```js\nclass HeaderController {\n  constructor(ThemeProvider) {\n    'ngInject';\n\n    this.ThemeProvider = ThemeProvider;\n    this.headerStyles = {};\n  }\n\n  $onInit() {\n    this.headerStyles.color = ThemeProvider.getTextPrimaryColor();\n  }\n}\n```\n\n```html\n\u003ch1 ng-style=\"$ctrl.headerStyles\"\n    class=\"Header\"\u003e\n    Welcome\n\u003c/h1\u003e\n```\n\n## ![angular] Angular\n\nWhen defining Angular components you may also include the CSS styles that will go with the template. By default the styles will be compiled as shadow DOM, which basically means you don't need any namespacing strategy for CSS classes.\n\nThe [`ngStyle`](https://angular.io/api/common/NgStyle) directive allows you to set custom CSS styles dynamically.\n\n```ts\n@Component({\n  selector: 'ng-header',\n  template: require('./header.html'),\n  styles: [require('./header.scss')],\n})\nexport class HeaderComponent {\n  headerStyles = {};\n\n  constructor(private themeProvider: ThemeProvider) {}\n\n  ngOnInit() {\n    this.headerStyles.color = ThemeProvider.getTextPrimaryColor();\n  }\n}\n```\n\n```html\n\u003ch1 [ngStyle]=\"headerStyles\"\n    class=\"Header\"\u003e\n    Welcome\n\u003c/h1\u003e\n```\n\n```scss\n.Header {\n    font-weight: normal;\n}\n```\n\n:link: https://angular.io/guide/component-styles\n\n## ![react] React\n\nIn the React community there are many approaches to styling your app, ranging from traditional preprocessors (like in the Angular world) to so-called [CSS in JS](https://github.com/MicheleBertoli/css-in-js). The most popular include:\n\n* [css-modules](https://github.com/gajus/react-css-modules)\n* [styled-components](https://github.com/styled-components/styled-components)\n* [aphrodite](https://github.com/Khan/aphrodite)\n\nTo dynamically apply styles you can directly pass an object to the [style](https://reactjs.org/docs/dom-elements.html#style) attribute.\n\n```jsx\nexport class HeaderComponent {\n  state = {\n    color: null,\n  };\n\n  componentDidMount() {\n    this.setState({\n      color: ThemeProvider.getTextPrimaryColor(),\n    });\n  }\n\n  render() {\n    return (\n      \u003ch1 styles={ { color: this.state.color } }\u003e\n        Welcome\n      \u003c/h1\u003e\n    );\n  }\n}\n```\n\n## ![vue] Vue.js\n\nWhen using [Single File Components](https://vuejs.org/v2/guide/single-file-components.html) you can simply style a component inside the `\u003cstyle\u003e` tag. When the tag has the `scoped` attribute, its CSS will apply to elements of the current component only.\n\nTo bind styles dynamically you can use the [`v-bind:style`](https://vuejs.org/v2/guide/class-and-style.html#Binding-Inline-Styles) directive.\n\n```html\n\u003ctemplate\u003e\n  \u003ch1 class=\"Header\"\n    v-bind:style=\"headerStyles\"\u003e\n     Welcome\n  \u003c/h1\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nconst ThemeProvider = require('./utils/themeProvider');\n\nmodule.exports = {\n  data() {\n    return {\n      headerStyles: {\n        color: null,\n      }\n    };\n  },\n  created() {\n    this.headerStyles.color = ThemeProvider.getTextPrimaryColor();\n  },\n};\n\u003c/script\u003e\n\n\u003cstyle scoped\u003e\n  .Header {\n    font-weight: normal\n  }\n\u003c/style\u003e\n```\n\n# Inject HTML template\n\nAlso known as innerHTML.\n\n## ![angular.js] AngularJS\n\nBy default, the HTML content will be sanitized using the [$sanitize](https://docs.angularjs.org/api/ngSanitize/service/$sanitize) service. To utilize this functionality, you need to include `ngSanitize` in your module's dependencies. [Read more](https://docs.angularjs.org/api/ng/directive/ngBindHtml)\n\n```html\n\u003cp ng-bind-html=\"$ctrl.article.content\"\u003e\u003c/p\u003e\n```\n\n## ![angular] Angular\n\nThe values are automatically sanitized before displaying them using [DomSanitizer](https://angular.io/docs/ts/latest/api/platform-browser/index/DomSanitizer-class.html).\n\n```html\n\u003cp [innerHTML]=\"article.content\"\u003e\u003c/p\u003e\n```\n\n## ![react] React\n\nAll string values are sanitized before being inserted into the DOM. No more details are currently available.\nYou need to pass an object containing the `__html` property with the desired template contents.\n\n```jsx\n\u003cp dangerouslySetInnerHTML={ { __html: article.content } } /\u003e;\n```\n\n## ![vue] Vue.js\n\nThe content passed to [`v-html`](https://vuejs.org/v2/guide/syntax.html#Raw-HTML) is not being [sanitized](https://github.com/vuejs/vue/issues/6333). You have to use an external library, e.g. [sanitize-html](https://www.npmjs.com/package/sanitize-html).\n\n```html\n\u003cdiv v-html=\"article.content\"\u003e\u003c/div\u003e\n```\n","funding_links":[],"categories":["Learning Resources"],"sub_categories":["References"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeimosi%2Fframeworks-code-comparison","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffeimosi%2Fframeworks-code-comparison","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeimosi%2Fframeworks-code-comparison/lists"}