Angular-cli 3rd party javascript stops working if I route to another component and then come back

Viewed 613

I am using angular-cli and I am working on a component that needs some javascript to move through a set of bootstrap tab-panes to create a "wizard" effect. The javascript works just fine if I navigate directly to the component (i.e. http://localhost:4200/bulklabels/new). However, if I navigate to another component (using the nav menu and router-outlet) and then back to the wizard component, the javascript stops working (i.e. I can no longer move through the tab-panes using the next/prev buttons). If I refresh the page, it starts working again.

Here is the output of ng -v on my project

@angular/cli: 1.0.5
node: 6.10.3
os: win32 x64
@angular/common: 4.1.3
@angular/compiler: 4.1.3
@angular/core: 4.1.3
@angular/forms: 4.1.3
@angular/http: 4.1.3
@angular/platform-browser: 4.1.3
@angular/platform-browser-dynamic: 4.1.3
@angular/router: 4.1.3
@angular/cli: 1.0.5
@angular/compiler-cli: 4.1.3 

I am also using Bootstrap 4 alpha 6, if that is relevant.

I am loading the custom javascrpt from the scripts section of the angular-cli.json file, as shown below.

  "scripts": [
    "../node_modules/jquery/dist/jquery.min.js",          
    "../node_modules/tether/dist/js/tether.min.js",
    "../node_modules/bootstrap/dist/js/bootstrap.min.js",
    "assets/js/site.js"
  ],

The site.js file is my custom javascript.

Here is the custom javascript in site.js

$(document).ready(function () {

    //Wizard
    $('a[data-toggle="tab"]').on('show.bs.tab', function (e) {

        var $target = $(e.target);

        if ($target.parent().hasClass('disabled')) {
            return false;
        }
    });

    $(".next-step").click(function (e) {

        var $active = $('.nav-tabs li>a.active');
        $active.parent().next().removeClass('disabled');
        nextTab($active);

    });

    $(".prev-step").click(function (e) {

        var $active = $('.nav-tabs li>a.active');
        prevTab($active);

    });
});

function nextTab(elem) {
    $(elem).parent().next().find('a[data-toggle="tab"]').click();
}

function prevTab(elem) {
    $(elem).parent().prev().find('a[data-toggle="tab"]').click();
}

Here are the buttons that are associated with the javascript, from the ...component.html template file

<ul class="list-inline pull-right">
    <li class="list-inline-item">
        <button type="button" class="btn btn-primary prev-step">Previous</button>
    </li>
    <li class="list-inline-item">
        <button type="button" class="btn btn-primary next-step">Next</button>
    </li>
</ul>

Here is my navbar.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'masc-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

Here is my navbar.component.html

<div>
    <nav class="navbar navbar-toggleable-sm navbar-inverse cd-navbar-background">

      <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText"
          aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>

      <a class="navbar-brand mr-5" href="#">
        <img class="cd-logo-image" alt="Confirm Delivery logo">
      </a>

      <div class="collapse navbar-collapse" id="navbarText">

        <div class="nav bar-nav mr-auto">
          <a class="nav-item nav-link active" href="#"><i class="fa fa-home mr-1" aria-hidden="true"></i>Home<span class="sr-only">(current)</span></a>

          <div class="dropdown">
            <a class="nav-item nav-link dropdown-toggle" href="#" id="navbarTasksDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              <i class="fa fa-gears mr-1" aria-hidden="true"></i>
              Tasks
            </a>
            <div class="dropdown-menu" aria-labelledby="navbarTasksDropdownMenuLink">
              <a class="dropdown-item nav-link"[routerLink]="['bulklabels/about']">Bulk Labels</a>
              <a class="dropdown-item nav-link"[routerLink]="['bulklabels/new']">Create Bulk Label</a>
              <a class="dropdown-item" href="#">Users</a>
            </div>  
          </div>

          <a class="nav-item nav-link" href="#"><i class="fa fa-lock mr-1" aria-hidden="true"></i>Admin</a>


        </div>


        <span class="navbar-text login">
          <a href="#" ><i class="fa fa-user mr-1" aria-hidden="true"></i>Login</a>
        </span>


      </div>
    </nav>
  </div>

Here is my app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { HomeComponent } from './home/home.component';
import { BulkLabelsComponent } from './bulk-labels/bulk-labels.component';
import { CreateBulkLabelComponent } from './bulk-labels/create-bulk-label/create-bulk-label.component';

const routes: Routes = [
      { path: 'home', component: HomeComponent},
      { path: 'bulklabels/about', component: BulkLabelsComponent},
      { path: 'bulklabels/new', component: CreateBulkLabelComponent},
      { path: '', redirectTo: 'home', pathMatch: 'full' },
];

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

Thanks in advance for any help you can provide.

1 Answers
declare var jQuery: any;
declare var $: any;

Add these declarations with your imports and add the code inside the ready function inside your OnInit

Related