<!DOCTYPE html>
<html lang="en">
  
<head>
  <title>Angular2: Using contentchildren to display messages</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
  <script src="https://npmcdn.com/es6-shim@0.35.0/es6-shim.min.js"></script>
  <script src="https://npmcdn.com/zone.js@0.6.12?main=browser"></script>
  <script src="https://npmcdn.com/reflect-metadata@0.1.3"></script>
  <script src="https://npmcdn.com/systemjs@0.19.27/dist/system.src.js"></script>
  <script src="systemjs.config.js"></script>
  <script>
    System.import('app').catch(function (err) {
      console.error(err);
    });
  </script>
</head>

<body>
<my-app>loading...</my-app>
</body>

</html>
### Recreating ng-messages using contentchildren
System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  //map tells the System loader where to look for things
  map: {
    app: "./src"
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    }
  }
});
//main entry point
import {bootstrap}    from '@angular/platform-browser-dynamic';
import {App} from './app';

bootstrap(App, [])
  .catch(err => console.error(err));
//our root app component
import {Component} from '@angular/core'
import {SomeForm} from  './formdemo.component'


@Component({
  selector: 'my-app',
  providers: [],
  template: `
  <div class="well" style="height:230px">
   <some-form></some-form>
   </div>
  `,
  directives: [SomeForm]
})
export class App {
  constructor() {
  }
}
import {Component, OnInit} from "@angular/core";
import {FormBuilder, AbstractControl, FORM_DIRECTIVES, ControlGroup, Validators} from "@angular/common";
import {ExtendedInput} from "./extended-input.component"
import {InputError} from "./input-error.component";

@Component({
  selector: 'some-form',
  template: `
 <extended-input [labelText]="'Some number'"
                [isError]="!someNumber.valid">
    <input class="form-control"
           [ngFormControl]="someNumber">
    <input-errors>
        <input-error class="help-block" 
                     *ngIf="someNumber.hasError('required')">
            A number is required
        </input-error>
        <input-error class="help-block" *
                     *ngIf="someNumber.hasError('divisibleByTen')">
            The number should be divisible by 10
        </input-error>
        <input-error class="help-block" 
                     *ngIf="someNumber.hasError('minlength')">
            The number should be at least 7 digits
        </input-error>
    </input-errors>
</extended-input>
  `
  directives: [FORM_DIRECTIVES,ExtendedInput,InputError]
})
export class SomeForm implements OnInit {

  someFormHandle:ControlGroup;
  someNumber:AbstractControl;

  constructor(private formBuilder:FormBuilder) {
  }
  
  divisibleByTen(control:Control) {
      return parseInt(control.value) % 10 == 0 ? null : {
        divisibleByTen: true
      }
  }
  
  ngOnInit():void {
    this.someFormHandle = this.formBuilder.group({
      'someNumber': ['', Validators.compose([Validators.required, 
                                             Validators.minLength(7), 
                                             this.divisibleByTen])]
    });

    this.someNumber = this.someFormHandle.find('someNumber');
  }
  
}
import {Component} from "@angular/core";
import {CORE_DIRECTIVES} from "@angular/common";

@Component({
  selector: 'input-error',
  template: `<span *ngIf="showErrorFlag" class="help-block">
               <ng-content></ng-content>
             </span>
             `,
  directives: [CORE_DIRECTIVES]
})
export class InputError {

  showErrorFlag:boolean = true;

  hideError():void {
    this.showErrorFlag = false;
  }

  showError():void {
    this.showErrorFlag = true;
  }

}
import {Component, Input, ContentChildren, QueryList, DoCheck} from "@angular/core";
import {CORE_DIRECTIVES} from "@angular/common";
import {InputError} from "./input-error.component";


@Component({
  selector: 'extended-input',
  template: `<div class="form-group"
                  [ngClass]="{'has-error':isError}"> 
                        <label class="control-label">{{labelText}}
                            <ng-content select="input"></ng-content>
                        </label>
                        <ng-content select="input-errors"></ng-content>
             </div>
            `,
  directives: [CORE_DIRECTIVES, InputError]
})
export class ExtendedInput {
  @Input()
  labelText:string = '';
  @Input()
  isError:boolean = false;
  @ContentChildren(InputError)
  errors:QueryList<InputError>;
  
  ngDoCheck():void {
    if (this.errors) {
      this.errors.toArray().forEach(
        (error:QaInputError, i:number) => {
          if (i == 0) {
            error.showError();
          } else {
            error.hideError();
          }
        });
    }
  }
}
(function(global) {

  var ngVer = '@2.0.0-rc.1'; 

  var  map = {
    'app':                        'src',

    '@angular':                   'https://npmcdn.com/@angular', // sufficient if we didn't pin the version
    'rxjs':                       'https://npmcdn.com/rxjs@5.0.0-beta.6',
    'ts':                         'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
    'typescript':                 'https://npmcdn.com/typescript@1.8.10/lib/typescript.js',
 };

  //packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.ts',  defaultExtension: 'ts' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' },
  };

  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];

  // Add map entries for each angular package
  // only because we're pinning the version with `ngVer`.
  ngPackageNames.forEach(function(pkgName) {
    map['@angular/'+pkgName] = 'https://npmcdn.com/@angular/' + pkgName + ngVer;
  });

  // Add package entries for angular packages
  ngPackageNames.forEach(function(pkgName) {

    // Bundled (~40 requests):
    packages['@angular/'+pkgName] = { main: pkgName + '.umd.js', defaultExtension: 'js' };

   });

  var config = {
    transpiler: 'typescript',
    typescriptOptions: {
      emitDecoratorMetadata: true
    },

    map: map,
    packages: packages
  }

  System.config(config);

})(this);