After adding a component into directives array of root component, Angular2 starts complaining in the browser about self enclosing "meta" tag which should be ok, and which also works without complaints if the directive is not there.
I'm trying to add a my-header component into my application.
app.html
<div> <my-header></my-header> </div> <nav class="nav-bar"> <div class="nav-bar-top-spacer"></div> <ul> <li *ngFor="#group of navigation" class="nav-option-group"> <div class="nav-option-group"></div> <div (click)="hideGroup(group)" class="nav-option-group-name">{{ group.Croatian }}</div> <ul [ngClass]="{displayNone: !group.visible}"> <li [routerLink]="[comp.componentName]" *ngFor="#comp of group.components" class="option-group-item">{{ comp.Croatian }}</li> </ul> </li> <li class="nav-option-group"> <div class="nav-option-group-name">Odjavi se</div> </li> </ul> </nav> <router-outlet></router-outlet>
app.ts
import { Component, View } from "angular2/core"; import { COMMON_DIRECTIVES } from "angular2/common"; import { Http } from "angular2/http"; import { RouteConfig, RouterLink, RouterOutlet, Route, ROUTER_DIRECTIVES, Router} from 'angular2/router'; import { Header } from '../app/header'; import { AccountData } from '../settings/AccountData/AccountData'; import { AccountDelete } from '../settings/AccountDelete/AccountDelete'; import { AccountLogin } from '../settings/AccountLogin/AccountLogin'; import { AccountPassword } from '../settings/AccountPassword/AccountPassword'; import { AddTrack } from '../settings/AddTrack/AddTrack'; import { EditUser } from '../settings/EditUser/EditUser'; import { MakePlaylist } from '../settings/MakePlaylist/MakePlaylist'; import { MakeWishlist } from '../settings/MakeWishlist/MakeWishlist'; import { ManageAdmins } from '../settings/ManageAdmins/ManageAdmins'; import { ManageEditors } from '../settings/ManageEditors/ManageEditors'; import { ManageRadiostation } from '../settings/ManageRadiostation/ManageRadiostation'; import { ManageTracks } from '../settings/ManageTracks/ManageTracks'; import { ManageUsers } from '../settings/ManageUsers/ManageUsers'; var components = ['AccountData', 'AccountDelete', 'AccountLogin' , 'AccountPassword', 'AddTrack', 'EditUser', 'MakePlaylist' , 'MakeWishlist', 'ManageAdmins', 'ManageEditors', 'ManageRadiostation' , 'ManageTracks', 'ManageUsers']; //var routes = components.map((componentName) => { return new Route(componentName, componentName, componentName) }); @Component({ selector: 'App', templateUrl: './dest/App/App.html', styles: [], directives: [ ROUTER_DIRECTIVES, COMMON_DIRECTIVES, Header ] }) @RouteConfig([ { path: '/', redirectTo: ['AccountData'] }, { path: 'AccountData', name: 'AccountData', component: AccountData }, { path: 'AccountDelete', name: 'AccountDelete', component: AccountDelete }, { path: 'AccountLogin', name: 'AccountLogin', component: AccountLogin }, { path: 'AccountPassword', name: 'AccountPassword', component: AccountPassword }, { path: 'AddTrack', name: 'AddTrack', component: AddTrack }, { path: 'EditUser', name: 'EditUser', component: EditUser }, { path: 'MakePlaylist', name: 'MakePlaylist', component: MakePlaylist }, { path: 'MakeWishlist', name: 'MakeWishlist', component: MakeWishlist }, { path: 'ManageAdmins', name: 'ManageAdmins', component: ManageAdmins }, { path: 'ManageEditors', name: 'ManageEditors', component: ManageEditors }, { path: 'ManageRadiostation', name: 'ManageRadiostation', component: ManageRadiostation }, { path: 'ManageTracks', name: 'ManageTracks', component: ManageTracks }, { path: 'ManageUsers', name: 'ManageUsers', component: ManageUsers } ]) export class App { router: Router; location: Location; navigation: any[]; hideGroup(group): void { group.visible = !group.visible; } constructor(router: Router) { this.router = router; this.navigation = [ { 'Croatian': 'Slusaj radio', 'groupName': 'Listen', 'components': [] }, { 'Croatian': 'Vlasničke mogućnosti', 'groupName': 'OwnerOptions', 'components': [ { 'Croatian': 'Upravljaj administratorima', 'componentName': 'ManageAdmins', 'componentObject': ManageAdmins }, { 'Croatian': 'Pregledaj podatke o postaji', 'componentName': 'ManageRadiostation', 'componentObject': ManageRadiostation } ] }, { 'Croatian': 'Administratorske modućnosti', 'groupName': 'AdminOptions', 'components': [ { 'Croatian': 'Uredi zvučne zapise', 'componentName': 'ManageTracks', 'componentObject': ManageTracks }, { 'Croatian': 'Upravljaj urednicima', 'componentName': 'ManageEditors', 'componentObject': ManageEditors }, { 'Croatian': 'Dodaj pjesmu', 'componentName': 'AddTrack', 'componentObject': AddTrack }, { 'Croatian': 'Upravljaj korisnicima', 'componentName': 'EditUser', 'componentObject': EditUser }, ] }, { 'Croatian': 'Uredničke mogućnosti', 'groupName': 'EditorOptions', 'components': [ { 'Croatian': 'Pregledaj termine', 'componentName': 'MakePlaylist', 'componentObject': MakePlaylist } ] }, { 'Croatian': 'Korisničke mogućnosti', 'groupName': 'UserOptions', 'components': [ { 'Croatian': 'Pregledaj listu želja', 'componentName': 'MakeWishlist', 'componentObject': MakeWishlist } ] }, { 'Croatian': 'Postavke računa', 'groupName': 'AccountSettings', 'components': [ { 'Croatian': 'Uredi osobne podatke', 'componentName': 'AccountData', 'componentObject': AccountData }, { 'Croatian': 'Promijeni lozinku', 'componentName': 'AccountPassword', 'componentObject': AccountPassword }, { 'Croatian': 'Obriši račun', 'componentName': 'AccountDelete', 'componentObject': AccountDelete } // { 'Croatian': 'Login', 'componentName': 'Login', 'componentObject': Logi} ] } ]; for (var i = 0; i < this.navigation.length; ++i) { this.navigation[i].visible = true; } }; }
header.html
<div class="header-bar"> <div class="app-box"><a href=""> <div class="app-name">FM Radio</div></a> <div class="app-descr">99.4 MHz</div> </div> <div class="user-box row"> <div class="user-form-box"> <form [ngFormModel]="loginForm" (onSubmit)="loginForm.value" method="post" action="/user/auth/login" class="row"> <input type="email" id="email" placeholder="E-mail" [ngFormControl]="loginForm.controls['email']" [class.error]="!email.valid && email.touched" [(ngModel)]="emailModel"/> <input type="password" id="password" placeholder="Lozinka" [ngFormControl]="loginForm.controls['password']" [class.error]="!password.valid && password.touched" [(ngModel)]="passwordModel"/> <button type="submit">Prijavi se</button><a href="#register"> <button type="button" class="dim">Registriraj se</button></a> </form> </div> <div class="user-name-box"><i class="material-icons user-icon">account_circle</i> <div class="user-name">Mirko Horvat<span class="user-type">administrator</span></div> </div> </div> </div>
header.ts
import { Component } from 'angular2/core'; import { FORM_DIRECTIVES, COMMON_DIRECTIVES, FormBuilder, ControlGroup, Validators, Control } from 'angular2/common'; @Component({ selector: 'my-header', templateUrl: '.dest/app/header', styles: [], directives: [ FORM_DIRECTIVES, COMMON_DIRECTIVES ] }) export class Header { // @Input() modelName // @Output() eventEmitterName loginForm: ControlGroup; email: Control; password: Control; emailModel: string; passwordModel: string; constructor(fb, FormBuilder) { this.email = new Control('', Validators.required); this.password = new Control('', Validators.required); this.loginForm = fb.group({ 'email': this.email, 'password': this.password }); } }
In the reality, despite the other answer, the real cause of the problems can be found in the BREAKING CHANGES
section of the angular2 changelog, at version 2.0.0-alpha48:
End tags used to be tolerated for void elements with no content. They are no more allowed so that we more closely follow the HTML5 spec.
Thus, if you had a code like <example a="b" />
, for example you read it in an example in the internet to an angular2 version earlier as 2.0.0-alpha48, it won't work.
But, <example a="b"></example>
will work!
The angular2 developers think, they want to follow HTML5 "more closely". My opinion about what should they do, is quite different.
It is not clear, what the doc or the error message understands on "void or foreign elements". I suspect, maybe using a different html namespace for our own tags, (i.e. having a <myapp:example a="b" />
) will maybe also work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With