I have 3 files, model.ts, modal.html and modal.ts. I would like to do the auto refresh only when the modal is open and stop it when it is closed. my modal shows me information continuously.
modal.htlm :
<button class="btn btn-success" style="padding: 0.1rem 0.5rem; float: left; font-size: 12px;"(click)="viewFile(model)">Voir</button>
<div class="modal" id="mdl" tabindex="-1" role="dialog" aria-hidden="true"
[ngStyle]="{'display': mdlIsOpen ? 'block' : 'none', 'opacity': 1}">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Hello</h5>
<button type="button" class="close" aria-label="Close" (click)="openContent(false)">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div style="white-space: pre-wrap" innerHTML="{{reponse}}"></div>
</div>
<div class="modal-footer" align="right">
<button type="button" id="btnOK" class="btn btn-success"
(click)="openContent(false)">close</button>
</div>
</div>
</div>
</div>
modal.ts:
export class ModalComponent implements OnInit {
private updateSubscription: Subscription;
reponse: String;
model: Model[];
constructor(private modelService: ModelService) {
}
ngOnInit() {
}
refreshAuto(){
console.log(this.mdlIsOpen);
if(this.mdlIsOpen === true){
this.updateSubscription = interval(10000).subscribe(
(val) => {
this.refresh();
this.refreshAuto();
});
}
}
refreshFile(): void {
this.viewFile(this.model);
}
refresh(): void {
this.view(this.model);
}
openContent(open: boolean): void {
console.log(open);
this.mdlIsOpen = open;
}
viewFile(model: Model): void {
this.modelService.viewFile(model)
.subscribe(res => {
this.openContent(true);
this.reponse = res;
//console.log(res);
this.refreshAuto();
//clearInterval(this.interval);
}, err => {
console.log("here for view");
console.log(err);
alert (JSON.parse(err.error).message);
}
);
}
view(model: Model): void {
this.modelService.viewFile(model)
.subscribe(res => {
this.reponse = res;
//console.log(res);
}, err => {
console.log("here for view");
console.log(err);
alert (JSON.parse(err.error).message);
}
);
}
}
model.ts:
export class Model {
Id: number;
mode: number;
App: string;
name: string;
}
but its not working well, when I close the modal and mdlIsOpen goes to false, the auto refresh continues.
Step 1) Do not continually call this method
refreshAuto(){
console.log(this.mdlIsOpen);
if(this.mdlIsOpen === true){
this.updateSubscription = interval(10000).subscribe(
(val) => {
this.refresh();
this.refreshAuto();
});
}
}
Why? Because interval never stops on it's own. Each time this is called it sets up another interval observable.
Step 2) "I would like to do the auto refresh only when the modal is open" This code is ambiguous
openContent(open: boolean): void {
console.log(open);
this.mdlIsOpen = open;
}
We can't tell from the code who would ever want to openConent and set the open value to false. OpenContent should probably always be to open the dialog.
Step 3) Determine when to change this.mdlIsOpen to false. One good place, for sure is in ngOnDestroy. You may also stop the interval timer there too.
Step 4) Provide a method isOpen(open:boolean) which allows an explicit self explaining entry into your component to open or close the dialog.
Step 5) MatDialog does have a close option
Example
import { MatDialog, MatDialogConfig } from "#angular/material/dialog";
#Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
constructor( private dialog: MatDialog) {}
// The HTML button click handler
onButtonClicked($event) {
let httpClient: HttpClient = new HttpClient(this.httpHandler);
// Causes a CORS error
httpClient.get("http://www.google.com").subscribe(
(response) => {
console.log(response);
},
(error) => {
let dc = new MatDialogConfig();
dc.autoFocus = true;
// Important part
dc.data = error;
this.dialog.open(ErrorHandlerComponent, dc);
}
);
}
And ErrorHandlerComponent
export class ErrorHandlerComponent implements OnInit, AfterViewInit {
error: HttpErrorResponse;
constructor(
// Must inject MAT_DIALOG_DATA
#Inject(MAT_DIALOG_DATA)
public data: any,
private ref: ElementRef,
private HtmlElementService: HtmlElementService
) {
// Html binds to this.error
this.error = data;
}
The Injected Component's HTML
<h1 mat-dialog-title>{{ error.statusText }}</h1>
<div mat-dialog-content>
<p>Message</p>
{{ error.message }}
</div>
<div mat-dialog-actions>
<button class="mat-raised-button" mat-dialog-close>Close</button>
<button class="mat-raised-button mat-primary" (click)="save()">Copy</button>
</div>
The result:
In your modal close method unsubscribe the interval observable.
openContent(open: boolean): void {
console.log(open);
this.mdlIsOpen = open;
this.updateSubscription.unsubscribe();
}
Related
I'm using Angular version 7 with a component that has a serie of divs being rendering according to the data coming from an #Input and it should be updated due the service response, nevertheless the component is not correctly updated, the loader remains loading (loading=true) until I click into the text input and then I click elsewhere.
Template:
<div class="row" *ngFor="let message of messages">
<div>{{message.date}}</div>
<div>{{message.body}}</div>
</div>
<div class="row" *ngIf="thread.isOpen">
<div class="panel" >
<form (ngSubmit)="onSubmit()" [formGroup]="messageForm">
<textarea class="textarea" name="message" id="message" formControlName="message"></textarea>
<button class="btn"">
<span *ngIf="!loading; else loadingTemplate">send</span>
<ng-template #loadingTemplate>
<i class="fa fa-spin"></i>
</ng-template>
</button>
</form>
</div>
Component:
#Input() messages;
messageForm: FormGroup;
loading: boolean = false;
ngOnInit(): void {
this.loadFromControls();
}
loadFromControls(): void {
this.messageForm = this.formBuilder.group({
message: this.formBuilder.control('', [])
});
}
onSubmit() {
if (!this.messageForm.valid) return;
this.loading = true;
const message = this.messageForm.controls['message'].value;
this.service.sendMessage(this.thread._id, message).subscribe(() => {
if (this.messages) {
this.messages.push({
isFromExtranet: true,
date: new Date(),
body: message
});
}
this.messageForm.controls['message'].setValue("");
this.loading = false;
}, (err) => this.errorMessage(err));
}
Service
sendMessage(id: string, message: string): Observable<any> {
return this.http.post(`/api/messages/${id}`, { message })
.map((res) => res.json())
.catch((error) => Observable.throw(error.json().code || 'error'));
}
I've been dealing with this a few hours and maybe I'm just missing something very basic.
Can you try update the code as per below and make sure that you're getting correct value from #Input decorator.
<div *ngIf="isDataloaded>
<div class="row" *ngFor="let message of messages">
<div>{{message.date}}</div>
<div>{{message.body}}</div>
</div>
<div class="row" *ngIf="thread.isOpen">
<div class="panel" >
<form (ngSubmit)="onSubmit()" [formGroup]="messageForm">
<textarea class="textarea" name="message" id="message" formControlName="message"></textarea>
<button class="btn"">
<span *ngIf="!loading; else loadingTemplate">send</span>
<ng-template #loadingTemplate>
<i class="fa fa-spin"></i>
</ng-template>
</button>
</form>
</div>
</div>
Component.ts
#Input() messages;
isDataloaded = flase;
messageForm: FormGroup;
loading: boolean = false;
ngOnInit(): void {
this.loadFromControls();
}
loadFromControls(): void {
this.messageForm = this.formBuilder.group({
message: this.formBuilder.control('', [])
});
}
onSubmit() {
this.loading = true;
if (!this.messageForm.valid) return;
const message = this.messageForm.controls['message'].value;
this.service.sendMessage(this.thread._id, message).subscribe(() => {
if (this.event.data.discussionThread.messages) {
this.event.data.discussionThread.messages.push({
isFromExtranet: true,
date: new Date(),
body: message
});
}
this.messageForm.controls['message'].setValue("");
this.loading = false;
}, (err) => this.errorMessage(err));
this.isDataloaded = true;
}
I fixed using a BehaviorSubject, as:
loading$: BehaviorSubject<boolean> = new BehaviorSubject(false);
...
this.loading$.next(true);
instead of:
loading: boolean = false;
...
this.loading = true;
and in the template with async as:
<span *ngIf="!(loading$ | async); else loadingTemplate">
I'd like to ask how can I send data from one sibling component to another and send it back with changed value?
I need to add bootstrap effect fadeInDown to a newly added comment in my comments section.
It works but unfortunately it affects all of the comments when I reload the page and the effect is also added when I edit a comment.
I need to send boolean value on method addComment from new-comment component to comment component but then I need that value in new-component to become false again. Now it's false and after using addComment method it becomes true forever. How can I handle this?
I will be glad for any advice
This is my comment section:
Comment section
This is the structure of my files: Files structure
These are the components I'm working on:
Comment section HTML
<h6>Comments: ({{commentsCount}})</h6>
<app-new-comment class="d-block mt-3" [requestId]="requestId" (update)="updateComments()">
</app-new-comment>
<app-comment *ngFor="let comment of comments; let i = first"
[ngClass]="{'fadeInDown': i}"
class="d-block mt-3 animated"
[comment]="comment"
(update)="updateComments()"></app-comment>
Comment section TS
export class CommentSectionComponent implements OnInit, OnDestroy {
#Input() requestId: string
comments: CommentDetailsDto[]
commentsCount = 0
private subscription: Subscription
constructor(
private commentsService: CommentsService,
private alert: AlertService
) {
}
ngOnInit(): void {
this.updateComments()
}
ngOnDestroy(): void {
this.unsubscribe()
}
updateComments(): void {
this.unsubscribe()
this.subscription = this.commentsService.getComments(this.requestId)
.subscribe({
next: (comments: CommentDetailsDto[]) => {
this.comments = comments.reverse()
this.commentsCount = this.getCommentsCount(comments)
},
error: (error: HttpErrorResponse) => {
this.alert.handleHttpError(error)
}
})
}
private getCommentsCount(comments: CommentDetailsDto[]): number {
return comments.reduce(
(cnt, comment) => cnt + 1 + (comment.replies ? this.getCommentsCount(comment.replies) : 0),
0
)
}
private unsubscribe(): void {
if (this.subscription instanceof Subscription) {
this.subscription.unsubscribe()
}
}
}
Comment section SCSS
#keyframes fadeInDown {
from {
opacity: 0;
transform: translate3d(0, -100%, 0);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
.fadeInDown {
animation-name: fadeInDown;
}
New comment component HTML
<div class="d-flex">
<app-user-image class="mr-3"></app-user-image>
<textarea #textArea class="d-block" placeholder="Add comment" [(ngModel)]="newComment">
</textarea>
</div>
<div class="text-right mt-3">
<button class="btn btn-primary font-weight-bold px-5" type="button"
[disabled]="!newComment" (click)="submit()">
Post
</button>
</div>
New comment TS
export class NewCommentComponent implements OnInit {
#ViewChild('textArea') textArea: ElementRef<HTMLTextAreaElement>
#Input() requestId?: string
#Input() comment?: CommentDetailsDto
#Output() update = new EventEmitter()
newComment: string
private readonly commentResponseObserver = {
error: (error: HttpErrorResponse) => {
this.alert.handleHttpError(error)
},
complete: () => {
delete this.newComment
this.update.emit()
this.alert.showSuccess('Comment submitted successfully')
}
}
constructor(
private commentsService: CommentsService,
private alert: AlertService,
private route: ActivatedRoute
) {
}
ngOnInit(): void {
if (this.comment) {
this.textArea.nativeElement.focus()
}
}
submit(): void {
if (this.requestId) {
this.addComment()
} else if (this.comment) {
this.addReply()
}
}
addComment(): void {
if (this.newComment) {
this.commentsService.addComment(this.requestId, this.newComment)
.subscribe(this.commentResponseObserver)
}
}
addReply(): void {
if (this.newComment) {
this.commentsService.addReply(this.route.snapshot.queryParamMap.get('requestId'), this.comment, this.newComment)
.subscribe(this.commentResponseObserver)
}
}
}
Comment component HTML
<div class="comment">
<app-user-image></app-user-image>
<div class="position-relative d-inline-block flex-fill">
<div class="d-flex justify-content-between align-items-center">
<div><strong>{{comment.author.name}} / {{comment.author.id}}</strong><span
class="date">{{comment.created | krakenDateTime}}</span></div>
<div class="actions">
<button *ngIf="this.hateoas.supports(comment, 'update') && !edit"
type="button" class="bg-transparent border-0" title="Edit"
(click)="toggleEdit()"><i class="icon-kraken icon-kraken-edit"></i></button>
<button *ngIf="this.hateoas.supports(comment, 'delete')"
type="button" class="bg-transparent border-0" title="Delete"
(click)="displayDeletionConfirmation()"><i class="icon-kraken icon-kraken-trash"></i></button>
</div>
</div>
<textarea *ngIf="edit; else readonlyComment"
#textarea
class="d-block w-100"
style="min-height: 7rem;"
[rows]="rows()"
[(ngModel)]="commentContent"></textarea>
<ng-template #readonlyComment>
<div [innerHTML]="commentContentHtml()"></div>
</ng-template>
<strong *ngIf="showReplyButton"
class="reply-button"
(click)="toggleReplyComponent()">Reply</strong>
</div>
</div>
<div *ngIf="edit" class="animated fadeIn text-right mt-3">
<button class="btn btn-sm discard" (click)="cancelEdit()">Discard</button>
<button class="btn btn-sm ml-2 update" (click)="updateComment()">Update</button>
</div>
<div class="replies">
<app-new-comment *ngIf="showNewReplyWindow"
class="d-block mt-3"
[comment]="comment"
(update)="this.update.emit()"></app-new-comment>
<app-comment *ngIf="firstReply"
class="d-block my-3"
[comment]="firstReply"
(update)="update.emit()"></app-comment>
<div *ngIf="moreReplies.length" class="replies-toggle" (click)="showMoreReplies =
!showMoreReplies">
<div class="horizontal-bar"></div>
<span class="mx-3">{{showMoreReplies ? 'Hide' : 'See'}} {{moreReplies.length}} more
comments</span>
<div class="horizontal-bar"></div>
</div>
<div *ngIf="showMoreReplies">
<app-comment *ngFor="let reply of moreReplies"
class="d-block my-3"
[comment]="reply"
(update)="update.emit()"></app-comment>
</div>
<span id="temporaryLastRow"></span>
Comment TS
export class CommentComponent implements OnInit {
#ViewChild('textarea', {static: true}) textarea: ElementRef<HTMLTextAreaElement>
#Input() comment: CommentDetailsDto
#Output() update = new EventEmitter()
edit = false
showReplyButton = false
showNewReplyWindow = false
showMoreReplies = false
commentContent: string
firstReply: CommentDetailsDto
moreReplies: CommentDetailsDto[]
constructor(
private commentsService: CommentsService,
private modalFactoryService: ModalFactoryService,
public hateoas: HateoasService,
private alert: AlertService
) {
}
ngOnInit(): void {
this.commentContent = this.comment.content
this.showReplyButton = this.hateoas.supports(this.comment, 'reply')
this.moreReplies = this.comment.replies.reverse().slice(1)
this.firstReply = this.comment.replies[0]
}
toggleEdit(): void {
this.edit = !this.edit
}
updateComment(): void {
this.commentsService.updateComment(this.comment, this.commentContent)
.subscribe({
error: (error: HttpErrorResponse) => {
this.alert.handleHttpError(error)
},
complete: () => {
this.alert.showSuccess('Comment updated successfully')
this.update.emit()
}
})
}
cancelEdit(): void {
this.edit = false
this.commentContent = this.comment.content
}
displayDeletionConfirmation(): void {
this.modalFactoryService.openConfirmationModal(
'Delete Comment',
{
message: 'Are you sure you want to delete this comment?',
yesOptionButton: 'Yes',
noOptionButton: 'No'
},
() => {
this.hateoas.execute(this.comment, 'delete')
.subscribe({
error: (error: HttpErrorResponse) => {
this.alert.handleHttpError(error)
},
complete: () => {
this.alert.showSuccess('Comment deleted successfully')
this.update.emit()
}
})
}
)
}
toggleReplyComponent(): void {
this.showNewReplyWindow = !this.showNewReplyWindow
}
commentContentHtml(): string {
return this.commentContent.replace(/\n/g, '<br>')
}
rows(): number {
const newLines = this.commentContent.match(/\n/g) || []
return newLines.length + 1
}
}
export interface Author {
id: string
name: string
}
export interface CommentDetailsDto extends Resource {
content: string
author: Author
replies: CommentDetailsDto[]
created: string
}
When a user selects a tag, I want to display only the blogs containing that tag.
For example when a user selects the '#C#' tag only posts with this tag will be displayed.
My set up is as follows: I have an array of blogs which contain post tags which contain tags:
export interface IBlog
{
id: number
title: string
content: string
subscription: number
time: string
created: Date;
imageUrl: string
coverImage: string
image: string
likes: number
body: string
comments?:{
message: string
handle: string,
city: string,
country: string
},
articleLinkUrl?: string,
sessions: ISession[],
mainComments: IComments[],
postTags: IPostTags[]
}
export interface ISession
{
id: number,
name: string,
presenter: string,
duration: number,
level: string,
abstract: string,
voters: string[]
}
export interface IComments
{
id: number,
message: string
}
export interface IPostTags
{
id: number,
tag: ITag[]
}
export interface ITag
{
id: number,
name: string
}
I have a blog-list.component.ts:
import {Component, OnInit} from '#angular/core'
import { BlogService} from './shared/blog.service';
import { ActivatedRoute } from '#angular/router';
import { IBlog } from './shared';
#Component({
template: `
<div>
<h1>Upcoming Blogs</h1>
<hr/>
<div class= "btn-group btn-group-sm">
<button class="btn btn-default" [class.active] = "filterBy==='all'" (click) = "filterBy='all'">All</button>
<button class="btn btn-default" [class.active] = "filterBy==='c#'" (click) = "filterBy='#C#'">C#</button>
<button class="btn btn-default" [class.active] = "filterBy==='angular'" (click) = "filterBy='#Angular'">Angular</button>
<button class="btn btn-default" [class.active] = "filterBy==='netcore'" (click) = "filterBy='#NetCore'">.NET Core</button>
</div>
<div class ="row">
<blog-thumbnail [filterBy]="filterBy" [blogs] = "blogs"></blog-thumbnail>
<div class='row' style="margin-bottom: 10px;">
<div class="col-md-2">
<h3 style="margin:0">Sort by Tag</h3>
</div>
<div class="col-md-7">
<div class= "btn-group btn-group-sm" style="margin-right: 20px; margin-left: 20px;">
<button class="btn btn-default" [class.active] = "sortBy==='name'" (click) = "sortBy='name'">By Name</button>
<button class="btn btn-default" [class.active] = "sortBy==='votes'" (click) = "sortBy='votes'">By Votes</button>
</div>
</div>
</div>
</div>
</div>`
})
export class BlogListComponent implements OnInit{
blogs:IBlog[]
filterBy: string = 'all';
constructor(private blogService: BlogService, private route: ActivatedRoute){
}
ngOnInit(){
this.blogs = this.route.snapshot.data['blogs']
}
}
This displays a blog-thumbnail component
import {Component, Input, EventEmitter, Output, OnChanges} from '#angular/core'
import { forEach } from '#angular/router/src/utils/collection';
import { IBlog, IPostTags } from './shared';
#Component ({
selector: 'blog-thumbnail',
template: `
<div class="row" *ngFor="let blog of blogsSession">
<div [routerLink] = "['/blogs', blog.id]" class="well hoverwell thumbnail">
<img src={{blog?.coverImage}}/>
<h2>{{blog?.title | uppercase}}</h2>
<div>{{blog?.created | date}}</div>
<div>Content: {{blog?.content}}</div>
<div>Tags: {{blog?.content}}</div>
<div well-title *ngIf="blog?.mainComments">
{{blog?.likes}} Reactions
<i *ngIf="blog?.likes >= 1" class="glyphicon glyphicon-heart-empty" style="color:red"></i>
{{blog.mainComments.length}} Comments
<i *ngIf="blog.mainComments.length >= 1" class="glyphicon glyphicon-comment" ></i>
</div>
<div well-title *ngIf="blog?.postTags">
{{blog.postTags.length}} Post Tags
<i *ngIf="blog.postTags.length >= 1" class="glyphicon glyphicon-comment" ></i>
</div>
</div>
`,
styles:[
`
.thumbnail {min-height: 210px;}
.pad-left {margin-left: 10px;}
.well div { color: #bbb;}
`]
})
export class BlogThumbnailComponent implements OnChanges {
#Input() blog: IBlog
#Input() filterBy: string;
#Input() blogs: IBlog[];
blogsSession: IBlog[] = [];
getStartTimeStyle(): any{
if (this.blog && this.blog.time === '7:30pm')
return{color: '#003300', 'font-weight' : 'bold'}
return{};
}
ngOnChanges(){
if(this.blogs){
this.filterSessions(this.filterBy);
//this.sortBy === 'name' ? null : null;
}
}
filterSessions(filter){
if(filter === 'all'){
this.blogsSession= this.blogs.slice(0);
}
else
{
this.blogsSession = this.blogs.filter(blog => {
return blog.postTags.filter( postTag =>{
postTag.tag.name === filter
})
})
this commented out code works but it is not what i want
// this.blogsSession = this.blogs.filter(blog => {
// return blog.postTags.length < 2;
//})
}
}
}
The following section off code is where I am having my problem. It does not work:
this.blogsSession = this.blogs.filter(blog => {
return blog.postTags.filter( postTag =>{
postTag.tag.name === filter
})
})
I have spent a large amount of time on this. Would anybody be able to explain what I am doing wrong here?
The function used in the filter() method should return true or false (or actually a value that coerces to true or false). Your function returns an array; you are filtering blog.postTags.
Try this instead:
this.blogsSession = this.blogs.filter(blog => {
return blog.postTags.some(postTag => postTag.tag.name === filter)
})
The some() method will return true if at least one of the items in the array meet the conditions used in the function.
Why do you have 2 filter operators? I think this:
this.blogsSession = this.blogs.filterpostTags.filter( postTag =>{
postTag.tag.name.toLocaleLowerCase() === filter.toLocaleLowerCase()
})
should be enough.
I am a newbie and learning angular. I have a background of angularjs. I have structure of my app like this.
// src /
// app /
// app-footer
// app-footer.component.css , app-footer-component.html,app-footer.component.ts
// app-header
// app-header.component.css,app-header.component.html,app-header.ts
// home
// home.component.css,home.component.html,home.component.ts
// shared
// modals
// todo
// update-todo.css,update-todo.html,update-todo.ts
I am using ng-bootstrap and with the help of it i am showing a modal on click. My home.component.html looks like this.
<div class="container home-page">
<div class="jumbotron text-center">
<h1>I'm a Todo-aholic
</h1>
</div>
<div id="todo-form" class="row">
<div class="mx-auto col-sm-8 text-center">
<form action="">
<div class="form-group">
<input type="text" name="something" [(ngModel)]="todo" class="form-control input-lg text-center" placeholder="I want to buy a puppy that will love me forever">
<div class="add-button-todo-app">
<button class="btn btn-primary" (click)="pushInTodoArr(todo) " [disabled]="todo =='' ? true : false">ADD</button>
</div>
</div>
</form>
</div>
</div>
<div class="list-of-todos">
<ul>
<li *ngFor="let item of todoArray;let i=index">
<span class="tick">
<i class="fa fa-check" aria-hidden="true"></i>
</span>
{{item}}
<span class="trash" (click)="removeItemInTodoArr(item);">
<i class="fa fa-trash" aria-hidden="true"> </i>
</span>
<span class="trash" (click)="content.openLg(content)">
<i class="fa fa-pencil" aria-hidden="true"> </i>
</span>
</li>
</ul>
</div>
<update-todo></update-todo>
and app.component.ts looks like this.
import { Component, OnInit } from '#angular/core';
import { NgbdModalOptions } from '../shared/modals/todo/update-todo';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
/* todo array list */
todoArray: String[] = [];
todo: string = "";
constructor() {
}
ngOnInit() {
}
/* Push data in todo array */
pushInTodoArr(value) {
this.todoArray.push(value);
this.todo = '';
}
/* remove item in array */
removeItemInTodoArr(key) {
for (var i = this.todoArray.length - 1; i >= 0; i--) {
if (this.todoArray[i] === key) {
this.todoArray.splice(i, 1);
}
}
}
/* update item in array */
updateItemInTodoArr(key,updatedValue) {
for (var i = this.todoArray.length - 1; i >= 0; i--) {
if (this.todoArray[i] === key) {
this.todoArray[i] = updatedValue;
}
}
}
}
Its basically a todo app. Which adds delete and updates. I want to update the field in modal.
This is my update-todo.ts.
import {Component, ViewEncapsulation} from '#angular/core';
import {NgbModal, ModalDismissReasons} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'update-todo',
templateUrl: './update-todo.html',
encapsulation: ViewEncapsulation.None,
styleUrls: ['./update-todo.css']
})
export class NgbdModalOptions {
closeResult: string;
constructor(private modalService: NgbModal) {}
openLg(content) {
this.modalService.open(content, { size: 'lg' });
}
}
Now I want to open the pop up and pass the value on click update icon. i am calling this function (click)="content.openLg(content)" but i get Cannot read property 'openLg' of undefined.
Will some one please point me to right direction. I am stumbling between ng-bootstrap,ngx-bootstrap and ng2-bootstrap. But i want to do it with ng-bootstrap.
This is how I did it in my app:
Import:
import { NgbModal, NgbModalOptions } from '#ng-bootstrap/ng-bootstrap';
constructor:
constructor(
private _modalService: NgbModal
) { }
Call:
onEdit(car: ICars) {
const modalRef = this._modalService.open(RentACarDetailComponent, { size: 'lg' });
modalRef.componentInstance.car = car;
modalRef.componentInstance.type = 'edit';
modalRef.componentInstance.pageTitle = 'Edit vehicle';
modalRef.result.then((result) => {
if (result) {
let answer: number;
this._rentACarService.editVehicle(result, 2)
.takeUntil(this.ngUnsubscribe)
.subscribe(
result => { answer = result; },
error => { this.errorMessage = <any>error; },
() => {answer > 0) {
this._helperService.showInfo('You have succesfully editet vehicle.', 5);
this.ngOnInit();
}
});
}
},
(reason) => { });
}
car, type and PageTitle are set as Inputs in modal component
I am trying to push on an array for every interval but for some reason I get an error either it is ERROR TypeError: Cannot set property 'NaN' of undefined if I use this.numbers[this.value] = this.value; or it is core.es5.js:1020 ERROR TypeError: Cannot read property 'push' of undefined if I use this.numbers.push(this.value);
here is my code
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-game-control',
templateUrl: './game-control.component.html',
styleUrls: ['./game-control.component.css']
})
export class GameControlComponent implements OnInit {
timer = null;
value: number;
interval: number;
numbers = [];
constructor() { }
ngOnInit() {
console.log(this.numbers);
}
onClickStart() {
console.log('timer called');
if (this.timer !== null) {
return;
}
this.timer = setInterval(function() {
this.value += 1;
// console.log(this.numbers[this.value - 1 ]);
// this.numbers[this.value] = this.value;
this.numbers.push(this.value);
console.log(this.numbers);
}, this.interval );
}
onClickStop() {
clearInterval(this.timer);
this.timer = null;
}
}
My html is
<div class="row">
<div class="col-xs-12 ">
<button type="submit" class="btn btn-success" (click)="onClickStart()">Start</button>
<button type="button" class="btn btn-danger" (click)="onClickStop()">Stop</button>
<button type="button" class="btn btn-primary" >Clear</button>
</div>
</div>
<div class="row">
<div class="col-xs-10">
<hr>
<ul class="list-group">
<a
class="list-group-item"
style="cursor: pointer"
*ngFor="let number of numbers"
>
<app-even [num]="number" ></app-even>
<app-odd [num]="number" ></app-odd>
</a>
</ul>
</div>
</div>
but I don't think it matters yet
function () {} causes this not to point to the current class instance anymore, as most coming from other languages would expect, use arrow functions instead to get the desired behavior:
this.timer = setInterval(() => {