How do i rebind the javascript to elements in angular2 component? - javascript

I have defined some custom scripts in javascript file for my angular2 application. When i navigate to other component and come back to previous one, the scripts are not being binded to the html elements since the js file is not loaded the second time. How can i rebind the scripts to the html elements of a component in angular2? Or reload the js file needed by the component every time i navigate to that component?
Updated with Code
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<my-app></my-app>
</body>
</html>
myjs.js
$(document).ready(function() {
$('#btnNext').click(function(){
$('#myModal').modal('show');
});
});
vendor.ts
// Angular
import '#angular/platform-browser';
import '#angular/platform-browser-dynamic';
import '#angular/core';
import '#angular/common';
import '#angular/http';
import '#angular/router';
// RxJS
import 'rxjs';
// Other vendors for example jQuery, Lodash or Bootstrap
// You can import js, ts, css, sass, ...
import '../public/css/bootstrap.css';
import '../public/css/style.css';
import '../public/js/bootstrap.js';
import '../public/js/myjs.js';
modal.component.ts
import { Component } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'my-modal',
template: `
<button type="button" id="btnNext" class="btn btn-primary btn-lg">
Launch demo modal
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<button class="btn btn-secondary btn-lg" (click)="goToNextView()">Go to next view </button>
`
})
export class ModalComponent {
constructor(
private router: Router
){}
goToNextView(){
this.router.navigate(['/next']);
}
}
next-view.component.ts
import { Component } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'my-view',
template: `
<b>Hello this is my next route.</b>
<button class="btn-secondary btn-lg" (click)="goToModal()">Go Back</button>
`
})
export class NextViewComponent {
constructor(
private router: Router
){}
goToModal(){
this.router.navigate(['/']);
}
}
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { ModalComponent } from './modal.component'
import { NextViewComponent } from './next-view.component';
const routes: Routes = [
{
path:'',
redirectTo: '/',
pathMatch: 'full'
},
{
path:'',
component: ModalComponent
},
{
path: 'next',
component: NextViewComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule { }
app.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { BrowserModule } from '#angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ModalComponent } from './modal.component';
import { NextViewComponent } from './next-view.component';
#NgModule({
imports: [
BrowserModule,
CommonModule,
AppRoutingModule
],
declarations: [
AppComponent,
ModalComponent,
NextViewComponent
],
bootstrap: [AppComponent]
})
export class AppModule{}
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `<router-outlet></router-outlet>`
})
export class AppComponent {}
Initially my app looks like this :
when i click the Launch demo modal:
when i navigate to 'next' route:
when i click 'Go Back' and come to the initial page then my modal wont open. I did a lot of research on that and found that the js i have include is not binded to the element of the component when i navigate back to that component.
SO HOW CAN I REBIND MY JS TO THE ELEMENTS? If it is not how we do things in angular2 then please guide me to how to do it correctly.

It seems that i can include the trigger script in the ngAfterViewInit() to get it working.
Here is how i did it:
modal.component.ts
import { Component, AfterViewInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'my-modal',
template: `
<button type="button" id="btnNext" class="btn btn-primary btn-lg">
Launch demo modal
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<button class="btn btn-secondary btn-lg" (click)="goToNextView()">Go to next view </button>
`
})
export class ModalComponent implements AfterViewInit{
constructor(
private router: Router
){}
goToNextView(){
this.router.navigate(['/next']);
}
ngAfterViewInit(){
$('#btnNext').click(function(){
$('#myModal').modal('show');
});
}
}
Remember that typescript will show the error for $ and modal. But it will work. The error will only be shown in console. But if you don't want to see any error in the console also, then just install typings for bootstrap and jquery
npm install #types/jquery --save-dev
and
npm install #types/bootstrap --save-dev
and you will have to import jquery in vendor.ts as:
import * as $ from 'jquery';
and that is it. No error and working scripts.
It is recommended not to use JQUERY in angular2 application. You can use
ng2-bootstrap or ng-bootstrap
I only did it due to time constraint of the project.

Related

Navigate to component in another module (Angular)

I have app.component which is creating by default and here is a button. When I click it, I want to go to login.component.
Here is my app.module.ts file
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing/app-routing.module';
import { AppComponent } from './app.component';
import { MatButtonModule } from '#angular/material/button';
import { MainModule } from './main/main.module';
#NgModule({
declarations: [AppComponent],
imports: [BrowserModule, MatButtonModule, MainModule, AppRoutingModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Here is my app-routing.module.ts code
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { LoginComponent } from '../main/login/login.component';
const routes: Routes = [
{ path: 'main', children: [{ path: 'login', component: LoginComponent }] },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Here is how I try to do this - <button mat-raised-button class="btn-default" [routerLink]="['/main/login']">Log in</button>
Here is stackblitz url to check code Stackblitz
My problem is, that link changed to localhost:4200/main/login, but view not changed.
How I can solve this?
This is a CSS issue. split left and spit right do not give the login component inside any space. Instead, have your main page (main-page) (the page with the login and sign up button) as its own component, and have split right only having the router outlet.
app.component.html
<div class="split left">
<div class="centered">
<h1>Learn what you want.</h1>
<h1>Teach what you love.</h1>
</div>
</div>
<div class="split right">
<router-outlet></router-outlet>
</div>
main-page.component.html
<div class="centered">
<div>
<button mat-raised-button class="btn-default" [routerLink]="['/main/login']">Log in</button>
</div>
<div style="margin-top: 20px">
<button mat-raised-button class="btn-default-transparent">Sign up</button>
</div>
</div>
I created a bug-fixed version here for you: Stackblitz
Your problem was that it loaded but behind the app.component.html template.
You created a main module for LoginComponent. When You have more than one module the best practice is to use Lazy Loading which I created for you on my demo. In addition, it's better that app-component, mean main app just have <router-outlet></router-outlet> and content loads from other component.
So the problem was not in CSS
Problem was that I need to have all components to be separate and have <router-outlet></router-outlet> only in app.component.ts file.

React bootstrap modal doesn't show up

Cant make my modal works. Everything seems set up.
Can somebody help me? It must be something trivial
because here
similar set up and it works. Its like my bootstrap is not loaded
from index.html.
I have in index.html my bootstrap js and css.
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<div id="root"></div>
App.js
import React, { Component } from 'react';
import './App.css';
import Home from './Home';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import GroupList from './GroupList';
class App extends Component {
render() {
return (
<Router>
<Switch>
<Route path='/' exact={true} component={Home}/>
<Route path='/groups' exact={true} component={GroupList}/>
</Switch>
</Router>
)
}
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './App.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
GroupList.js where is my modal
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">
Open modal
</button>
<div class="modal" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Modal Heading</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
Modal body..
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
I would also advise you to implement "reactstrap" library. Then use state to control if the modal should be opened.

When I import the formsmodule in angular my button seems to not working after that

When I imported this "import { FormsModule } from '#angular/forms';" on my angular project. it seems that my button is not working anymore. if I click on it there's nothing.
This is my app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
#NgModule({
declarations: [
AppComponent,
HomeComponent,
AboutComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
This is My Home HTML
the button class is btn
<div class="container color-dark">
<div class="col">
<p>Add you Bucket List</p>
</div>
<div class="col">
<p>Your Bucket List ({{ itemCount }})</p>
</div>
</div>
<div class="container color-light">
<div class="col">
<p>Use this form to add a new Bucket List!</p>
<form>
<input type="text" class="txt" name="item" placeholder="Life Goal.." [(ngModel)]="goalText">
<input type="submit" class="btn" value="Add Item" (click)="addItem()">
</form>
</div>
<div class="col">
<p class="life.container">
I want to climb a mountain.
</p>
</div>
</div>
This is My home.compenent.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
itemCount: number;
btnText: string = 'Add an Item';
goalText: string = 'My First Life Goal';
goals = [];
constructor() { }
ngOnInit() {
this.itemCount = this.goals.length;
}
additem(){
this.goals.push(this.goalText);
this.goalText = '';
this.itemCount = this.goals.length;
}
}
I tried searching it on google but nothing pops up or am I just looking at the wrong side of the code. if you have an idea or tips that can help me solve this, I would really appreciate it
in home.components.ts correct the function name from additem() to addItem() it will work . capital I should be used that's why it's not working

How to open component content into bootstrap modal?

I have component that i want to inject into modal window using ng bootstrap features so i have imported modules into app also added into entrypoints as suggested in ng-bootstrap docs its giving me little hard time. what is correct approach basically i am calling modal from existing component and that component content should load into modal window. any help will be appreciate.
modal.component.ts
import {Component, Input} from '#angular/core';
import {NgbModal, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'ngbd-modal-content',
template: `
<div class="modal-header">
<h4 class="modal-title">Hi there!</h4>
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Hello, {{name}}!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
</div>
`
})
export class NgbdModalContent {
#Input() name;
constructor(public activeModal: NgbActiveModal) {}
}
detail.component.ts
import { Component, OnInit,Pipe, PipeTransform, EventEmitter,Input, Output,OnChanges, SimpleChanges } from '#angular/core';
import {NgbModal,NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css'],
})
export class DetailComponent implements OnChanges{
constructor(private detailService: DetailService,private ngbModal: NgbModal) {};
onClick(evt){
const modalRef = this.ngbModal.open(Component);
}
}
detail.component.html
<div class="card card-outline-info">
<div class="card-header bg-info"><h5>Detail</h5><button (click)="onClick($event)"></button></div>
<div class="card-block">
<div class="table-responsive" style="cursor: pointer">
<generic-table [gtClasses]="'table-hover'" #myCustomTable [gtSettings]="secondConfigObject.settings" [gtFields]="secondConfigObject.fields" [gtData]="secondConfigObject.data"></generic-table>
</div>
</div>
</div>
app.module.ts
import { NgbModule,NgbActiveModal } from '#ng-bootstrap/ng-bootstrap';
import { NgbdModalContent } from './NgModal/modal.component';
#NgModule({
declarations: [
AppComponent,
StreamComponent,
SearchComponent,
DetailComponent,
SlaChartComponent,
NgbdModalContent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
HttpModule,
ChartsModule,
BrowserAnimationsModule,
NgbModule.forRoot()
],
providers: [StreamService,DatePipe,
SearchService,
DetailService,
ChartService,AuthService,NgbActiveModal,
{provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true}],
entryComponents: [NgbdModalContent,DetailComponent],
bootstrap: [AppComponent]
})
Try this, I'm not a fan of your modal.component.ts file so scrap that and remove the NgbdModalContent from your app.module.ts
yourModal.component.html
<ng-template #theModal let-c="close" let-d="dismiss">
<div class="modal-header">
<h4 *ngIf="type == 0" class="modal-title">Header</h4>
<button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Hello, {{name}}!</p>
</div>
<div class="modal-footer">
<button type="button" id="cancel-edit-btn" class="btn btn-primary" (click)="c('Close click')">Cancel</button>
</div>
</ng-template>
yourModal.component.ts
import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ViewChildren, ElementRef, Renderer2 } from '#angular/core';
import { NgbModal } from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-custom-modal',
templateUrl: './yourModal.component.html',
styleUrls: ['./yourModal.component.scss']
})
export class EditNotesComponent implements OnInit {
#Input() name: string;
#ViewChild('theModal') theModal: ElementRef;
constructor(private modalService: NgbModal) {}
ngOnInit() {
}
showModal() {
this.modalService.open(this.theModal, { size: 'sm', backdrop: 'static'});
}
}
detail.component.html
<div class="card card-outline-info">
<div class="card-header bg-info"><h5>Detail</h5><button (click)="yourCustomModal.showModal()"></button></div>
<div class="card-block">
<div class="table-responsive" style="cursor: pointer">
<generic-table [gtClasses]="'table-hover'" #myCustomTable [gtSettings]="secondConfigObject.settings" [gtFields]="secondConfigObject.fields" [gtData]="secondConfigObject.data"></generic-table>
</div>
</div>
</div>
<app-custom-modal #yourCustomModal [name]="name"></app-custom-modal>
detail.component.ts
import { Component, OnInit,Pipe, PipeTransform, EventEmitter,Input, Output,OnChanges, SimpleChanges } from '#angular/core';
#Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css'],
})
export class DetailComponent implements OnChanges{
name: string;
constructor(private detailService: DetailService) {
this.name = 'John Doe';};
}

Angular2 Route events

I'm using Angular2 routing and I need to subscribe to an event when route is changed. (i.e. user clicked on one of the route links). The important thing is that the event should be when the new view HTML is inserted to DOM.
Are there any events like onNavigating and onNavigated, so I can subscribe to?
I've found a couple of examples on stackoverflow and tried to use them (see constructor below), but that didn't work. Any ideas?
/// <reference path="../../typings/tsd.d.ts" />
import {Component, View} from 'angular2/angular2';
import {RouteConfig, Router, RouterOutlet, RouterLink} from 'angular2/router';
#RouteConfig([...])
#Component({
selector: 'app'
})
#View({
directives: [RouterOutlet, RouterLink],
template: `
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<header class="mdl-layout__header">
<div class="mdl-layout__header-row">
<span class="mdl-layout-title">Test</span>
<div class="mdl-layout-spacer"></div>
<nav class="mdl-navigation mdl-layout--large-screen-only">
<a class="mdl-navigation__link" [router-link]="['/routelink1']">routelink1</a>
</nav>
</div>
</header>
<main class="mdl-layout__content" style="padding: 20px;">
<router-outlet></router-outlet>
</main>
</div>
`
})
export class App {
constructor(private router: Router){
router.subscribe((val) => function(){...}); //here is I need to process HTML
}
}
I ended up with having base class for my routing components and it contains routerOnNavigate override.
import {OnActivate, ComponentInstruction} from 'angular2/router';
export class BaseView implements OnActivate {
routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) {
componentHandler.upgradeDom();
}
}

Categories

Resources