Bhushan Gadekar Bhushan Gadekar - 1 month ago 18
Javascript Question

The selector "app" did not match any elements

I m using angular2-universal for server side rendering and generating static HTML.

so far my static HTML is generated & component is also getting rendered.
but in my browser console its showing this error.

EXCEPTION: The selector "app" did not match any elements


I have used following code for this purpose:

1.index.html

<!doctype html>
<html lang="en">

<head>
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<link href="\node_modules\bootstrap\dist\css\bootstrap.min.css" rel="stylesheet" />
<link href="\node_modules\bootstrap\dist\css\style.css" rel="stylesheet" />
<script src="/node_modules/es6-shim/es6-shim.js"></script>
<script src="/node_modules/es6-promise/dist/es6-promise.js"></script>
<script src="/node_modules/reflect-metadata/Reflect.js"></script>
<script src="/node_modules/zone.js/dist/zone-microtask.js"></script>
<script src="/node_modules/zone.js/dist/long-stack-trace-zone.js"></script>
<script src="/dist/client/bundle.js"></script>
</head>
<body>
<app>Loading....</app>
</body>
</html>


2.client.ts

import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS} from 'angular2/http';
import 'rxjs/add/operator/map';
import {App} from './app/app.component';

bootstrap(App,[HTTP_PROVIDERS,]);


3.server.ts

import * as path from 'path';
import * as express from 'express';
import * as universal from 'angular2-universal-preview';

// Angular 2
import {App} from './app/app.component';


let app = express();
let root = path.join(path.resolve(__dirname, '../'));

// Express View
app.engine('.ng2.html', universal.ng2engine);
app.set('views', __dirname);
app.set('view engine', 'ng2.html');

// Serve static files
app.use(express.static(root));
var i = 0;
// Routes
app.use('/', (req, res) => {
res.render('index_new', {App}, function(err,html){
console.log("------------------My HTML ---------\n"+(i++));
console.log(html);
console.log("------------------My HTML ----------");
res.send(html);
});
});

// Server
app.listen(3000, () => {
console.log('Listen on http://localhost:3000');
});


4.app.component.ts



import {Component} from 'angular2/core';
import {NgSwitch, NgSwitchWhen, NgSwitchDefault,NgFor} from 'angular2/common';
import {Http, Response} from 'angular2/http';
import {Observable} from 'rxjs/Rx';

@Component({
selector: 'app',
template: `
<div *ngFor="#comp of record">
<div class="col-sm-4 divDynamic">
<table style="width:100%;">
<tr style="background-color:#B8B8B8">
<th>{{comp.data[comp.mappings[0].mapAttr]}}</th>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</table>
<br/>
</div>
<div class="col-sm-4 divDynamic">
<table style="width:100%;">
<tr style="background-color:#B8B8B8">
<th>{{comp.data[comp.mappings[1].mapAttr]}}</th>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</table>
<br/>
</div>
<div class="col-sm-4 spec" style="float:right;">
<table style="width:100%;">
<tr style="background-color:#f5821f;color:white;">
<th>{{comp.data[comp.mappings[2].mapAttr]}}</th>
</tr>
<tr>
<td style="border:none;text-align:left;">{{comp.data[comp.mappings[16].mapAttr]}}</td>
</tr>
<tr>
<td style="border:none;text-align:left;">{{comp.data[comp.mappings[15].mapAttr]}}</td>
</tr>
<tr>
<td style="border:none;text-align:left;">{{comp.data[comp.mappings[17].mapAttr]}}</td>
</tr>
</table>
<br/>
</div>
<div class="col-sm-8 spec">
<table style="width:100%;">
<tr>
<td rowspan="2" style="background-color:#f5821f;color:white;" class="col-xs-2 ">{{comp.data[comp.mappings[3].mapAttr]}}</td>
<th>{{comp.data[comp.mappings[7].mapAttr]}}</th>
<th>{{comp.data[comp.mappings[7].mapAttr]}}</th>
<th>{{comp.data[comp.mappings[7].mapAttr]}}</th>
<th>{{comp.data[comp.mappings[7].mapAttr]}}</th>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
<br/>
</div>
<div class="col-sm-8 divDynamic">
<table style="width:100%;">
<tr>
<td rowspan="2" style="background-color:#B8B8B8;" class="col-xs-2 ">{{comp.data[comp.mappings[4].mapAttr]}}</td>
<th>{{comp.data[comp.mappings[11].mapAttr]}}</th>
<th>{{comp.data[comp.mappings[12].mapAttr]}}</th>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
<br/>
</div>
<div class="col-sm-12 divDynamic">
<table style="width:100%;">
<tr>
<td rowspan="2" style="background-color:#B8B8B8;" class="col-xs-2 ">{{comp.data[comp.mappings[5].mapAttr]}}</td>
<th>{{comp.data[comp.mappings[13].mapAttr]}}</th>
<th>{{comp.data[comp.mappings[14].mapAttr]}}</th>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
<br/>
</div>
<div class="col-sm-12" style="color:#a41c2b;border:solid #a41c2b 2px;">
{{comp.data[comp.mappings[6].mapAttr]}}
</div>
</div>
`
})
export class App{
public record = [{
"styling": {
"overall": {}
},
"data": {
"statementDate": "Statement Date",
"minAmtDue": "Minimum Amount Due",
"totalAmtDue": "Your Total Amount Due",
"stmtSummary": "Statement Summary",
"creditSummary": "Credit Summary",
"rewards": "REWARDS",
"bottomPara": "Convert your Big shopping bills into small, manageable EMI's! If any of the below transaction is highlighted,you may login to Internet Banking and convert into EMI now ! TnC apply.",
"prevBalance": "Previous Balance",
"purchases": "Purchases/ Charges",
"cashAdv": "Cash Advances",
"payments": "Payments/ Credits",
"creditLimit": "Credit Limit",
"creditAvail": "Available Credit",
"pointsEarned": "Points Earned",
"payback": "Points Transferred to PAYBACK(Acc:",
"dueDate": "Due Date:",
"Amt": "Rs.",
"interest": "Interest will be levied if Total Amount Due is not paid"
},
"mappings": [
{
"mapAttr": "statementDate"
},
{
"mapAttr": "minAmtDue"
},
{
"mapAttr": "totalAmtDue"
},
{
"mapAttr": "stmtSummary"
},
{
"mapAttr": "creditSummary"
},
{
"mapAttr": "rewards"
},
{
"mapAttr": "bottomPara"
},
{
"mapAttr": "prevBalance"
},
{
"mapAttr": "purchases"
},
{
"mapAttr": "cashAdv"
},
{
"mapAttr": "payments"
},
{
"mapAttr": "creditLimit"
},
{
"mapAttr": "creditAvail"
},
{
"mapAttr": "pointsEarned"
},
{
"mapAttr": "payback"
},
{
"mapAttr": "dueDate"
},
{
"mapAttr": "Amt"
},
{
"mapAttr": "interest"
}
]
}
];
}




Answer

After looking at this code I realized that it bootstrapping app on client side too.

After deleting below line from client.ts it works fine.

bootstrap(App,[HTTP_PROVIDERS,]);

after I removed this line from client.ts , the application didn't produce any errors. but I am not sure why universal-starter people had used this line in first place if they are using server-side-rendering.

what i am understanding from this is , application tried to load the component two times,

from client side & server side respectively.

So it rendered server side component but failed to find selector for client side component.