Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EXCEPTION: Template parse errors: Only void and foreign elements can be self closed "meta"

Tags:

angular

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 &amp;&amp; email.touched" [(ngModel)]="emailModel"/>         <input type="password" id="password" placeholder="Lozinka" [ngFormControl]="loginForm.controls['password']" [class.error]="!password.valid &amp;&amp; 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         });     } } 
like image 574
ditoslav Avatar asked Jan 09 '16 11:01

ditoslav


1 Answers

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.

like image 73
peterh Avatar answered Nov 12 '22 00:11

peterh