this is undefined in class - ecmascript-6

I have the following class
class ContractStore {
clauses = [];
addClause() {
this.clauses.push({
id: uuidv1()
})
}
}
export let contractStore = new ContractStore();
and then importing it as
import { contractStore } from '../store/ContractStore'
...
contractStore.addClause()
and I am getting this as undefined in addClause() method. what am i doing wrong here?

You are missing to set the context here. You can do it in two ways.
Arrow function way
class ContractStore {
clauses = [];
addClause = () => {
this.clauses.push({
id: uuidv1()
})
}
}
or
Bind way
class ContractStore {
constructor() {
this.addClause = this.addClause.bind(this)
}
clauses = [];
addClause() {
this.clauses.push({
id: uuidv1()
})
}
}
Thanks. Feedbacks are welcome

Related

Problem withAngular when I want to add elements in array

I have an animals array. I want to put in another array just the field "espece" of each animal.
I push all the espece of animals in especeAnimalPresenteTmp and then I remove the duplicates and save the next array in especeAnimalPresente.
I have this angular code :
import { Component, OnInit } from '#angular/core';
import { AnimalService } from "./animal.service";
import { Animal } from "./animal";
#Component({
selector: 'app-animal',
templateUrl: './animal.component.html',
styleUrls: ['./animal.component.css']
})
export class AnimalComponent implements OnInit {
private animaux:Array<Animal>;
private especeAnimalPresente:Array<string>;
private especeAnimalPresenteTmp:Array<string>;
constructor(private animalService: AnimalService) { }
ngOnInit() {
this.recupAllAnimals();
}
recupAllAnimals(){
this.animalService.getAllAnimaux().subscribe(data => {
this.animaux = data;
this.recupEspecePresent();
})
}
recupEspecePresent(){
// if (this.animaux){
for (let animal of this.animaux) {
this.especeAnimalPresenteTmp.push(animal.espece);
}
this.especeAnimalPresente = this.removeDuplicates(this.especeAnimalPresenteTmp);
// }
}
removeDuplicates(array) {
let unique = {};
array.forEach(function(i) {
if(!unique[i]) {
unique[i] = true;
}
});
return Object.keys(unique);
}
}
But I have this error in my console :
ERROR TypeError: "this.especeAnimalPresenteTmp is undefined"
recupEspecePresent animal.component.ts:32
recupAllAnimals animal.component.ts:24
RxJS 11
Angular 8
Someone can help me please ?
You have to initialize the array, for example in the constructor:
constructor(private animalService: AnimalService) {
this.especeAnimalPresenteTmp = [];
}

Angular Observable<ObjectModel> services return a string (instead an object of type ObjectModel)

here is my service:
get(id: string): Observable<PaginaModel> {
return this.http.get<PaginaModel>('api/pagini/get/' + id);
}
the model:
import { LinieModel } from "./linie.model";
export class PaginaModel {
linii: LinieModel[] = [];
}
and here how i call it:
ngOnInit() {
this.canvas = document.getElementById('AfisareCanvas') as HTMLCanvasElement;
this.ctx = this.canvas.getContext('2d');
this.service.get('5b9bad0c457b4e1c70af18f8').subscribe(data => {
console.log(data); //here data is string (like using stringify)
console.log(data.linii.length); //undefined error
});
}
i tried using JSON.parse but didnt work.

How to pass data from a component to another component

When I click to edit I can edit but when I try to append a kind to the parent it takes the parent infoprmation and not create a new VI.
With angular dialog I made like this but with component I dont know.
This is with dialog
<div class="dropdown-menu-item" (click)="openValueItemEditDialog({valueItem: valueItem})">Edit</div>
This is the TS
openValueItemEditDialog(editOptions: EditOptions) {
this.dialog.open(ValueItemEditDialogComponent, {data: editOptions, disableClose: true});
}
And this is the TS of dialog
constructor(private store: Store<ApplicationState>, #Inject(MAT_DIALOG_DATA) public editOptions: EditOptions) {
}
ngOnInit() {
if (this.editOptions.valueItem) {
this.editedValueItem = _.cloneDeep(this.editOptions.valueItem);
} else {
this.editedValueItem = emptyValueItem();
}
export interface EditOptions {
valueItem?: ValueItem;
appendToParentId?: string;
planning?: number;
}
But without dialog I dont know how to pass the data
showChild = false
edit(editOptions: EditViOptions) {
this.showChild = !this.showChild;
if (editOptions.valueItem) {
return editOptions.valueItem;
} else if (editOptions.appendToParentId) {
return editOptions.appendToParentId;
}
this.activeSelected = this.valueItem.id;
} //this open and closes the component
}
This is the Html of Service matrix row
<app-edit-dialog-vi [showMePartially]="showChild"></app-edit-dialog-vi>
<div *ngIf="valueItem.level < 7" class="dropdown-menu-item" (click)="edit({appendToParentId: valueItem})">Append2</div>
Here is the edit-dialog-vi
<div *ngIf="showMePartially" class="container">
</div>
In the constructor I dont know what to write
This is the TS file and interface what I have created for the Edit vi dialog
constructor(private store: Store<ApplicationState>, public editOptions: ServiceMatrixRowComponent) { }
ngOnInit() {
if (this.editOptions.valueItem) {
this.editedValueItem = _.cloneDeep(this.editOptions.valueItem);
console.log(this.editedValueItem, '***');
} else {
this.editedValueItem = emptyValueItem();
}
export interface EditViOptions {
valueItem?: ValueItem;
appendToParentId?: string;
planning?: number;
}
I don't know if I understood your question well, but you can try this :
ParentHtml
<app-edit-dialog-vi [data]="dataToPass" [showMePartially]="showChild"></app-edit-dialog-vi>
<div class="dropdown-menu-item" (click)="edit(valueItem.level < 7 ? {appendToParentId: valueItem.id} : {valueItem: valueItem})">Edit2</div>
Parent Ts
Add a property dataToPass, and set it to the data you want to send to the child.
showChild = false;
dataToPass: EditViOptions = null;
edit(editOptions: EditViOptions) {
this.showChild = !this.showChild;
if (editOptions.valueItem || editOptions.appendToParentId) {
this.dataToPass = editOptions;
}
this.activeSelected = editOptions.valueItem.id;
}
Child Ts
Add an input named data to get the data sent :
#Input() showMePartially = false;
#Input() data: EditViOptions = null;
constructor(private store: Store<ApplicationState>, public editOptions: ServiceMatrixRowComponent) { }
ngOnInit() {
if (this.data.valueItem || this.data.appendToParentId) {
this.editedValueItem = _.cloneDeep(this.data.valueItem);
console.log(this.editedValueItem, '***');
} else {
this.editedValueItem = emptyValueItem();
}
export interface EditViOptions {
valueItem?: ValueItem;
appendToParentId?: string;
planning?: number;
}
To learn better i will suggest you just look at the below link. It will let you know how to pass data from Parent-> Child and Child-->Parent component in different ways.
https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/
Hope it gonna help you.
Thanks

Pagination - How to wait till dataSource is ready/available

I have a pagination service and component which is working fine except that the dataSource is empty when loading the page first time. By second time, the dataSource is ready and I can display the dataTable and paginate.
Is there any fix to work around this issue, so that the function is invoked after the data is ready/loaded?
setTimeOut() would not be an option based on my tries.
list-user.service.ts:
let registeredUser:USers[] = [];
#Injectable()
export class ListUserService {
constructor(public loginService:LoginService){}
getUserDatasource(page:number, limit:number, sortBy?:string, sortType?:DatatableSortType): IPaginableUsers {
this.loginService.getUsersList().subscribe(
(res) => {
registeredUser = res.message
return registeredUser;
}, (err) => {})
}
...
...
}
list-users.component.ts:
export class ListUsersComponent implements AfterViewInit, OnDestroy {
...
...
constructor( private listUserService:ListUserService, private changeDetectorRef:ChangeDetectorRef) {
this.fetchUserDataSource();
}
ngOnInit(){}
ngAfterViewInit() {
if (this.datatable) {
Observable.from(this.datatable.selectionChange).takeUntil(this.unmount$).subscribe((e:IDatatableSelectionEvent) =>
this.currentSelection$.next(e.selectedValues)
);
Observable.from(this.datatable.sortChange).takeUntil(this.unmount$).subscribe((e:IDatatableSortEvent) =>
this.fetchUserDataSource(this.currentPagination.currentPage, this.currentPagination.itemsPerPage, e.sortBy, e.sortType)
);
Observable.from(this.pagination.paginationChange).takeUntil(this.unmount$).subscribe((e:IDatatablePaginationEvent) =>
this.fetchUserDataSource(e.page, e.itemsPerPage)
);
}
}
ngOnDestroy() {
this.unmount$.next();
this.unmount$.complete();
}
shuffleData() {
this.users$.next(shuffle(this.users$.getValue()));
this.currentSelection$.next([]);
this.changeDetectorRef.detectChanges();
}
private fetchUserDataSource(page:number = this.currentPagination.currentPage, limit:number = this.currentPagination.itemsPerPage, sortBy:string | undefined = this.currentSortBy, sortType:DatatableSortType = this.currentSortType) {
if (sortBy) {
this.currentSortBy = sortBy;
this.currentSortType = sortType;
}
const { users, pagination } = this.listUserService.getUserDatasource( page, limit, sortBy, sortType);
this.users$.next(users);
this.currentSelection$.next([]);
this.currentPagination = pagination;
}
}
you MUST subscribe in an ngOnInit to this.listUserService.getUserDataSource in your list-user-component
export class ListUsersComponent implements OnInit,...
{
page:number=1;
limit:number=5;
sortBy:string='';
....
ngOnInit() {
this.listUserService.getUserDataSource(page, limit, sortBy, sortType).subscribe((res)=>{
....here ...
}
}

Loading JSON data gives undefined object in Angular 2 - asynchronous?

...component.ts:
import { Component } from '#angular/core';
import { ValgteSkolerService } from '../valgteSkoler.service';
import { DatoService } from './datoer.service';
#Component({
selector: 'kalender',
providers: [DatoService],
templateUrl: 'app/kalendervisning/html/kalender.html'
})
export class KalenderComponent {
private valgteSkoleRuter: Array<any> = [];
public datoer: any[] = [];
constructor(private valgteSkolerService: ValgteSkolerService, private DatoService: DatoService) {
this.DatoService
.getDato()
.subscribe(datoer => { this.datoer = datoer; });
}
ngOnInit() {
this.valgteSkolerService.hentLagretData();
this.valgteSkoleRuter = this.valgteSkolerService.delteValgteSkoleRuter;
}
antallRuter: number = 0;
j: number = 0;
ukeEn(mnd: number, aar: number) :Cell[] {
var cells: Array<Cell> = [];
this.antallRuter = 0;
for (this.j = 1; this.j <= this.antallDager(mnd, aar); this.j++) {
var cell = new Cell;
console.log(this.datoer[this.j].dato);
cell.id = this.datoer[this.j].dato;
cell.text = this.j;
cells.push(cell);
this.antallRuter++;
this.j = this.j;
if (this.antallRuter % 7 == 0 && this.antallRuter != 0) {
break;
}
}
return cells;
}
class Cell {
id: string;
text: number;
}
...service.ts:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class DatoService {
dato: Array<any>;
constructor(private http: Http) {}
getDato() {
return this.http.request('app/kalendervisning/datoer.json')
.map(res => res.json());
}
}
...json:
{
"dato": "2016-08-01"
},
etc.
I am struggling with the cell.id = this.datoer[this.j].dato statement in the component.
I have checked the browser inspector, and it seems like the datoer array is undefined until the whole code has been run through several times. After a while, the array gets filled up. When I tested this with console.log, it prints 9 undefined objects, and then the actual data, but for some reason repeated 2 times also.
I think there might be a problem that the data is not loaded asynchronously, but I'm not sure.
Are there any ideas why it acts like this, and do you have a solution?
add constrctor code of calling API inside ngOnInit :
ngOnInit() {
this.DatoService
.getDato()
.subscribe(datoer => { this.datoer = datoer; });
this.valgteSkolerService.hentLagretData();
this.valgteSkoleRuter = this.valgteSkolerService.delteValgteSkoleRuter;
}