Bootstrap accordion not working with angular 7 - javascript

I am building an accordion based on array of data fetched from the server but the clicks are not working.
The accordion is working fine on hard-coded data but not on the data fetched using HttpClient. I even tried using button instead of anchor tags but to no avail.
<div class="accordion" id="chalsAccordion">
<div class="card rounded-0" *ngFor="let chal of chals">
<a data-toggle="collapse" href="#{{ chal._id }}"
><div class="card-header text-dark">
<p class="mb-0">
{{ chal.title }}<small> - {{ chal.author }}</small>
</p>
<p class="mb-0 ml-auto">{{ chal.points }}</p>
</div></a
>
<div id="{{ chal._id }}" class="collapse">
<div class="card-body" [innerHTML]="chal.desc"></div>
<div class="card-footer" *ngIf="!userService.admin">
<form [formGroup]="flagForm" style="width: 100%">
<div class="input-group">
<input type="text" class="form-control rounded-0" placeholder="Flag" formControlName="flag" />
<div class="input-group-append">
<button class="btn btn-primary rounded-0" [disabled]="!flagForm.valid" (click)="submitFlag(chal._id)">Submit</button>
</div>
</div>
</form>
</div>
<div class="card-footer" *ngIf="userService.admin">
<div class="ml-auto">
<button class="btn btn-danger rounded-0"><fa-icon [icon]="['fas', 'trash']"></fa-icon></button>
</div>
</div>
</div>
</div>
</div>
<button class="btn btn-primary add-chal-btn" routerLink="/chals/add" *ngIf="userService.admin"><fa-icon [icon]="['fas', 'plus']"></fa-icon></button>
import { Component, OnInit } from "#angular/core";
import { FormGroup, FormControl, Validators } from "#angular/forms";
import { ToastrService } from "ngx-toastr";
import { UserService } from "../services/user.service";
import { ChalService } from "../services/chal.service";
import { Response } from "../interfaces/response";
import { $ } from "protractor";
#Component({
selector: "app-chals",
templateUrl: "./chals.component.html",
styleUrls: ["./chals.component.scss"]
})
export class ChalsComponent implements OnInit {
chals = [];
flagForm = new FormGroup({
flag: new FormControl("", [Validators.required])
});
constructor(private toast: ToastrService, public userService: UserService, private chalService: ChalService) {}
ngOnInit() {
this.chalService.getAll().subscribe(
(data: Response) => {
this.chals = data.data["chals"];
},
err => {
this.toast.error(err.error.msg, "Oops!!!");
}
);
}
submitFlag(id: string) {}
}
Edit - The response is coming fine and the UI is also rendered correctly, just the problem is that the click does not expand the accordion.

Arrays are Index based so to access an element in an Array you have to provide an Index. To get the results from the response simply try to set the response to your array.
`ngOnInit() {
this.chalService.getAll().subscribe(
(data: Response) => {
this.chals = data.data; // -- updated the code here
},
err => {
this.toast.error(err.error.msg, "Oops!!!");
});
}`
Also please debug chalService to see if you are getting the response of your http call to the api.

I found the problem, it was that the _id field was starting with an int which was the root of the problem.
I solved it by adding an _ to every _id field.

Related

How can I configure my <li> items with Angular Routing so that it shows the relevant details in a new view?

I am building an Angular Movie DB, the two components I am working with are the "search-movie" component and the "single-view" component. The "search-movie" component displays a list of movies, the "single-view" component shows further details of a given movie.
I would like it so that when I click on a movie from the list in the "search-movie" component, the page renders the "single-view" component for that movie.
I have managed to set this up so that navigating to the "single-view" path with a movie id (i.e. /movie/tt4425200) directly from the URL, correctly loads up the info for that movie by it's ID, so that's all correctly set up.
I just can't seem to connect the clicking of a movie in the "search-movie" component, to then successfully navigate to the correct "single-view" path. So using the example above, clicking on the relevant movie loads up the "single-view" component with the URL path /movie/tt4425200.
I'm sure that this is a case of using #Input to communicate between the two components, but I just can't figure it out.
search-movie.component.ts:
import { Component, OnInit, Input } from '#angular/core';
import { FormControl } from '#angular/forms';
import { DataService } from '../data.service';
#Component({
selector: 'app-search-movie',
templateUrl: './search-movie.component.html',
styleUrls: ['./search-movie.component.css']
})
export class SearchMovieComponent implements OnInit {
searchControl = new FormControl('');
movieResults: any = [];
constructor(private data: DataService) { }
ngOnInit() {}
/* GET request */
getData(event) {
const film = event.target.value;
this.data.searchFilm(film)
.subscribe( (res) => {
res = this.movieResults = res;
console.log(res);
});
}
}
search-movie.component.html:
<div class="container">
<h1 class="is-size-3">Find your favorite movies...</h1>
<form (ngSubmit)="onSubmit()">
<input
type="text"
(keyup)="getData($event)"
placeholder="Start typing..."
[formControl]="searchControl" />
</form>
{{searchControl.value}}
</div>
<div class="container">
<ul>
<li id="list-item" *ngFor="let x of movieResults; let i = index;">
<img [src]="x.Poster" onerror="this.src='../assets/images/default-poster.jpg'">
<p id="movie-title" class="is-size-5">{{x.Title}} ({{x.Year}}) </p>
</li>
</ul>
</div>
single-view.component.ts:
import { Component, OnInit, Input } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { DataService } from '../data.service';
#Component({
selector: 'app-single-view',
templateUrl: './single-view.component.html',
styleUrls: ['./single-view.component.css']
})
export class SingleViewComponent implements OnInit {
singleDetails: any = {};
constructor(
private data: DataService,
private route: ActivatedRoute) { }
ngOnInit() {
/** GENERATE FILM DETAILS BY movie/id where id is the imdbID */
const id = this.route.snapshot.paramMap.get('id');
this.data.moviebyID(id)
.subscribe( (res) => {
res = this.singleDetails = res;
});
}
}
single-view.component.html:
<div class="container singleDisplayContainer">
<div class="columns is-mobile">
<div class="column" id="poster-column">
<img id="poster" [src]="singleDetails.Poster" [alt]="singleDetails.Title" onerror="this.src='../assets/images/default-poster.jpg'">
</div>
<div id="info-column" class="column">
<div class="columns">
<div class="column is-three-fifths">
<h1 class="is-size-3">{{singleDetails.Title}} <span class="is-size-4">({{singleDetails.Year}})</span> </h1>
<p style="font-size: 14px"> {{singleDetails.Rated}} | {{singleDetails.Runtime}} | {{singleDetails.Genre}} | {{singleDetails.Released}} </p>
</div>
<div class="column">
<div class="columns">
<div class="column is-one-third">
<img id="star-rating" width="50px" src="../../assets/images/star-rating.png" alt="{{singleDetails.Title}}">
</div>
<div class="column">
<p style="font-size: 2em"> {{singleDetails.imdbRating}}<span style="font-size: 12px">/10</span></p>
<p>{{singleDetails.imdbVotes}}</p>
</div>
</div>
</div>
</div>
<br>
<p>Plot: {{singleDetails.Plot}} </p>
<br>
<p>Directed by: {{singleDetails.Director}} </p>
<br>
<p>Writers: {{singleDetails.Writer}} </p>
<br>
<p>Actors: {{singleDetails.Actors}} </p>
<br>
<p onerror="this.style.display='none'">Box office: {{singleDetails.BoxOffice}} </p>
</div>
</div>
</div>
In Your UL -> LI, add routerLink property and pass the movie id as the second param
[routerLink]="['/movie/,x.movieId]">
<ul>
<li id="list-item" *ngFor="let x of movieResults; let i = index;" [routerLink]="['/movie/,x.movieId]">
<img [src]="x.Poster" onerror="this.src='../assets/images/default-poster.jpg'">
<p
id="movie-title"
class="is-size-5">{{x.Title}} ({{x.Year}}) </p>
</li>
</ul>
Looks like you have everything set up, all you need to do is navigate to single-view on click of the movie.
search-movie.component.ts
showDetails(id : string) {
this.router.navigate(['movie',{ id }]);
}
search-movie.component.html
<!-- in showDetails you will pass id of the current movie while looping -->
<li id="list-item" *ngFor="let x of movieResults; let i = index;" (click)="showDetails(x.id)">
<img
[src]="x.Poster"
onerror="this.src='../assets/images/default-poster.jpg'"
>
<p
id="movie-title"
class="is-size-5">{{x.Title}} ({{x.Year}}) </p>
</li>
This will navigate to single-view page. is this what you want right?
or you need to load single-view in the same page as the list?

Angular: #Input value available in template, but not in component

So I'm sending a movie object from a parent to a child component. I use #Input from the core module to do this.
Now, I am able to use this data inside the template to display my view, but when I try to access it in for example editReview() then this.movie returns undefined.
Does anyone know how to fix this?
Child Component: the console.log returns undefined
export class ReviewListComponent implements OnInit {
#Input('movie') movie;
constructor(private reviewService: ReviewService){}
editReview() {
console.log(this.movie);
}
}
Child Component Template: I am able to display my name and the content of the review. What's not working unfortunately is when I click the button it says that this.movie is undefined
<ul class="list-group">
<li *ngFor="let review of movie?.reviews" class="list-group-item">
<p>{{review.user.firstName}} {{ review.user.lastName}}</p>
<hr>
<p>{{review.content}}</p>
</li>
</ul>
<button (click)="editReview()">Button</button>
Edit: I added the components and templates of the two parent components: The first one is the movie component where I retrieve the movie object asynchronously, the second is the review component which contains the review-list component that I had already posted above
movie.component.ts
import {Component, OnInit} from "#angular/core";
import { MovieService} from "./movie.service";
import {ActivatedRoute} from "#angular/router";
#Component({
selector: 'app-movie',
templateUrl: './movie.component.html',
styleUrls: ['./movie.component.css']
})
export class MovieComponent implements OnInit{
rating;
movie;
movieId;
constructor(private movieService: MovieService, private route: ActivatedRoute){
}
checkRating(){
return typeof this.rating === 'number';
}
ngOnInit(){
this.route.params.subscribe(params => {
this.movieId = params.id;
var userId = localStorage.getItem('userId');
this.movieService.getMovie(this.movieId)
.subscribe(movie => {
this.movie = movie.obj;
this.movie.averageRating = Number(this.movie.averageRating);
console.log(this.movie);
});
if (userId){
this.movieService.getRating(userId, this.movieId)
.subscribe( result => {
this.rating = result.rating;
})
}
});
}
addRating(score) {
var userId = localStorage.getItem('userId');
this.movieService.addRating(score, userId, this.movie._id)
.subscribe(data => {
this.rating = data.obj.rating;
});
}
}
movie.component.html: this gives movie object to review.component through element app-review
<div class="container">
<div class="col col-md-4 col-md-offset-2">
<img [src]="movie?.pictureUrl" class="img-responsive" alt="hello">
</div>
<div class=" col col-md-6">
<h2>{{movie?.title}} ({{movie?.year}})</h2>
<h3>Average Score:</h3>
<span class="glyphicon glyphicon-star"></span><span><h1>{{movie?.averageRating}}</h1></span><br>
<h3>My Score:</h3>
<div class="row">
<div class="col">
<div *ngIf="!checkRating()" ngbDropdown class="d-inline-block">
<button class="btn btn-outline-primary" ngbDropdownToggle>Rate The Movie!</button>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<button value="1" (click)="addRating(1)" class="dropdown-item">1</button>
<button value="2" (click)="addRating(2)" class="dropdown-item">2</button>
<button value="3" (click)="addRating(3)" class="dropdown-item">3</button>
<button value="4" (click)="addRating(4)" class="dropdown-item">4</button>
<button value="5" (click)="addRating(5)" class="dropdown-item">5</button>
</div>
</div>
<div *ngIf="checkRating()">
<h1>{{rating}}</h1>
</div>
</div>
</div>
<h4>{{movie?.director}}</h4>
<h4>{{movie?.actors}}</h4>
<h4>{{movie?.country}}</h4>
<p> {{movie?.description}}</p>
</div>
</div>
<hr class="col-md-8 col-md-offset-2">
<div class="col-md-8 col-md-offset-2">
<ng-container *ngIf="!!movie">
<app-review [movie]="movie"></app-review>
</ng-container>
</div>
review.component.ts
import {Component, ElementRef, Input, OnInit, ViewChild} from "#angular/core";
import {NgForm} from "#angular/forms";
import {ReviewService} from "./review.service";
import {ActivatedRoute} from "#angular/router";
#Component({
selector: 'app-review',
templateUrl: './review.component.html',
styleUrls: ['./review.component.css']
})
export class ReviewComponent implements OnInit{
movieId;
#Input('movie') movie;
#ViewChild('textArea') textArea;
constructor(private reviewService: ReviewService, private route: ActivatedRoute){}
ngOnInit(){
this.route.params.subscribe( params => {
this.movieId = params.id
});
};
onClear(form: NgForm) {
form.resetForm()
}
onSubmit(form: NgForm) {
let content = form.value.review;
let userId = localStorage.getItem('userId');
let movieId = this.movieId;
this.reviewService.addReview(content, userId, movieId)
.subscribe( result => {
console.log(result.obj);
this.movie.reviews.unshift(result.obj);
form.resetForm()
})
}
}
review.component.html: this gives movie object to the review-list component through app-review-list
<ng-container *ngIf="!!movie">
<app-review-list [movie]="movie"></app-review-list>
</ng-container>
<hr>
<form ngNativeValidate (ngSubmit)="onSubmit(f)" #f="ngForm">
<div class="form-group">
<label for="review">Write A Review:</label>
<textarea
#textArea
(keyup.enter)="onSubmit(f)"
rows="4"
cols="50"
type="text"
id="review"
ngModel
class="form-control"
name="review"
required
></textarea>
</div>
<button type="button" class="btn btn-danger" (click)="onClear(f)">Clear</button>
<button class="btn btn-primary" type="submit">Save</button>
</form>
you can access it in ngOnInit() just implement OnInit interface

how to use single Modal dialog Component to show different data or message in Angular 2

I am working on application in Angular 2 and fairly new to it. I want to display Modal dialog on click of a Card. I have integrated angular material Modal popup in my app as instructed in this tutorial. Each of card have different Data and that data i want to display on same modal popup.
My Modal Component is :
import { Component, OnInit } from '#angular/core';
import { MdDialogRef } from '#angular/material';
#Component({
selector: 'confirm-dialog',
template: `
<p>{{ title }}</p>
<p>{{ message }}</p>
<button type="button" md-raised-button
(click)="dialogRef.close(true)">OK</button>
<button type="button" md-button
(click)="dialogRef.close()">Cancel</button>
`,
})
export class ModalComponent {
public title: string;
public message: string;
constructor(public dialogRef: MdDialogRef<ModalComponent>) {
}
}
my Card component is :
import { Component, OnInit } from '#angular/core';
import { ModalService } from '../services/modal.service';
#Component({
selector: 'app-content',
templateUrl: './content.component.html',
styleUrls: ['./content.component.css']
})
export class ContentComponent implements OnInit {
private solutions: Array<Object>;
public result: any;
constructor(public dialogsService: ModalService) {
}
public openDialog() {
this.dialogsService
.confirm('Confirm Dialog', 'Are you sure you want to do this?')
.subscribe(res => this.result = res);
}
ngOnInit() {
}
}
and HTML is :
<div class="container self-card-container">
<div class="row lab-work">
<div class="col-12 col-sm-4 col-md-4 col-lg-4 col-xl-4">
<div class="custom-card">
<div class="card-header whatWeDo align-item-center">
<div class="custom-header-image mat-card-avatar d-flex justify-content-center align-self-center" md-card-avatar="">
<img src="./assets/what-we-do.png" class="align-self-center">
</div>
<div class="custom-header-text d-flex align-self-center">
<div class="custom-card-title">What We Do</div>
</div>
</div>
<div class="custom-card-content">
Co-Innovate with customers and partners in a "sandbox" environment to develop proof of concepts. Harness Emerging technologies
to come up with newer solutions around existing problems. Provide an Immersive Experience to our customers of potential
solutions for feel and function.
</div>
<div class="custom-card-action align-items-center">
<button md-button class="read-more" (click)="openDialog()">Read More</button>
</div>
</div>
</div>
<div class="col-12 col-sm-4 col-md-4 col-lg-4 col-xl-4">
<div class="custom-card">
<div class="card-header howWeDo align-item-center">
<div class="custom-header-image mat-card-avatar d-flex justify-content-center align-self-center" md-card-avatar="">
<img src="./assets/how-we-do.png" class="align-self-center">
</div>
<div class="custom-header-text d-flex align-self-center">
<div class="custom-card-title">How We Do</div>
</div>
</div>
<div class="custom-card-content">
We begin with problem identification followed by ideation phase to create an alternate point of view on the problem. This
is followed by building a proof of concept or a prototype which is then handed over to customer for feedback. The
whole process is repeated iteratively as desired.
</div>
<div class="custom-card-action align-items-center">
<button md-button class="read-more" (click)="openDialog()">Read More</button>
</div>
</div>
</div>
<div class="col-12 col-sm-4 col-md-4 col-lg-4 col-xl-4">
<div class="custom-card">
<div class="card-header howWeDone align-item-center">
<div class="custom-header-image mat-card-avatar d-flex justify-content-center align-self-center" md-card-avatar="">
<img src="./assets/how-things-get-done.png" class="align-self-center">
</div>
<div class="custom-header-text d-flex align-self-center">
<div class="custom-card-title">How Things Get Done</div>
</div>
</div>
<div class="custom-card-content">
We follow 'continuous flow' based development as opposed to traditional software development life-cycle to stay lean. An
integrated application life cycle management gives us necessary agility and transparency.
</div>
<div class="custom-card-action align-items-center">
<button md-button class="read-more" (click)="openDialog()">Read More</button>
</div>
</div>
</div>
</div>
Dialog Service is :
import { Observable } from 'rxjs/Rx';
import { ModalComponent } from '../modal/modal.component';
import { MdDialogRef, MdDialog, MdDialogConfig } from '#angular/material';
import { Injectable } from '#angular/core';
#Injectable()
export class ModalService {
constructor(private dialog: MdDialog) { }
public confirm(title: string, message: string): Observable<boolean> {
let dialogRef: MdDialogRef<ModalComponent>;
dialogRef = this.dialog.open(ModalComponent);
dialogRef.componentInstance.title = title;
dialogRef.componentInstance.message = message;
return dialogRef.afterClosed();
}
}
I want to display title and message of card on modal that is being clicked.
How to pass Data respective to card in Modal?
Pass the title and message as parameters to the openDialog() method, eg.
html:
<button md-button class="read-more" (click)="openDialog('My special title', 'My special message')">Read More</button>
component:
public openDialog(title: string, message: string) {
this.dialogsService
.confirm(title, message)
.subscribe(res => this.result = res);
}
EDIT based on question in comment:
The quick and easy way would be to add the message content as string properties of the component and pass these as the parameters, eg.
In component:
export class ContentComponent implements OnInit {
private solutions: Array<Object>;
public result: any;
public dialogOneMessage = `<p>Stuff</p><p>More stuff<p><img src=:/photo.jpg" />
html:
<button md-button class="read-more" (click)="openDialog('My special title', dialogOneMessage)">Read More</button>
I don't really like this approach though - not a good separation of concerns having large amounts of html as component properties. If you have large amounts of complex data for each custom dialog you are probably better off creating a custom component for each of your dialogs and pass your custom component to the this.dialog.open() instead reusing the ConfirmDialog component.

Github API - Get followers of follower in Angular2

How can i display followers count of a follower?
What i have setup right now:
Field (input) to enter Github username in, when button is clicked all of followers of the user will be listed bellow. Follower username & follower ID are already shown, but i also would like to show the amount of followers the follower has.
Picture for better understanding of what I'm looking for:
SCREENSHOT
github-profile.component.ts
import {Component} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/forkJoin';
import {GitHubService} from './github.service';
#Component({
selector: 'github-profile',
styles: [
`
/*noinspection CssInvalidPropertyValue*/.avatar {
width: 100;
height: 100;
border-radius: 100%;
}
`
],
template: `
<i *ngIf="isLoading" class="fa fa-spinner fa-spin fa-3x"></i>
<form #f="ngForm" class="animated fadeInRight">
<div class="form-group">
<label for="name">Follower finder</label>
<input ngControl="username"
#username="ngForm"
[(ngModel)] = "inputusr"
type="text"
class="form-control"
placeholder="Enter GitHub username"
required
minlength="3">
<div *ngIf="username.touched && username.errors">
<div *ngIf="username.errors.required"
class="alert alert-danger">
Username is required.
</div>
<div class="alert alert-danger"
*ngIf="username.errors.minlength">
First name should be minimum 3 characters.
</div>
</div>
</div>
<button (click)=OnClick($event) type="submit" class="btn btn-default" [disabled]="!f.valid">Search</button>\
<button type="submit" class="btn btn-danger" (click)=ClearResults($event)>Clear</button>
</form>
<h3 *ngIf="isVisible">#{{user.login}} aka {{user.name}}</h3>
<img *ngIf="isVisible" class="avatar" src="{{ user.avatar_url }}">
<h3 *ngIf="isVisible">Followers</h3>
<div *ngIf="isVisible" class="row">
<div *ngFor="#follower of followers" class="col-sm-3 animated fadeInRight">
<div class="thumbnail">
<img *ngIf="isVisible" src="{{ follower.avatar_url }}" alt="...">
<div class="caption">
<h4 class="text-center">{{ follower.login }}</h4>
<p class="text-center">User ID: {{ follower.id }}</p>
<p class="text-center">Followers: Show followers of a follower here.</p>
</div>
</div>
</div>
</div>
`,
providers: [HTTP_PROVIDERS, GitHubService]
})
export class GitHubProfileComponent {
inputusr: string;
isVisible = false;
isLoading = false;
username: string;
user = {};
followers = {};
constructor(private _gitHubService: GitHubService){
}
ClearResults($event){
this.isVisible = false;
this.inputusr = "";
}
OnClick($event){
this.isLoading = true;
this.username = this.inputusr;
Observable.forkJoin(
this._gitHubService.getUser(this.username),
this._gitHubService.getFollowers(this.username)
)
.subscribe(
res => {
this.user = res[0];
this.followers = res[1];
},
null,
() => { this.isLoading = false; this.isVisible = true; })
}
}
github.service.ts
import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class GitHubService {
private _baseUrl = "https://api.github.com/users/";
constructor(private _http: Http){}
getUser(username){
return this._http.get(this._baseUrl + username)
.map(res => res.json());
}
getFollowers(username){
return this._http.get(this._baseUrl + username + "/followers")
.map(res => res.json());
}
}
There is a key named "followers" in the response for https://api.github.com/users/odetocode which is pretty much what u need.
The below method can be used if u want the basic details of each follower of the user.
The URL https://api.github.com/users/:username/followers basically returns an array of objects, with each object representing a follower.
There is an upper limit of 30 on the number of entries returned in the response.
Workaround
So basically in order to fetch more users we can append to the url a query string parameter ?page=1, ?page=2and so on.
Check for the response till the length of array = 0;
That will give u the last page till which followers exists.
Then count the number of followers in the last page.
Example: I have 340 followers
So response for https://api.github.com/users/:username/followers?page=13 will be and array of length 0.
Then send a request for https://api.github.com/users/:username/followers?page=12 which will return an array of length 10
Count of followers: (30 * 11) + (10 * 1) = 340

Ng-bootstrap modal not showing

My goal is to open a modal in angular when I press a button. I decided to use ng-bootstrap for this. I went to their website and decided to copy paste the default modal code into my application.
The button is showing and when I click it, the screen moves a little bit, but there is no modal to be seen. When I click the button a second time I get a feedback Dismissed by clicking on a backdrop. The console shows me no errors.
Does anyone know how to fix this?
image of what the webpage looks like
homepage HTML file: the ng-template is the modal
<div class="col-md-8 col-md-offset-2">
<h5>Welcome to MovieMeter! <span *ngIf="isLoggedIn"> You are logged in as {{fullName}}</span></h5>
<br>
<ng-template #content let-c="close" let-d="dismiss">
<div class="modal-header">
<h4 class="modal-title">Modal title</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>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="c('Close click')">Close</button>
</div>
</ng-template>
<button class="btn btn-lg btn-outline-primary" (click)="open(content)">Launch demo modal</button>
<hr>
<pre>{{closeResult}}</pre>
<h3>Trailers:</h3>
<hr>
<ul>
<li *ngFor="let trailer of trailers">
<img src="{{trailer.body.items[0].snippet.thumbnails.high.url}}" alt="nope">
<div class="trailerTitle"><h5>{{trailer.movie.title}}</h5></div>
</li>
</ul>
<app-cinema-featured></app-cinema-featured>
</div>
Home.component.ts
import {Component, OnInit} from "#angular/core";
import {AuthService} from "../auth/auth.service";
import {MovieService} from "../movie/movie.service";
import {NgbModal, ModalDismissReasons} from '#ng-bootstrap/ng-bootstrap';
#Component({
styleUrls: ['./home.component.css'],
selector: 'app-home',
templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {
isLoggedIn:Boolean;
fullName;
trailers;
closeResult: string;
constructor(private modalService:NgbModal, private authService: AuthService, private movieService: MovieService){}
ngOnInit(){
if (localStorage.getItem('token') !== null || undefined){
this.isLoggedIn = true;
this.fullName = localStorage.getItem('fullName');
}
// get the thumbnails and links of the three most recent movie trailers via the youtube API
this.movieService.getTrailers()
.subscribe(trailers => {
this.trailers = trailers.result;
console.log(this.trailers);
})
}
open(content) {
this.modalService.open(content).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
}
Update: this are the elements in the console after I clicked the button. The ng backdrop and ng-modal are showing, but cannot be seen.
After trying a lot of things I discovered that I needed bootstrap 4 instead of bootstrap 3.
Try to use #ViewChild to select the modal in your component code:
HTML
<button class="btn btn-lg btn-outline-primary" (click)="open()">Launch demo modal</button>
TS
#ViewChild("content") content: NgbModal;
open() {
this.modalService.open(this.content).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
//1. The modal component has to be registered in entryComponents (angualr 8 and prev)
entryComponents: [
YourModalComponent
],
providers: [
...]
//2. also the model directly inputted in the open:
openConfirmUpdateModal() {
this.modalService.open( YourModalComponent);
}

Categories