Home > front end >  Page is not displaying properly until manually refresh Angular
Page is not displaying properly until manually refresh Angular

Time:04-01

I m facing very strange issue. My angular application page is displaying properly. It seems its not fully loaded, and when I m manually reloading/refreshing the page, its loading fine.

Here is the full scenario. I created a login page which displays perfectly and working as expected. After login I m navigating to my dashboard page which is not showing properly, seems half loaded, but when manually refresh its work fine. After inspecting elements, I found that the contents of dashboard is there but not showing properly. there is no any error in console as well

Here is my app-routing.module.ts code:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { MainLayoutComponent } from './main-layout/main-layout.component';

const routes: Routes = [

  { path: 'login', component: LoginComponent },
  { path: 'dashboard', component: MainLayoutComponent },
  { path: '', pathMatch: "full", redirectTo: 'dashboard' },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

And here is my login.component.ts

declare var $: any;
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Common } from '../Common/common';
import { Router } from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class LoginComponent implements OnInit {
  constructor(private httpClient: HttpClient, private router: Router) { }

  form: any;

  submitModel: any = {
    username: "",
    password: ""
  };

  ngOnInit(): void {
    this.form = $('#myloginform').parsley();

    localStorage.clear();
  }

  SubmitForm() {
    if ($("#myloginform").parsley().validate()) {
      $(".preloader").show();
      this.httpClient.post<any>(Common.APIUrl   "login", this.submitModel, { withCredentials: true }).subscribe(
        {
          next: data => {
            console.log(data);
            localStorage.setItem("token", data.result);
            this.router.navigate(['dashboard']);
          },
          error: error => {
            console.error(error);
          },
          complete: function () {
            console.log("complete");
            $(".preloader").hide();
          }
        }
      );
    }
  }
}

Here is my main-layout.component.ts

declare var $: any;
import { HttpClient } from '@angular/common/http';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Router } from '@angular/router';
import { Common } from '../Common/common';

@Component({
  selector: 'app-main-layout',
  templateUrl: './main-layout.component.html',
  styleUrls: ['./main-layout.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class MainLayoutComponent implements OnInit {
  constructor(private httpClient: HttpClient, private router: Router) { }

  ngOnInit(): void {
    console.log("MainLayoutComponent - on init called")
  }


  Logout() {
    $(".preloader").show();
    this.httpClient.get<any>(Common.APIUrl   "logout", { withCredentials: true }).subscribe(
      {
        next: data => {
          localStorage.clear();
          this.router.navigate(['login']);
        },
        error: error => {
          console.error(error);
        },
        complete: function () {
          $(".preloader").hide();
        }
      }
    );
  }
}

Currently facing like this: enter image description here

Expected result: enter image description here

Additional Info: when I m logging out, its navigating to Login page properly. I have added all references of jQuery/Bootstrap additional plugin in my index html page.

I m new to angular and this is my first question in StackOverflow. Please forgive me, if I couldn't explain better. Thanks in advance

I removed the content from Dashboard and just added one <h1> tag. it is displaying

Index.html

<!DOCTYPE html>
<html dir="ltr" lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <!-- Tell the browser to be responsive to screen width -->
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="robots" content="noindex,nofollow">
  <base href="/">
  <title>Employee App</title>
  <!-- Favicon icon -->
  <link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicon.png">
  <!-- Custom CSS -->
  <link href="assets/dist/css/style.min.css" rel="stylesheet">
  <link href="assets/dist/css/style.extended.css" rel="stylesheet">
</head>
<body>

  <app-root></app-root>

  <script src="assets/libs/jquery/dist/jquery.min.js"></script>
  <!-- Bootstrap tether Core JavaScript -->
  <script src="assets/libs/popper.js/dist/umd/popper.min.js"></script>
  <script src="assets/libs/bootstrap/dist/js/bootstrap.min.js"></script>
  <!--Parsley -->
  <script src="assets/extra-libs/parsley/parsley.js"></script>
  <!-- apps -->
  <script src="assets/dist/js/app.min.js"></script>
  <script src="assets/dist/js/app.init.js"></script>
  <script src="assets/dist/js/app-style-switcher.js"></script>
  <!-- slimscrollbar scrollbar JavaScript -->
  <script src="assets/libs/perfect-scrollbar/dist/perfect-scrollbar.jquery.min.js"></script>
  <script src="assets/libs/jquery-sparkline/jquery.sparkline.min.js"></script>
  <!--Wave Effects -->
  <script src="assets/dist/js/waves.js"></script>
  <!--Menu sidebar -->
  <script src="assets/dist/js/sidebarmenu.js"></script>
  <!--Custom JavaScript -->
  <script src="assets/dist/js/feather.min.js"></script>
  <script src="assets/dist/js/custom.min.js"></script>
</body>
</html>

MainLayout.component.html

<div id="main-wrapper">
  <header >
    <nav >
      <div >
        <a  href=""><i ></i></a>
        <a  href="">
          <b >
            <img src="../assets/images/logo-icon.png" alt="homepage"  />
            <img src="../assets/images/logo-light-icon.png" alt="homepage"  />
          </b>
          <span >
            <img src="../assets/images/logo-text.png" alt="homepage"  />
            <img src="../assets/images/logo-light-text.png"  alt="homepage" />
          </span>
        </a>
        <a  href="" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><i ></i></a>
      </div>
      <div  id="navbarSupportedContent">
        <ul >
          <li ><a  href="" data-sidebartype="mini-sidebar"><i ></i></a></li>
        </ul>
        <ul >
          <li >
            <a  href="" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><img src="../assets/images/users/1.jpg" alt="user"  width="31"></a>
            <div >
              <div >
                <div ><img src="../assets/images/users/1.jpg" alt="user"  width="80"></div>
                <div >
                  <h4 >Steave Jobs</h4>
                  <p >[email protected]</p>
                  <a href="profile.html" >View Profile</a>
                </div>
              </div>
              <a  href="" (click)="Logout()"><i ></i> Logout</a>
            </div>
          </li>
        </ul>
      </div>
    </nav>
  </header>

  <aside >
    <div >
      <nav >
        <ul id="sidebarnav">
          <li ><i ></i> <span >Personal</span></li>
          <li >
            <a href=""  aria-expanded="false"><i data-feather="link" ></i><span >Sample Link</span></a>
          </li>
          <li >
            <a  href="" aria-expanded="false"><i data-feather="map" ></i><span >Sample Link</span></a>
            <ul aria-expanded="false" >
              <li ><a href="map-google.html" ><i ></i><span >Google Maps</span></a></li>
              <li ><a href="map-vector.html" ><i ></i><span >Vector Maps</span></a></li>
            </ul>
          </li>
          <li >
            <a  href="" aria-expanded="false"><i data-feather="git-pull-request" ></i><span >Multi level dd</span></a>
            <ul aria-expanded="false" >
              <li ><a href="" ><i ></i><span >item 1.1</span></a></li>
              <li ><a href="" ><i ></i><span >item 1.2</span></a></li>
              <li >
                <a  href="" aria-expanded="false"><i ></i> <span >Menu 1.3</span></a>
                <ul aria-expanded="false" >
                  <li ><a href="" ><i ></i><span > item 1.3.1</span></a></li>
                  <li ><a href="" ><i ></i><span > item 1.3.2</span></a></li>
                  <li ><a href="" ><i ></i><span > item 1.3.3</span></a></li>
                  <li ><a href="" ><i ></i><span > item 1.3.4</span></a></li>
                </ul>
              </li>
              <li ><a href="" ><i ></i><span > item 1.4</span></a></li>
            </ul>
          </li>
        </ul>
      </nav>
    </div>
    <div >
      <a href=""  data-toggle="tooltip" title="Settings"><i ></i></a>
      <a href=""  data-toggle="tooltip" title="Email"><i ></i></a>
      <a href=""  data-toggle="tooltip" title="Logout"><i ></i></a>
    </div>
  </aside>
  <div >

    <!--<router-outlet></router-outlet>-->

    <footer >
      © 2020 Monster Admin by wrappixel.com
    </footer>
  </div>
</div>

CodePudding user response:

Where you localStorage.getItem("token")? where you're use?.

If you use in the MainLayoutComponent I imagine you get in the ngOnInit of this component.

If you're use in other component -perhafs in the main.component that is who has the <router-outlet>- already loaded you need indicate to Angular that localStorage has changed. Generally you can use a Subject of one service. That's:

Imagine you has a service. As you should makes all the calls in a service, not in a component, you can have a services like

@Injectable({
  providedIn: 'root',
})
export class LoginService {
  login$:Subject<bool>=new Subject<bool>()
  constructor(private httpClient:HttpClient) { }

  login(model:any)
  {
      return this.httpClient.post<any>(Common.APIUrl   "login", model, { withCredentials: true })
       .pipe(tap(()=>{
            this.login$.next(true); //<--makes subject "next"
       })
      );
     
  }
  logout()
  {
    return this.httpClient.get<any>(Common.APIUrl   "logout", { withCredentials: true })
       .pipe(tap(()=>{
            this.login$.next(false); //<--makes subject "next"
       })
    )
  }

See that the functions return an observable -the call to your API-

When you subscribe to your LoginService -replace the httpClient.get by this.loginService.login() and this.loginService.logout()-

  SubmitForm() {
    if ($("#myloginform").parsley().validate()) {
      $(".preloader").show();
      this.loginService.login(this.submitModel)
        .subscribe(
         {
            ..your code..
         })
      );
    }
  }

And

Logout() {
    $(".preloader").show();
    this.loginService.logOut().subscribe(
      {
         ...your code
      }
    );
  }

See that, the "subject" change. So in the component where you need the information of the token you can subscribe to this subject and read the token

this.loginService.login$.subscribe((res:boolean)=>{
    ..make something to updte the "login"
})

CodePudding user response:

Thank you @The Head Rush for putting me right direction. I m using a bootstrap theme which is not designed for Angular. After digging some Theme js files, I saw some code which is using jQuery code to implement some classes on runtime based on Theme selection. I just called its theme setting function back again, and its works. In my mainlayout component init function, I added this code

  ngOnInit(): void {
    $("#main-wrapper").AdminSettings();
  }
  • Related