2

I fetch my Dashboard HTML data using the following code which is executed when I click a button:

fetchDashboard() {
    const requestOptions: Object = {
      headers: new HttpHeaders().append('Authorization', 'Bearer <tokenhere>'),
      responseType: 'text'
    }
    this.http.get<string>('http://localhost:3000/avior/dashboard',
        requestOptions)
            .subscribe(response => {
                   this.dashboardData = response;
            }
    );
}

I have multiple components setting up my view and I want to modify one of the views completely from scratch to contain the fetched content, how do I do that?

As recommended here I tried using <div [innerHtml]="dashboardData"></div> without any avail.


UPDATE

My admin nav.ts looks like this:

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';

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

  dashboardData: string;


  constructor(private http: HttpClient) { }

  ngOnInit() {console.log('dashboardData: ', this.dashboardData);


  }
  fetchDashboard() {

    const requestOptions: object = {
      // tslint:disable-next-line: max-line-length
      headers: new HttpHeaders().append('Authorization', 'Bearer tokenhere'),
      responseType: 'text'
    };
    this.http.get<string>('http://localhost:3000/avior/dashboard',
        requestOptions)
            .subscribe(response => {
                   console.log(response);
                   this.dashboardData = response;
            }
    );
}

}

My dashboard component.ts looks like this:

import { Component, OnInit, Input } from '@angular/core';
import { User } from '../models/user.model';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})

export class DashboardComponent implements OnInit {
  /* @Input() */ dashboardData: string;
  user: User;
  // dashboardData: string;
  constructor() { }

  ngOnInit() {
    console.log('dashboardData in dashboard comp: ', this.dashboardData);
  }

  canDeactivate(): Promise<any> | boolean {
    if (localStorage.getItem('currentUserToken') === 'token') {
            return (true);
          } else {
            return (false);
          }

}
}

My dashboard component HTML looks like this:

<p>
  Welcome and please replace me with dashboard text!
</p>
<div [innerHtml]="dashboardData"></div>
<div *ngIf="this.dashboardData" [innerHtml]="dashboardData">Test {{this.dashboardData}}</div>

My admin nav HTML looks like this:

                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Administration
                    </a>
                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <a class="dropdown-item" (click)=fetchDashboard()>Dashboard</a>
                        <a class="dropdown-item" [routerLink]="['/avior/users']">Users</a>
                        <a class="dropdown-item" [routerLink]="['/avior/workflows']">Workflows</a>
                        <div class="dropdown-divider"></div>
                        <a class="dropdown-item" [routerLink]="['/avior/system']">System</a>
                    </div>
                </li>

My avior.component.html looks like this:

<div>
    <router-outlet></router-outlet>
</div>

My app.component.html looks like this:

<!-- Navigation -->
<div class="navigation">
    <nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">

        <!-- Brand - Logo + Title -->
        <a class="navbar-brand">
            <img width="25" src="../assets/images/app_logo.jpg">
            <a class="navbar-brand" [routerLink]="['/avior/dashboard']">&nbsp;&nbsp;=== Application ===</a>
        </a>

        <!-- Menu -->
        <div class="collapse navbar-collapse" id="navbarSupportedContent">

            <!-- Menu left -->
            <ul class="navbar-nav mr-auto">

                <!-- Menu App -->
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Application
                    </a>
                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <a class="dropdown-item" [routerLink]="['/carinae/list-content']">Mask 1</a>
                        <a class="dropdown-item" [routerLink]="['/carinae/tree-tab']">Mask 2</a>
                        <div class="dropdown-divider"></div>
                        <a class="dropdown-item" [routerLink]="['/carinae/app-settings']">App Settings</a>
                    </div>
                </li>

                <!-- Menu Admin-->
                <app-avior-admin-nav></app-avior-admin-nav>
            </ul>

            <!-- Menu right -->
            <app-avior-user-nav></app-avior-user-nav>
        </div>
    </nav>
</div>

<!-- Content / Output -->
<div class="content">
    <router-outlet></router-outlet>
</div>

Munchkin
  • 857
  • 5
  • 24
  • 51

1 Answers1

1

If the response of the request returns HTML as a string, you'll just have to correct your binding to the template. Replace :

<div [innerHtml]="this.dashboardData"></div>

by

<div [innerHTML]="dashboardData"></div>

If you check the link provided in your question, a binding in HTML never calls the this keyword.

EDIT

Now that the code is included, your admin-nav component gets the dashboardData, and stores it in its dashboardData member. But it was never transmitted to your dashboardComponent. Now :

DashboardComponent.ts : Uncomment the @Input().

DashboardComponent.html : Correct *ngIf="dashboardData"

Nav.html : add a <app-dashboard [dashboardData]="dashboardData"></app-dashboard>

faflo10
  • 386
  • 5
  • 13
  • It for some reason does nothing. How do I debug this? – Munchkin Nov 20 '19 at 11:57
  • In the .subscribe callback, have you checked if the response contained what was expected ? If not, try to put a `console.log(result)` here – faflo10 Nov 20 '19 at 12:00
  • Yes, the response contains what is expected, I already tested it with `console.log` – Munchkin Nov 20 '19 at 12:10
  • The problem is that the `
    ` displays nothing. Maybe the value doesn't get passed to the div? How do I debug that?
    – Munchkin Nov 20 '19 at 12:21
  • Try inspecting the div in your browser and see how the innerHTML is parsed. If you still cant figure it out then please share the response (or a snippet of it to debug) – hagner Nov 20 '19 at 12:42
  • I also tried adding return like this without any avail: `return this.dashboardData = response;` – Munchkin Nov 20 '19 at 12:42
  • @hagner the response is `Dashboard

    Dashboard works!

    `. I can't find anything added into the DOM with the Firefox debugger ( I am only checking the DOM, not the .js files)
    – Munchkin Nov 20 '19 at 12:45
  • Is your `fetchDashboard()` method in a service or in the .ts file of your component (the one containing the template with the `
    `)?
    – faflo10 Nov 20 '19 at 13:06
  • If the method is contained in the component .ts file, it should work. See [here](https://stackblitz.com/edit/angular-gdgusy) for a quick repro of your problem. The `of(result).pipe(delay(2000))` in `fetchDashboard()` is here to simulate a (long) webRequest that returns the content of the `result` constant. – faflo10 Nov 20 '19 at 13:22
  • @faflo10 the fetchDashboard() method is in the component.ts file. The only difference between the StackBlitz and my files appears to be that in your case the var result is statically defined. What am I doing wrong? – Munchkin Nov 20 '19 at 13:30
  • I edited the stackblitz to let the subscription to the Observable store its result inside the `dashboardData` member, and it still works fine... Without seeing the code, I may have two guesses : 1. Is there something that reset the dashboardData value to null or an empty string ? 2. If you check the network tab, does your request appear after clicking the button ? – faflo10 Nov 20 '19 at 13:40
  • @faflo10 1. I'm guessing that's the case please check the updated question, I don't know how to determine why that is happening. 2. Networking is fine, a XHR response is visible, we already debugged that with `console.log(response);` – Munchkin Nov 20 '19 at 13:54
  • I am finding that you can't load components after angular bootstrap has been called. Maybe that's the issue? – Munchkin Nov 20 '19 at 14:02
  • @faflo10 `'app-dashboard' is not a known element: 1. If 'app-dashboard' is an Angular component, then verify that it is part of this module. 2. If 'app-dashboard' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.`, `Can't bind to 'dashboardData' since it isn't a known property of 'app-dashboard'. 1. If 'app-dashboard' is an Angular component and it has 'dashboardData' input, then verify that it is part of this module. 2. If 'app-dashboard' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule...` – Munchkin Nov 20 '19 at 14:10
  • I edited the stackblitz link. If the nav template cannot contains the dashboard tag (for instance if it is a parent that calls the nav component, then the dashboard), tell me, I'll update the link again. – faflo10 Nov 20 '19 at 14:11
  • Did you include, declare and export the DashboardComponent in the Angular Module ? – faflo10 Nov 20 '19 at 14:13
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/202731/discussion-between-munchkin-and-faflo10). – Munchkin Nov 20 '19 at 14:16