Can ng-content be utilized within the app-root component?

I have successfully developed an Angular application, and now I am looking to integrate it with a content management system that generates static pages. In order to achieve this, I need to utilize content projection from the main index.html file.

The desired structure would look like this:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>AngularCMS</title>
    <base href="/">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
  </head>
  <body>
    <app-root>Content injected from index.html</app-root>
  </body>
</html>

Next, the app-root component can implement content projection by including

<ng-content></ng-content>
in its template:

@Component({
  selector: 'app-root',
  template: '<p>External Content Projection:<ng-content></ng-content></p>',
  styleUrls: ['./app.component.css']
})
export class AppComponent { }

However, when trying this out, the result does not match the expected output. The rendered text ends up being:

  • External Content Projection:1111

This leads me to my question:

  • Is it feasible to apply content projection from outside the Angular application, similar to the example shared above?
  • If yes, then how can this be achieved? If no, what are the limitations?

Edit: Some may wonder about the purpose behind such integration. To provide some context: my Angular app includes customizable components for financial back-testing simulations. This involves fetching historical data, running tests, and displaying results graphically. I aim to showcase these simulations on platforms like WordPress, Dokuwiki, or even as static pages served by Apache. Here's a theoretical scenario:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Example Buy &amp; Hold Strategy</title>
    <base href="./">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
  </head>
  <body>
    <p>This simulation demonstrates a pure <em>Buy &amp; Hold</em> strategy, investing $100,001 in the S&amp;P500 from January 1, 2000, to January 1, 2020:</p>
    <app-root>
      <simulation start="2000-01-01" end="2020-4-9" quotes="SPY">
        <chart-report>
          <chart-report-configuration show="SPY.CLOSE" showDataAs="LINE" showDataOn="LEFT" normalize="true"></chart-report-configuration>
          <chart-report-configuration show="BAH.NAV" showDataAs="LINE" showDataOn="LEFT" normalize="true"></chart-report-configuration>
        </chart-report>
        <accounts>
          <swiss-quote id="BAH" cash="100000">
            <strategy>
              <buy-and-hold assetName="SPY"></buy-and-hold>
            </strategy>
          </swiss-quote>
        </accounts>
      </simulation>
    </app-root>
    <p/>Additional information goes here.</p>
  </body>
</html>

Answer №1

At the moment, Angular up to version 15 does not support injecting app-root content with ng-content. However, this feature is currently under consideration and there is an ongoing issue discussing it in more detail: https://github.com/angular/angular/issues/4946


One approach I've taken to display the Initial Loading Indicator is by initially placing the default app-root content outside the app-root element and then projecting it into the app component.

In index.html:

...
<body>
  <div id="initialization-container">
    Initializing...
  </div>
  <app-root></app-root>
</body>
...

In app.component.html:

<ng-container *ngIf="isInitializing$ | async; else appInitialized">
  <app-initialization-container/>
</ng-container>

<ng-template #appInitialized>
  APPLICATION
</ng-template>

In initialization-container.ts:

import {AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Renderer2} from '@angular/core';

@Component({
  selector: 'app-initialization-container',
  template: '',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class InitializationContainerComponent implements AfterViewInit {
  constructor(
    private render: Renderer2,
    private hostRef: ElementRef
  ) {
  }

  ngAfterViewInit() {
    const el = document.getElementById('initialization-container');
    if (el != null) {
      this.render.appendChild(this.hostRef.nativeElement, el);
    }
  }
}

Another option for handling the loading indicator scenario could be removing it from the DOM once the loading is complete. However, this example showcases how to project content into the application to suit your specific use-case.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Intro.js is not compatible with React and Remix.run

I am currently working on implementing onboarding modals for header links using intro.js within a React environment. Below is the code snippet: import { useState, type FC } from 'react' import type { Links } from '../types' import &apo ...

Encountering an error with the Next Auth adapter in TypeScript when attempting to modify the default User interface

This is my first time using TypeScript and I am attempting to customize the default User interface for next-auth. I have experimented with the following code: next-auth.d.ts import { User } from "next-auth" import { JWT } from "next-auth/j ...

What is the reason for TypeScript disabling unsecure/non-strict compiler rules by default?

Recently, I found myself having to enable a slew of compiler options in my application: "alwaysStrict": true, "extendedDiagnostics": true, "noFallthroughCasesInSwitch": true, "noImplicitAny", true, "noImplicitThis", true, "noImplicitReturns": true, "noUnu ...

Discover the method of sending individual row data to a component using *ngFor in Angular 4

I need assistance with Angular as I am not very experienced in it. Here is the HTML code that I have: <tbody> <tr *ngFor="let data of employeeFilterLists"> <td>{{data.Code}}</td> <td (clic ...

Unlocking the power of variables in Next.js inline sass styles

Is there a way to utilize SASS variables in inline styles? export default function (): JSX.Element { return ( <MainLayout title={title} robots={false}> <nav> <a href="href">Title</a> ...

Encountering a cloning error while using React Typescript and React Router DOM when calling props.history.push

When using props.history.push without passing state, everything works perfectly fine. However, when trying to pass data with state, an error occurs. The error message reads: DOMException: Failed to execute 'pushState' on 'History': func ...

Having trouble getting the installed datejs typings to work properly

As I delve into Typescript due to my interest in Angular 2, I have come across the datejs Javascript library. To incorporate it into my Angular 2 project, I went ahead and installed datejs via npm, ensuring that it is correctly listed in my package.json. A ...

What is the best way to merge an array into a single object?

I have an array object structured like this. [ { "name": "name1", "type": "type1", "car": "car1", "speed": 1 }, { "name": &q ...

What leads to the inability to utilize environment variables in this TypeScript app built with Vue 3?

Currently, I am developing a single page application utilizing Vue 3 and TypeScript. The main purpose of this app is to interact with an API. All the necessary information including the API's URL and key are stored in the 'src\env.js' f ...

Angular 2: Emptying input field value on click event

I am experiencing an issue with resetting my input values. I have a search bar with filter functions. When I enter a value, it displays a list below and I want to add a function to these links. When I click on one of them, it takes me to another component ...

A special function designed to accept and return a specific type as its parameter and return value

I am attempting to develop a function that encapsulates a function with either the type GetStaticProps or GetServerSideProps, and returns a function of the same type wrapping the input function. The goal is for the wrapper to have knowledge of what it is ...

Middleware for Redux in Typescript

Converting a JavaScript-written React app to Typescript has been quite the challenge for me. The error messages are complex and difficult to decipher, especially when trying to create a simple middleware. I've spent about 5 hours trying to solve an er ...

After installing Microsoft.AspNetCore.SpaTemplates::*, the Angular template seems to be missing

Today I decided to start using .Net and successfully installed the SDK. Following instructions, I ran the CLI command to install the SPA template: dotnet new --install Microsoft.AspNetCore.SpaTemplates::* Although the command ran without any errors, I co ...

Implementing rxjs switch between multiple observables

As I work with 2 observables, my goal is to retrieve a value from Observable1, then disregard it and only anticipate a value coming from Observable2. After that, repeat the process by getting a value from Observable1 once more, and so on. I am exploring w ...

Getting the current browser window in the renderer within Electron 14: A step-by-step guide

Previously, I utilized the code below to retrieve the current window from the renderer: import {remote, BrowserWindow} from 'electron'; export function getCurrentWindow(): BrowserWindow { return remote.getCurrentWindow(); } With electron 14 ...

The standard build.gradle settings for Ionic projects on Android

By default, in the platforms/android/build.gradle file, I have the following configuration: allprojects { repositories { google() jcenter() } //This replaces project.properties w.r.t. build settings project.ext { defa ...

Struggling with Primeng's KeyFilter functionality?

I've implemented the KeyFilter Module of primeng in my project. Check out the code snippet below: <input type="text" pInputText [(ngModel)]="price.TintCost" [pKeyFilter]="patternDecimal" name="tintCost" required="true" /> Take a look at my Typ ...

How to determine the return type based on the quantity of arguments passed to a rest parameter function

Is there a way to create an arrow function using rest parameters that can return different types based on the number of arguments passed? For example, I am looking to implement a safeId() function with the following return type variations: safeId() // () ...

What is the best way to implement a Promise Function within a For loop?

Here is a function called sendEmail: public async sendEmail (log: LogMessage): Promise<void> { nodemailer.createTestAccount(async () => { return ServiceFactory.getSystemService().getNetworkPreferences().then(async (networkPreferences) => ...

Trouble with Jest when trying to use route alias in Next.js with Typescript

Currently, I am developing a Next.js App (v13.2.3) using Typescript and have set up a path alias in the tsconfig.json. Does anyone know how I can configure the jest environment to recognize this path alias? // tsconfig.json { "compilerOptions": ...