Javascript Angular Blocking? - javascript

I have an angular function that looks for a 'list' parameter in the initial URL, and if found will go out and get information. Otherwise I want to get the geolocation. I don't want to get geolocation if the URL param is present. Am I even using the right terms?
constructor(private router: Router, private activatedRoute: ActivatedRoute, private providerService: ProviderService) { }
ngOnInit(): void {
this.processURL();
this.processGPS();
}
private processURL() {
console.log('1a');
this.activatedRoute.queryParams.forEach(item => {
if (item['list']) {
console.log('1b');
this.providerService.setCurrentProvider(item['list']);
}
});
}
private processGPS() {
console.log('2a');
window.navigator.geolocation.getCurrentPosition(position => {
this.providerService.findByGeo(position.coords).subscribe(providers => {
if (providers.length > 0) {
console.log('2b');
this.providerService.setCurrentProvider(providers[0]);
}
},
() => {
console.log('GeoLocation Not available or disabled');
}).unsubscribe();
});
}

queryParams is an Observable, not an array, so you should subscribe to it.
What I did:
subscribe to the this.activatedRoute.queryParams
check if the list property exists on the parameters
If it does exist call some service
Else if it does not exist use GPS
ngOnInit(){
this.activatedRoute.queryParams.subscribe( params => {
if( typeof params.list !== 'undefined')
this.providerService.setCurrentProvider( params.list );
else
this.processGPS();
});
}

Move the processGPS to an else when the list parameter is not found:
ngOnInit(): void {
this.processURL();
}
private processURL() {
console.log('1a');
this.activatedRoute.queryParams.subscribe(item => {
if (item['list']) {
console.log('1b');
this.providerService.setCurrentProvider(item['list']);
} else {
this.processGPS();
}
});
}

Related

Cannot set property 'id' of undefined when trying to get a object

I am having an issue when I try to get a specified user from Firebase, Firestore.
export class TaskService {
tasksCollection: AngularFirestoreCollection<Task>;
taskDoc: AngularFirestoreDocument<Task>;
tasks: Observable<Task[]>;
task: Observable<Task>;
constructor(private afs: AngularFirestore) {
this.tasksCollection = this.afs.collection('tasks', ref => ref.orderBy('title', 'asc'));
}
getTask(id: string): Observable<Task> {
this.taskDoc = this.afs.doc<Task>(`clients/${id}`);
this.task = this.taskDoc.snapshotChanges().pipe(map(action => {
if (action.payload.exists === false) {
return null;
} else {
const data = action.payload.data() as Task;
data.id = action.payload.id;
return data;
}
}));
return this.task;
}
}
And this is my Component.ts file
export class TaskDetailsComponent implements OnInit {
id: string;
task: Task;
hasHours = false;
showHoursOnUpdate: false;
constructor(
private taskService: TaskService,
private router: Router,
private route: ActivatedRoute
) { }
ngOnInit() {
// Get id from url
this.id = this.route.snapshot.params.id;
// Get client
this.taskService.getTask(this.id).subscribe(task => {
if (task != null) {
if (task.hours > 0) {
this.hasHours = true;
}
}
this.task = task;
});
console.log(this.id);
console.log(this.task);
}
}
The result for id is good.
But the result for object (task) is undefined.
P.S
I also have functions for getting all the users and adding a new user, so if that's relevant please let me know in the comments
Your line of code
this.id = this.route.snapshot.params.id;
In this case id is not a table column but it's your document id by Firestore
Here an example of firestore
So your Id in this case is the red one and not the blue one.

Chrome autocomplete lock inputs like they are not clickable

I have a problem and very strange behavior with autofill in Chrome. When I login and then logout from app, input fields (email, password) were autocompleted but fields looks like they are frozen and not clickable.
This bug is not every time reproduced, it happens in 1/10 cases.
I noticed on logout when fields get autocompleted, after 1 seconds font gets smaller in inputs and after that if you click on input there it seems like you are not clicking , nothing happens, but if you type some text (numbers not work, stays like frozen) input field goes as normal.
Here is gif with strange behavior:
https://gifyu.com/image/kTkX
I tried to set autocomplete="off" , but not working.
Also I matched all css clases in input fields to see is there some overriding css, but everything looks good.
<form [formGroup]="loginForm">
<input id="emailHeader" type="text" formControlName="email" placeholder="E-mail">
<input #password type="password" formControlName="password" placeholder="Lozinka">
<input type="submit" (click)="executeLogin()" value="Prijava">
</form>
I expect to fields not been frozen after autofill.
public loginForm: FormGroup;
public emailInput: ElementRef;
public passwordInput: ElementRef;
#ViewChild('email') set emailContent(content: ElementRef) {
this.emailInput = content;
}
#ViewChild('password') set passwordContent(content: ElementRef) {
this.passwordInput = content;
}
// UI helpers
public showLoginForm: boolean;
public showBalance: boolean;
public player: PlayerModel = new PlayerModel({});
public balanceInfo: BalanceInfoModel = new BalanceInfoModel({});
public nxcsBalanceInfo: NXCSBalanceInfoModel = new NXCSBalanceInfoModel({});
public dialogType = DialogType;
public customMessageError = '';
// Store
private headerState$: Observable<any>;
private loginState$: Observable<any>;
private playerState$: Observable<any>;
private emailInput$: Observable<any>;
private passwordInput$: Observable<any>;
private balanceState$: Observable<any>;
private headerSubscription: Subscription;
private loginSubscription: Subscription;
private playerSubscription: Subscription;
private emailSubscription: Subscription;
private passwordSubscription: Subscription;
private balanceSubscription: Subscription;
// tslint:disable-next-line:no-inferrable-types
private leftMenu: string = '';
// tslint:disable-next-line:no-inferrable-types
private rightMenu: string = '';
constructor(
private authService: AuthService,
private fb: FormBuilder,
private store: Store<any>,
private route: Router,
private localStorageService: LocalStorageService,
private playerService: PlayerService,
private notificationService: NotificationService,
private dialogService: DialogService,
private helpers: HelpersService,
private translateCode: TranslateCode,
private promotionService: PromotionService,
) {
this.loginForm = this.buildLoginForm();
}
ngOnInit() {
this.setupStore();
}
ngAfterViewInit() {
this.formEventsAfterViewInit();
}
ngOnDestroy() {
this.headerSubscription.unsubscribe();
this.loginSubscription.unsubscribe();
this.playerSubscription.unsubscribe();
this.notificationService.closeConnection();
}
public executeLogin() {
if(!this.loginForm.valid) {
this.customMessageError = this.translateCode.transform("EMPTY_INPUT_MESSAGE");
return;
}
this.authService.login(new LoginModel({...this.loginForm.value, details: this.helpers.sendSessionData()}))
.subscribe(
data => {
this.localStorageService.setUserAfterLogin(data.token);
this.customMessageError = '';
this.loginForm.reset();
this.route.navigate(['/app/casino']);
},
error => {
error.message.includes('Račun je zaključan') ? this.store.dispatch(new PopupNotification(error.message)) : this.customMessageError = error.message
this.addAfterErrorSubscription();
}
);
}
public openDialog(dialogType: string): void {
switch (dialogType) {
case DialogType.PAYMENT:
this.openWithdrawalDialog()
break;
case DialogType.PAYMENT_DEPOSIT:
this.checkRegistrationStep();
break;
case DialogType.TRANSACTION_HISTORY:
this.store.dispatch(new OpenDialog({
type: dialogType,
}));
break;
}
}
public openInternalTransactionsDialog(): void {
this.promotionService.getPromotionsByLocation('NXCS_DEPOSIT')
.subscribe(
data => this.dialogService.openDialog(MENU_DIALOGS.INTERNAL_TRANSACTION, { promotions: data }),
error => this.dialogService.openDialog(MENU_DIALOGS.INTERNAL_TRANSACTION, { promotions: []}),
);
}
public backToRegistrationStep() : void {
switch (this.player.registrationStep) {
case 1 : this.route.navigate(['/auth/registration/step-two']);
break;
case 2 : this.route.navigate(['/auth/registration/step-three']);
break;
case 3 : this.route.navigate(['/auth/registration/step-four']);
break;
case 4 : this.route.navigate(['/auth/registration/step-five']);
break;
case 5 : this.route.navigate(['/auth/registration/step-six']);
break;
default : this.route.navigate(['/login']);
break;
}
}
public toggleMenu(dialog): void {
if (dialog === 'left') {
this.leftMenu = this.leftMenu === dialog ? '' : dialog;
}
if (dialog === 'right') {
this.rightMenu = this.rightMenu === dialog ? '' : dialog;
}
this.dispatchShadow();
}
private openWithdrawalDialog(_data: any = {}): void {
const playerRole = this.localStorageService.getPlayer()['profileRole'];
if (playerRole === 'WITHDRAWAL_DISABLED' && this.player.uploadedAdditionalInfo) {
this.store.dispatch(new OpenNotification({ type: NotificationType.WITHDRAWAL_DISABLED }));
return;
}
playerRole === 'WITHDRAWAL_DISABLED' ?
this.store.dispatch(new OpenNotification({type: NotificationType.MONEY_LAUNDERING})) :
this.dialogService.openDialog(MENU_DIALOGS.WHITDRAWALS, _data);
}
private openProceedToRegistration(): void {
this.store.dispatch(new OpenNotification ({type: NotificationType.PROCEED_REGISTRATION}))
}
private checkRegistrationStep(): void {
if(this.player.registrationStep < 6) {
this.openProceedToRegistration();
} else {
this.dialogService.openDialog(MENU_DIALOGS.DEPOSITS, {});
}
}
private dispatchShadow(): void {
if (this.leftMenu !== '') {
this.store.dispatch(new OpenedLeftMenu());
this.leftMenu = '';
}
if (this.rightMenu !== '') {
this.store.dispatch(new OpenedRightMenu());
this.rightMenu = '';
}
}
private buildLoginForm(): FormGroup {
return this.fb.group({
email: [
'', Validators.compose([Validators.required, Validators.min(5)]),
],
password: [
'', Validators.compose([Validators.required, Validators.min(5)])
],
});
}
private loadBalance(): void {
this.playerService.getPlayerBalance().toPromise()
.then(data => this.store.dispatch(new SetPlayerBalance({balanceInfo: new BalanceInfoModel(data) })))
.then(() => {
if (this.player.externalId) {
this.playerService.getNXCSPlayerBalance()
.subscribe(
data => this.store.dispatch(new SetPlayerNXCSBalance({ nxcsBalanceInfo: new NXCSBalanceInfoModel(data) })),
error => console.log(error),
);
}
});
}
// Store methods
private setupStore(): void {
this.headerState$ = this.store.pipe(select('headerStore'));
this.loginState$ = this.store.pipe(select('loginStore'));
this.playerState$ = this.store.pipe(select('playerStore'));
this.balanceState$ = this.store.pipe(select('balanceStore'));
this.addSubscriptions();
}
private formEventsAfterViewInit(): void {
if (this.emailInput && this.passwordInput) {
this.emailInput$ = fromEvent(this.emailInput.nativeElement, 'focus');
this.passwordInput$ = fromEvent(this.passwordInput.nativeElement, 'focus');
this.addFormEventsSubscriptions();
}
}
private addFormEventsSubscriptions(): void {
this.emailSubscription = this.emailInput$.subscribe(() => this.triggerEmailFocus());
this.passwordSubscription = this.passwordInput$.subscribe(() => this.triggerPasswordFocus());
}
private triggerEmailFocus(): void {
this.emailInput.nativeElement.select();
if (this.emailSubscription) {
this.emailSubscription.unsubscribe();
}
}
private triggerPasswordFocus(): void {
this.passwordInput.nativeElement.select();
if (this.passwordSubscription) {
this.passwordSubscription.unsubscribe();
}
}
private addSubscriptions(): void {
this.addHeaderSubscription();
this.addLoginSubscription();
this.addPlayerSubscription();
this.setBalanceSubscription();
}
private addHeaderSubscription(): void {
this.headerSubscription = this.headerState$
.subscribe(headerState => this.showLoginForm = headerState !== HeaderActionTypes.LoginPage);
}
private addLoginSubscription(): void {
this.loginSubscription = this.loginState$
.subscribe(loginState => {
if (loginState) {
this.loadBalance();
this.notificationService.connect(localStorage.getItem('token'));
} else {
this.notificationService.closeConnection();
}
this.showBalance = loginState;
this.formEventsAfterViewInit();
});
}
private addPlayerSubscription(): void {
this.playerSubscription = this.playerState$
.subscribe(playerData => this.player = playerData);
}
private addAfterErrorSubscription(): void {
this.passwordSubscription = this.passwordInput$.subscribe(() => {
if (this.customMessageError !== '') {
this.customMessageError = '';
this.passwordSubscription.unsubscribe();
}
});
}
}
I was facing the same issue in Angular and found a workaround for this scenario, resetting the input field's value on input click seems to fix the locking issue for me.
HTML:
<input (click)="unfreezeInput($event)">
TS:
unfreezeInput(el) {
// setting input value again makes it editable
el.target.value = el.target.value;
}
This is an issue that happens every time Google Chrome autofills the fields when you permit it to save your login credentials on any form. It bugged me out the first times as well.
I tried giving it a shot or two back when I encountered it for the first, but I gradually moved on and accepted it as a not-a-big deal kinda bug that every chrome user gotta have to deal with.
So in conclusion, it's got nothing to do with your code. If you want to unfreeze the input fields, start typing something in them to change their value.
I hope, this helps you and your nerves in accepting this browser-related behavior.
Have you tried using the a href tag? I know it's an obvious thing, but sometimes we forget to do things like that. Also, you can use the a:hover tag in your CSS.

How to implement a remember me function?

I am doing an Angular 4 application with node js backend. I did the login form, and all is good I want to implement the function "remember me".
This my login service:
import { Injectable } from '#angular/core';
#Injectable()
export class loginService{
rememberMe: boolean;
constructor() { }
login(credentials) {
sessionStorage.setItem('Name', credentials.firstName);
sessionStorage.setItem('token', credentials.token);
}
getCostumer() {
const user = {
Name: sessionStorage.getItem('firstName'),
token: sessionStorage.getItem('token')
}
This is the component:
constructor(private signInService: SignInService, private router: Router,
public dialog: MatDialog, private authService: AuthService) { }
ngOnInit() { }
login(costumer) {
this.loginService.login(costumer).subscribe((data) => {
this.authService.login(data);
this.router.navigate(['home']);
this.dialog.closeAll();
}, err => {
this.message = err._body;
console.log(this.message);
});
}
}
Use localStorage instead of sessionStorage
In your case, you can do something like this:
if (isRemberMeChecked) {
...
localStorage.setItem('Name', credentials.firstName);
localStorage.setItem('token', credentials.token);
...
} else {
...
sessionStorage.setItem('Name', credentials.firstName);
sessionStorage.setItem('token', credentials.token);
...
}
If you want to get isRemberMeChecked value globally you can use angular service
What you want to do here is use localStorage for the rememberMe and credentials.firstName. The credentials.token you can store in the sessionStorage:
login(credentials) {
localStorage.removeItem('Name');
localStorage.removeItem('RememberMe');
sessionStorage.setItem('token', credentials.token);
if(rememberMe){
localStorage.setItem('Name', credentials.firstName);
localStorage.setItem('RememberMe', JSON.stringify(this.rememberMe));
}
}
After a reload it will fetch the RememberMe and Name:
if(JSON.parse(localStorage.getItem('RememberMe')) !== null)
{
this.name = localStorage.getItem('Name');
this.rememberMe = JSON.parse(localStorage.getItem('RememberMe'));
}

listen to object property changes inside array in a service

So basically what I want to achieve is watching/listening objects changing inside of array within an injectable service using setters and getters to manipulate it's data
eg
#Injectable()
export class StorageService {
protected items: Array<any> = [];
constructor(private storage: Storage) {
this.storage.ready().then(() => {
StorageService.getGetters().forEach((get) => {
this.storage.get(get).then(res => this.items[get] = res);
});
});
}
public static getGetters(): string[] {
return Object.keys(this.prototype).filter(name => {
return typeof Object.getOwnPropertyDescriptor(this.prototype, name)["get"] === "function"
});
}
get Storage() {
return this.storage;
};
ClearStorage() {
this.storage.clear();
}
protected Setter(key: string, value: any): void {
this.items[key] = value;
this.storage.set(key, value);
}
protected Getter(key: string): any {
return this.items[key];
}
set User(value: User) {
this.Setter('User', value);
}
get User(): User {
return this.Getter('User');
}
}
where User interface is :
export interface User {
id: number;
role_id: number;
name: string;
email?: string;
}
now in any component or service/provider I can DI my StorageService so I can access the User getter.
so:
storage.User.name = 'testing';
now the name is changed , but I have no way to track that , so I can update my storage!
to update my storage I would do:
storage.User.name = 'testing';
storage.User = storage.User;
which is working , but I need a way to listen to any changes happens to the object properties, so I can update my storage...
I searched alot , and all I can find is watching components #Input() , which is not working in my case.
Hopefully I made my point clear.

Observer callback is not invoked when using rxjs interval

I have this method:
export class PeriodicData {
public checkForSthPeriodically(): Subscription {
return Observable.interval(10000)
.subscribe(() => {
console.log('I AM CHECKING');
this.getData();
});
};
public getData(): Observable<MyObject> {
let objects: MyObject[] = this.filterData();
return Observable.from(objects);
}
public filterData(): MyObject[] {
let someData;
// someData = filter(...) // logic to filter data
return someData;
}
}
Now I subscribe to getData() in another class:
class Another {
constructor(private periodicData: PeriodicData ) {
this.periodicData.getData().subscribe(obj => {
console.log('IN ANOTHER CLASS');
});
}
}
This is not working. The "IN ANOTHER CLASS" is not being logged. Am I missing something ?
If you tested this only with live TypeScript transpiler, then it doesn't throw an error when you don't specifically include Observable and the from operator (even though I don't know why).
I added to the top of app.component.ts and it works now:
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/from';
See your demo on plnkr.co: http://plnkr.co/edit/uVnwG3bo0N8ZkrAgKp7F

Categories

Resources