Cannot close ngb-datepicker with .close() (.close() is not a function) - html

I am attempting to set up a ngb-datepicker to close on clicking outside of it. I am however receiving this error:
GamesComponent.html:9 ERROR TypeError: dp.close is not a function
at GamesComponent.push../src/web/apps/command-center/games/games.component.ts.GamesComponent.closeCalendar (games.component.ts:202)
at Object.eval [as handleEvent] (GamesComponent.html:12)
at handleEvent (core.js:10050)
at callWithDebugContext (core.js:11143)
at Object.debugHandleEvent [as handleEvent] (core.js:10846)
at dispatchEvent (core.js:7509)
at core.js:7953
at HTMLDocument.<anonymous> (platform-browser.js:1140)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:3748)
The relevant html is below
<ng-template #popContent class="col-lg-3 align-items-center">
<ngb-datepicker (select)="convertNgbDatetoDate($event)"
name="dp" ngbDatepicker #d="ngbDatepicker"
(blur)="onInputBlur()"
(document:click)="closeCalendar($event, d)">
</ngb-datepicker>
</ng-template>
and the ts
closeCalendar(event, dp) {
console.log(dp)
const path = event.path.map(p => p.localName);
if ((!path.includes('ngb-datepicker') && !path.includes('ng-
container') && !path.includes('gns-sentient-dates') &&
!path.includes('howser-input'))) {
dp.close();
this.onInputBlur();
}
}
Any ideas as to what I am missing?

Closing ngb-datepicker with clicking outside is an open issue of ng-bootstrap since 2016. Have a look at this issue.
Possible workarounds:
A)
use view:
(click)="d.toggle(); $event.stopPropagation();" (document:click)="d.close()"
or B)
use component:
if(!this._eref.nativeElement.querySelector('ngb-datepicker').contains(event.target)
&& !this._eref.nativeElement.querySelector('.input-group-addon').contains(event.target)) {
let self = this;
setTimeout(function(){
self.dynamicId.close();
},10);
}
or C)
use view:
<input style="background-color: white;" class="form-control" placeholder="YYYY-MM-DD" name="date" [(ngModel)]="date" ngbDatepicker #eToggle="ngbDatepicker" (click)="eToggle.toggle(); sToggle.close();$event.stopPropagation()" (document:click)="decideClosure($event, eToggle)" readonly>
and component:
decideClosure(event, datepicker) { const path = event.path.map(p => p.localName); if (!path.includes('ngb-datepicker')) { datepicker.close(); } }

Related

Receiving errors when initializing Stripe payment page and when submitting card details

On my Angular/typescript page where I save credit cards, I receive 2 different errors that I can't fix. I've only been able to find this online link that's similar: How to change stripe locale when the stripe variable has been initialized
When the page first loads and Stripe and the elements get initialized and loaded, I receive this error below:
Uncaught TypeError TypeError: Cannot read properties of undefined (reading 'queuedMessages')
at value (https://js.stripe.com/v3/fingerprinted/js/controller-803e2f3ecfca23afd889cd24f93bdf22.js:1:452741)
at (https://js.stripe.com/v3/fingerprinted/js/controller-803e2f3ecfca23afd889cd24f93bdf22.js:1:451881)
value # js.stripe.com/v3/fingerprinted/js/controller-803e2f3ecfca23afd889cd24f93bdf22.js:1:452741
When I submit my card details the function 'stripe.createToken()' bombs out and I receive this error below:
ERROR IntegrationError: Please use the same instance of Stripe you used to create this Element to create your Source or Token.
at Ii (/Users/mysite/client:1:350323)
at e._handleMessage (/Users/mysite/client:1:355676)
at e._handleMessage (/Users/mysite/client:1:152157)
at /Users/mysite/client:1:353245
at _ZoneDelegate.invokeTask (/Users/mysite/client/node_modules/zone.js/fesm2015/zone.js:406:1)
at Object.onInvokeTask (/Users/mysite/client/node_modules/#angular/core/fesm2015/core.mjs:25535:1)
at _ZoneDelegate.invokeTask (/Users/mysite/client/node_modules/zone.js/fesm2015/zone.js:405:1)
at Zone.runTask (/Users/mysite/client/node_modules/zone.js/fesm2015/zone.js:178:1)
at ZoneTask.invokeTask [as invoke] (/Users/mysite/client/node_modules/zone.js/fesm2015/zone.js:487:1)
at invokeTask (https://localhost:4200/polyfills.js:4776:18) {message: 'Please use the same instance of Stripe you…this Element to create your Source or Token.', name: 'IntegrationError', stack: 'IntegrationError: Please use the same instanc…(https://localhost:4200/polyfills.js:4776:18)'}
Here is the code below where I'm having the 2 issue's.
// Just below all my imports, I declare Stripe like this
declare
const Stripe: any;
// Stripe and the elements get initialized in the ngAfterViewInit() like this
ngAfterViewInit() {
const style = {
// all style css left out for brevity
};
this.stripe = Stripe('pk_test_fTrh6B1...');
this.stripeElements = this.stripe.elements();
this.cardNumber = this.stripeElements.create('cardNumber', {
style
});
this.cardNumber.mount(this.cardNumberElement.nativeElement);
this.cardNumber.addEventListener('change', this.cardNumberHandler);
this.cardExpiry = this.stripeElements.create('cardExpiry', {
style
});
this.cardExpiry.mount(this.cardExpiryElement.nativeElement);
this.cardExpiry.addEventListener('change', this.cardExpiryHandler);
this.cardCvc = this.stripeElements.create('cardCvc', {
style
});
this.cardCvc.mount(this.cardCvcElement.nativeElement);
this.cardCvc.addEventListener('change', this.cardCvcHandler);
});
}
// here is the submit button to save card details
submitCard() {
this.loadingPayment = true;
const cardData = {
name: this.nameOnCard.value,
};
// 2nd error gets thrown below on createToken()
from(this.stripe.createToken(this.cardNumber, cardData)).pipe(take(1)).subscribe((result: any) => {
if (result.error) {
this.loadingPayment = false;
this.alertService.danger(result.error.message);
} else {
if (['Visa', 'MasterCard', 'Discover', 'American Express'].includes(result.token.card.brand) === true) {
this.accountService.saveCard({
token: result.token.id
}).subscribe(() => {
this.router.navigate(['/account/cards']);
this.alertService.success('Card added successfully');
}, error => {
console.log(error);
}).add(() => {
this.loadingPayment = false;
});
} else {
this.loadingPayment = false;
this.alertService.info('Only Visa, MasterCard, Discover or American Express are accepted');
}
}
});
}
<div class="mt-4" [formGroup]="paymentForm">
<div class="form-floating mb-3">
<input type="text" class="form-control" id="floatingName" placeholder="ex. John Smith" formControlName="nameOnCard" required maxlength="30" pattern="^[a-zA-Z\s]*$" [ngClass]="{'is-valid': nameOnCard.valid, 'is-invalid': nameOnCard.invalid && (nameOnCard.dirty || nameOnCard.touched)}">
<label for="floatingName">Name on Card</label>
<div *ngIf="nameOnCard.invalid && (nameOnCard.dirty || nameOnCard.touched)">
<div class="invalid-feedback d-block" role="alert" *ngIf="nameOnCard.errors.required">
Name is required
</div>
<div class="invalid-feedback d-block" role="alert" *ngIf="nameOnCard.errors.pattern">
Only characters are permitted
</div>
</div>
</div>
<div class="form-floating mb-3">
<div class="form-control" id="floatingNumber" placeholder="ex. 1111-1111-1111-1111" #cardNumber [ngClass]="{'is-valid': cardNumberValid === true, 'is-invalid': cardNumberValid === false && cardNumberErrors !== null}"></div>
<label for="floatingNumber">Number</label>
<div *ngIf="cardNumberErrors" class="invalid-feedback d-block" role="alert">
{{cardNumberErrors}}
</div>
</div>
<div class="form-floating mb-3">
<div class="form-control" id="floatingExpiration" placeholder="ex. 11/24" #cardExpiry [ngClass]="{'is-valid': cardExpiryValid === true, 'is-invalid': cardExpiryValid === false && cardExpiryErrors !== null}"></div>
<label for="floatingExpiration">Expirtion</label>
<div *ngIf="cardExpiryErrors" class="invalid-feedback d-block" role="alert">
{{cardExpiryErrors}}
</div>
</div>
<div class="form-floating mb-3">
<div class="form-control" id="floatingCvc" placeholder="ex. 123" #cardCvc [ngClass]="{'is-valid': cardCvcValid === true, 'is-invalid': cardCvcValid === false && cardCvcErrors !== null}"></div>
<label for="floatingCvc">CVC</label>
<div *ngIf="cardCvcErrors" class="invalid-feedback d-block" role="alert">
{{cardCvcErrors}}
</div>
</div>
<nav class="navbar fixed-bottom navbar-light bg-light">
<div class="container-md px-3">
<div class="w-100">
<button class="btn btn-yb float-md-end" style="width: 100px;" [disabled]="paymentForm.invalid || loadingPayment || paymentForm.pristine || !cardNumberValid || !cardExpiryValid || !cardCvcValid" [ngClass]="{'nopacity' : loadingPayment}" type="button" (click)="submitCard()">
<span *ngIf="loadingPayment" class="spinner-border spinner-border-sm color-white" role="status" aria-hidden="true"></span>
<span class="sr-only">Loading...</span>
<span *ngIf="!loadingPayment">Save</span>
</button>
</div>
</div>
</nav>
</div>
I think it's best to create a Service where you initialize your Stripe instance once and then use that in the Component. This might solve both issues at once.

Angular 5+ component HTMLElement.style.display suddenly give cannot read property 'style' of 'null'

I have a angular 5.2.0/Typescript 2.6.2 and Node 8.5.0 app that uses
HTML:
<button mat-raised-button id="submitDescription" class="submit-class" [ngStyle]="{'color':
themeFontColor()}" (click)="submit(false)">{{submit}}</button>
...
Component.ts:
....
submitBtn: HTMLElement;
.....
.....
ngOnInit{
......
.......
}
ngAfterViewInit() {
this.submitBtn = document.getElementById('submitDescription');
this.viewLoaded = true;
}
Now suddenly the line
this.submitBtn.style.display = 'none';
produce this error
Error: Uncaught (in promise): TypeError: Cannot read property 'style' of null
TypeError: Cannot read property 'style' of null
The similar code is in two components now without any modification to the code I am getting this error in both places which lead me to believe something external has changed but I have no idea what. Could Service Workers be causing this problem?
EDIT:
HTML:
<input [ngClass]='{"has-error":(wholeDescriptionRef.invalid && submitted), "has-success":(wholeDescriptionRef.valid && submitted)}' type="text" class="form-control query-input content-light-blue-color" id="wholeDescription" placeholder="{{ezzy.LOCALIZATION.requestPlaceHolder}}"
[ngStyle]="{'background-color': ezzy.getThemeSecondaryColor()}" name="wholeDescription" [(ngModel)]="wholeDescription" maxlength="100" #wholeDescriptionRef="ngModel" required (keyup)="submitOnEnter($event)">
<button mat-raised-button #submitDescription class="submit-class" [ngStyle]="{'color': ezzy.getThemeFontColor()}" (click)="submit(false)">{{ezzy.LOCALIZATION.submit}}</button>
<span [hidden]="!ezzy.supportsSpeech" (click)="ezzy.startDictation(this, 'wholeDescription', 'submit', 'wholeDescription', 'submitDescription')" class="input-group-addon cursor-pointer icon-style" [ngStyle]="{'color':'#ffffff','background-color': ezzy.getThemeHeaderColor(), 'border': ezzy.getThemeBorderColor(), 'border-collapse': 'collapse'}">
<i class="fa fa-microphone fa-lg" aria-hidden="true"></i></span>
Apparently the answer lies in tsconfig.json file...(credit to this answer https://github.com/angular/components/issues/9813)
......
........
"target": "es2015",
"typeRoots": [
"node_modules/#types"
],
"lib": [
"es2016",
"dom",
"es2015"
]
Where "target": "es2015" should be set to "es5"

ERROR TypeError: Cannot read property 'name' of undefined angular

I'm developing an app using Laravel as backend and Angular as frontend. To login and register I'm trying to use JWT but when I try to register using the register form I get the following error: "ERROR TypeError: Cannot read property 'name' of undefined".
register.component.html
<form #registerForm=ngForm (ngSubmit)="onSubmit()">
<div class="form-group row mx-auto">
<label for="inputName3" class="col-md-6 col-form-label">Name</label>
<div class="col-md-12">
<input type="text" name="name" class="form-control"
placeholder="Name" [(ngModel)]="form.name" required>
<div class="alert alert-danger mt-2" [hidden]="!error.name">
<i class="fa fa-times-circle"></i> {{error.name}}
</div>
</div>
</div>
...
</form>
register.component.js
export class RegisterComponent implements OnInit {
public form = {
name: null,
email: null,
password: null,
password_confirmation: null
};
constructor(private http: HttpClient) { }
onSubmit(){
return this.http.post('http://localhost/api/auth/register',
this.form).subscribe(
data => console.log(data),
error => this.handleError(error)
);
}
ngOnInit() {
}
}
In the template, your test [hidden]='!error.name' is not valid because the variable error is not defined in the controller (.ts).
You should define error property with type object in the component.
because Angular expects an object called error with name key.
If you wait error from the backend or you need a quick solution just put ? (question mark) after error word in HTML like: [hidden]='!error?.name'.
This will make Angular check for error variable before checking for name property.

Uncaught Error: Can't resolve all parameters for Component: ([object Object]?)

So, before You read the whole error stack, keep in mind that at this time I cant pinpoint the exact piece that causes the problem. However, I will disclose the code below the error stack. So, my only question is: what parameters can't be resolved?
If you like, you can test my application for yourself. It is a simple default angular 6 application with all the default settings you get from the following command below:
ng new app-name
let's begin with the error. The application starts like normal. When I try to run the code, this error pops up: Uncaught Error: Can't resolve all parameters for Component: ([object Object]?). You can read the full error stack below.
Uncaught Error: Can't resolve all parameters for Component: ([object Object]?).
at syntaxError (compiler.js:1016)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata (compiler.js:10917)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getTypeMetadata (compiler.js:10810)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNonNormalizedDirectiveMetadata (compiler.js:10429)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.loadDirectiveMetadata (compiler.js:10291)
at compiler.js:23865
at Array.forEach (<anonymous>)
at compiler.js:23864
at Array.forEach (<anonymous>)
at JitCompiler.push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._loadModules (compiler.js:23861)
syntaxError # compiler.js:1016
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata # compiler.js:10917
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getTypeMetadata # compiler.js:10810
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNonNormalizedDirectiveMetadata # compiler.js:10429
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.loadDirectiveMetadata # compiler.js:10291
(anonymous) # compiler.js:23865
(anonymous) # compiler.js:23864
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._loadModules # compiler.js:23861
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents # compiler.js:23839
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler.compileModuleAsync # compiler.js:23799
push../node_modules/#angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.compileModuleAsync # platform-browser-dynamic.js:143
push../node_modules/#angular/core/fesm5/core.js.PlatformRef.bootstrapModule # core.js:4352
./src/main.ts # main.ts:11
__webpack_require__ # bootstrap:76
0 # main.ts:12
__webpack_require__ # bootstrap:76
checkDeferredModules # bootstrap:43
webpackJsonpCallback # bootstrap:30
(anonymous) # main.js:1
As you see, there is no easy way of telling which part of my typescript is causing the problem. However, The application runs fine without the code in component.ts shown below. So, there is definitely something wrong with my typescript component.ts
the component.ts is shown below:
import {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, Directive} from '#angular/core';
import { FormGroup } from '#angular/forms';
import { DefineBusinessRuleService } from '../services/define/define-business-rule.service';
import { DefineBusinessRuleNamespace } from '../model/business-rule-namespace';
#Component({
selector: 'app-define-business-rule',
templateUrl: './define-business-rule.component.html',
styleUrls: ['./define-business-rule.component.css']
})
export class DefineBusinessRuleComponent implements OnInit {
// interfaces
headers : Headers;
output: any;
#Input() minValue: string;
#Input() maxValue: string;
#Input() attribute : Array<string>;
#Input() table : Array<string>;
submitted = false;
#Input() businessRuleType : Array<string>;
ruletypes : Array<string>;
ruletype : string;
constructor(
private defineBusinessRuleService: DefineBusinessRuleService
,private model : any
) {
this.table = ['table1', 'table2', 'table3'];
this.attribute = ['attribute1', 'attribute2', 'attribute3'];
this.ruletypes = [
// atrribute
'AttributeRange',
'AttributeCompare',
'AttributeList',
'AttributeOther',
'TupleCompare',
'TupleOther'
]
model = {
minValue : 5,
maxValue : 10,
name : 'RangeRule',
description : 'This is a Range Rule',
table1 : this.table[0],
column1 : this.attribute[2],
errorMsg : 'Error message'
};
}
get diagnostic() { return JSON.stringify(this.model); }
defineNewBusinessRule() {
//this.model = new DefineBusinessRuleService(42, 50, '', '', '', '', '');
}
saveAttributeRangeRule(){
this.output = {
database_id : 1,
minValue : this.minValue,
maxValue : this.maxValue,
table1 : this.table,
column1 : this.attribute
}
this.output.stringify;
this.defineBusinessRuleService.saveAttributeRangeRule(this.output);
}
saveAttributeCompareRule(){
this.output = {
database_id : 1,
table1 : this.table,
//table2 : this.table2,
column1 : this.attribute,
//column2 : this.attribute2,
//value : this.value
}
this.output.stringify;
//this.defineBusinessRuleService.saveAttributeCompareRule(this.output);
}
ngOnInit(){
}
onSelect(){
}
onSubmit() {
this.submitted = true;
this.ruletype = this.ruletypes[0];
switch(this.ruletype){
case "AttributeRange" : {
this.saveAttributeRangeRule();
break;
};
case "AttributeCompare" : {
this.saveAttributeCompareRule();
break;
};
}
}
}
Thanks for reading this! If you are visually orientated like me, then this form might help you understand what this code should do. However, it's off topic, since i'm certain enough that it doesn't cause operational problems in angular. keep that in mind!
the related html form is shown below
<br>
<br>
<main role="main" class="container">
<div class="container">
<h1>Define Business Rule</h1>
<form (ngSubmit)="onSubmit()" #defineBusinessRuleForm="ngForm">
<div class="form-group">
<label for="minValue">Minimum Value</label>
<input type="text" class="form-control" id="minValue">
</div>
<div class="form-group">
<label for="maxValue">Maximum Value</label>
<input type="text" class="form-control" id="maxValue">
</div>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Name is required
</div>
</div>
<div class="form-group">
<label for="description">Description</label>
<input type="text" class="form-control" id="description" required>
</div>
<div class="form-group">
<label for="table">Table</label>
<select class="form-control" id="table" required>
<option *ngFor="let tbl of table" [value]="table">{{tbl}}</option>
</select>
</div>
<div class="form-group">
<label for="attribute">Attribute</label>
<select class="form-control" id="attribute" required>
<option *ngFor="let attr of attribute" [value]="attribute">{{attr}}</option>
</select>
</div>
<div class="form-group">
<label for="errorMsg">Error Message</label>
<input type="text" class="form-control" id="errorMsg" required>
</div>
<button type="submit" class="btn btn-success" [disabled]="!defineBusinessRuleForm.form.valid">Submit</button>
<button type="button" class="btn btn-default" (click)="defineNewBusinessRule(); defineBusinessRuleForm.reset()">Define New BR</button>
</form>
</div>
</main>
The error is in the model definition location.
private model: any should be defined as a parameter outside of a constructor.
By placing it in the constructor, the compiler is trying to resolve any class, and, naturally is unable to do so.
Modify your code this way:
export class DefineBusinessRuleComponent implements OnInit {
private model : any
constructor() {
this.model = {
// your model definition
};
}
// rest of the code
}

Angular 4 error formating Date field in ISO format with DatePipe

In an angular 4 / nodejs application, I am retrieving the following date field from MongoDB:
"2018-06-14T03:00:00.000Z"
Here is my HTML:
<div *ngIf="this.Lacador.dataAssociacao">
<p style="margin-top: 10px" type="text"> <label style="font-weight: normal"> {{ this.Lacador.dataAssociacao | date:"dd/MM/yyyy" }} </label></p>
</div>
In the screen, the date is displayed (as per image), but I have an error in the console which messes with all the scripts of the page:
ERROR Error: InvalidPipeArgument: 'function Date() { [native code] }' for pipe 'DatePipe'
at invalidPipeArgumentError (common.es5.js:2610)
at DatePipe.webpackJsonp.../../../common/#angular/common.es5.js.DatePipe.transform (common.es5.js:3506)
at checkAndUpdatePureExpressionInline (core.es5.js:11665)
at checkAndUpdateNodeInline (core.es5.js:12370)
at checkAndUpdateNode (core.es5.js:12303)
at debugCheckAndUpdateNode (core.es5.js:13167)
at debugCheckRenderNodeFn (core.es5.js:13146)
at Object.eval [as updateRenderer] (LacadoresViewComponent.html:96)
at Object.debugUpdateRenderer [as updateRenderer] (core.es5.js:13131)
at checkAndUpdateView (core.es5.js:12275)
Date displayed correctly:
Any clues on why it throws an exception, even through it formats the field as I want?
Edit: Added a missing quote.