Walkaround for using html rendered by server in an Angular application

We have, unfortunately a multi page application that we’ve been running with AngularJS. Now we’re trying to migrate to Angular, as LTS approaches. We used to populate some part of our templates with the server data, rendering html as follows:

<div class="some-class" ng-controller="SomeCtrl as ctrl">
    <div>...</div> <!-- Render some data from server -->
    <div sec:authorize="isRememberMe()">...</div> <!-- Use some Thymeleaf security tags -->
</div>

However, now that the components are already on the client, I’m looking for ways to manipulate templates with html rendered by the server. I’ve tried with ng-content which is useful for some cases, where I can bootstrap the component itself outside app-root like Render Angular component outside the main app. But when the template is in component itself, this ability is gone as well.

An alternative would be rendering the page as a non-Angular, conventional html page (not a component), and accessing some basic functionality that could be provided by Angular. The approach we used in the past as well allowed this, but I have no idea how I could achieve this.

Is there a walkaround for what I’m looking for?

Answer

Here’s what I come up with:

Render the index.html with Thymeleaf as follows:

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<head th:replace="partials/head :: head"></head>
<body>
    <th:block th:replace="partials/header :: header"></th:block>
    <app-root th:attr="some-property=${some.value.from.model}"></app-root>
    <th:block th:replace="partials/footer :: footer"></th:block>
</body>

This will render:

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<head>
    ...
</head>
<body>
    ...
    <app-root some-property="some-value"></app-root>
    ...
</body>

Create a data.service.ts:

  appData: any = {};

And in app.component.ts:

constructor(private dataService: DataService,
            private element: ElementRef) {
}

ngOnInit(): void {
    this.dataService.appData['some-property'] = this.element.nativeElement.getAttribute('some-property');
}

Finally in sub.component.ts:

constructor(private dataService: DataService) {
}

ngOnInit(): void {
    this.someProperty = this.dataService.appData['some-property'];
}

Leave a Reply

Your email address will not be published. Required fields are marked *