Search code examples
angularapiangular-ui-router

How to push additional routes from backend API on app initizalzation


I am writing something similiar to CMS. I have two apps. Backend written in Django and a SPA in angular 7. I the backend part I have views that that list-pages and retrieve-page

On sending request to http://127.0.0.1:8000/pages-management/pages returns json with data:

[
  {
    "id": 1,
    "title": "some title 1",
    "section": "section1",
    "urlKey": "some_title_1"
  },
    {
    "id": 2,
    "title": "some title 2",
    "section": "section2",
    "urlKey": "some_title_2"
  },
]

On sendint request to:

http://127.0.0.1:8000/pages-management/pages/some_title_1

It returns:

{
  "id": 1,
  "title": "some_title_1",
  "section": "section1",
  "urlKey": "some_title_1",
  "content": "<p>html content</p>"
}

What I want to achieve?

I would like to be to load data from /pages-management/pages on angular app start and the data to create routes from it.

In the first attempt I tried to add those routes during my header component initialization:

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  currentUserEmail: string;
  pages: Page[];

  constructor(private authService: AuthService, private pageService: PageService, private router: Router) {
  }

  ngOnInit() {
    // TODO remove the property this.authService.currentUserEmail and export currentUserEmail from localstorage?
    this.currentUserEmail = this.authService.currentUserEmail;

    this.pageService.getPages().subscribe(data => {
      this.pages = data;
      const data = this.router.config.filter(value => value.path === 'children')[0].children;
      this.pages.forEach(item => {
        data.push({path: item.urlKey, component: PageComponent});
      });
    }, error1 => {
    });
  }
} 

  <div class="nav-item mr-2">

        <div class="row">
          <div class="col">
            <div ngbDropdown class="d-inline-block">
              <button class="btn btn-light" id="studentZoneDropDown" ngbDropdownToggle>
                Strefa Studenta
              </button>
              <div ngbDropdownMenu aria-labelledby="dropdownBasic1">
                <button class="dropdown-item" [routerLink]="['strefa-studenta', page.urlKey]"
                        *ngFor="let page of pages">{{page.title}}</button>
              </div>
            </div>
          </div>
        </div>
      </div>

It almost works when I let the app to load and enter the url through link in my navigation bar. The problem is when I try directly to enter the url through browser link http://localhost:4200/children/some_title_1 It dosent work. But navigating from http://localhost:4200 to http://localhost:4200/children/some_title_1 through link in the navbar is possible.

The question is how to achieve this goal?


Solution

  • If you want to perform data loading when your application startup, you can use the APP_INITIALIZER injection token:

    @NgModule({
       ...
       providers: [
          {
              provide: APP_INITIALIZER,
              useFactory: initializeApplication,
              deps: [/* Add dependencies here */],
              multi: true
          }
       ]
    })
    export class AppModule {}
    
    export function initializeApplication(/* Inject dependencies here */) {
        return () => {
            // TODO: send http request or execute promises.
        };
    }
    

    Find more informations here: https://www.tektutorialshub.com/angular/angular-how-to-use-app-initializer/

    Hope it helps.