Pass angular component function to javascript function - boxfactura - javascript

I am implementing this feature in my angular code to pull to refresh data and its pretty straightforward.
const ptr = PullToRefresh.init({
mainElement: 'div.custom-div'
onRefresh() {
this.getData();
}
});
and i have a function in my component called getData()
export class HomeComponent implements OnInit {
constructor() {}
ngOnInit(): void {
const ptr = PullToRefresh.init({
mainElement: 'div.custom-div'
onRefresh() {
this.getData();
}
});
}
getData() {
// get data function
}
}
but I'm having a hard time calling that from the javascript function. It throws the error
getData is not a function
and I know it does this because it reads this as the js function instead of the component it is embedded in. How can i go about this correctly?

Try this:-
export class HomeComponent implements OnInit {
constructor() {}
ngOnInit(): void {
const This = this;
const ptr = PullToRefresh.init({
mainElement: 'div.custom-div'
onRefresh() {
This.getData();
}
});
}
getData() {
// get data function
}
}

Related

Angular-Listening to store changes & emit a value from a Service component to a different component - only after Service completes certain operations

Here we have to classes GetDataAsyncService which waits for change in the store (and not executes the block of code under it until a change in the store ( this.getDataAsyncService.getAsyncData().subscribe((data)=>{
)}). When it is called from MainComponent it will get return of(propA); (from GetDataAsyncService) before the block of code in the listener is executed - because the listener is still waiting for a change in the store.
I want to emit that observable only when that operation block is executed.
export class GetDataAsyncService {
propA;
constructor(private store: Store<AppState>)
getData():Observable<any>{
this.store.pipe(select(appState)).subscribe((val)=>{
// operation block
// some operations
// some more operations
this.propA = val.propA;
})
return of(propA); // this should be emitted with the latest value only when the block of code above executes - not before that
}
}
export MainComponent implenents OnInit{
propA: string = '';
constructor(private getDataAsyncService: GetDataAsyncService){}
ngOnInit(): void{
this.getDataAsyncService.getAsyncData().subscribe((data)=>{
this.propA = data.propA;
})
}
// any operation involving propA
// code ......
}
You can achieve that by returning the Observable itself from the getData function and mapping it to the required prop, instead of subscribe to it, like the following:
export class GetDataAsyncService {
propA;
constructor(private store: Store<AppState>) {}
getData(): Observable<any> {
return this.store.pipe(
select(appState),
map((val) => val.propA)
);
}
}
export class MainComponent implements OnInit {
propA: string = '';
constructor(private getDataAsyncService: GetDataAsyncService) {}
ngOnInit(): void {
this.getDataAsyncService.getAsyncData().subscribe((propA) => {
this.propA = propA;
});
}
}

How to get last object from array of object based on condition in angular 8

I have some objects, that I am receiving one after another using settimeout function and then pushing every time into array to populate into a table. That is coming dynamically in my project but just for reference I am using settimeout and hard coding here.
Now my problem is, whenever I am receiving data using settimeout, I need to get last object by filtering with vehicle_number (if it contains same vehicle_number, I need to get last object of that vehicle_number) and need to populate/push into table again. Here is the code I have tried.
home.component.html
<div>
<table>
<tr *ngFor="let x of groupList">
<td>{{x.vehicle_number}}</td>
<td>{{x.status}}</td>
</tr>
</table>
</div>
home.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
imageSource :any;
statusdata1: any;
vehicle_number:any;
groupList:any = [];
constructor() {}
ngOnInit() {
/* First data */
this.statusdata1 = {"vehicle_number":1,"status":"red"};
this.groupList.push(this.statusdata1);
console.log(this.groupList);
/* second data */
setTimeout (() => {
this.statusdata1 = {"vehicle_number":1,"status":"green"};
this.groupList.push(this.statusdata1);
console.log(this.groupList);
}, 5000);
/* Third data */
setTimeout (() => {
this.statusdata1 = {"vehicle_number":2,"status":"yellow"};
this.groupList.push(this.statusdata1);
console.log(this.groupList);
}, 10000);
}
}
You could write a quick function to update the value like the following
private updateGroupList(statusData: any) {
for (const key in this.groupList) {
if (this.groupList[key].vehicle_number === statusData.vehicle_number) {
this.groupList[key].status = statusData.status;
return;
}
}
this.groupList.push(statusData);
}
And you could replace all this.groupList.push() in the ngOnInit() with this.updateGroupList(this.statusdata1).
ngOnInit() {
/* First data */
this.statusdata1 = {"vehicle_number":1,"status":"red"};
this.updateGroupList(this.statusdata1);
console.log(this.groupList);
/* Second data */
setTimeout (() => {
this.statusdata1 = {"vehicle_number":1,"status":"green"};
this.updateGroupList(this.statusdata1);
console.log(this.groupList);
}, 5000);
/* Third data */
setTimeout (() => {
this.statusdata1 = {"vehicle_number":2,"status":"yellow"};
this.updateGroupList(this.statusdata1);
console.log(this.groupList);
}, 10000);
}
Working example: Stackblitz
Stackblitz GIF

'this' returns undefined in extended Classes in Javascript

I am trying to run the code below, but it is not working. I think this is a scope problem, but I'm not sure how to fix this.
import CommonController from './CommonController';
import CategoryService from './category/Service.js';
class CategoryController extends CommonController {
constructor() {
super(CategoryService);
}
}
export default new CategoryController();
// ===================CommonController==========================
export default class CommonController {
constructor(service) {
this.service = service;
}
async get () {
console.log(this); // it returns undefined
}
}
// ===================CategoryService==========================
import Category from './Category'
import dto from './dto'
class CategoryService extends CommonService {
constructor() {
super(Category, dto);
}
}
export default new CategoryService();
// ===================CommonService==========================
export default class CommonService {
constructor(model, dto) {
this.model = model;
this.dto = dto;
}
}
if a run:
import CategoryController from './CategoryController';
CategoryController.get()
the console.log in CommonController get function will print undefined
Am I doing something wrong?
The issue is that you are calling get() on the class itself, instead of calling it on an instance of the class. Try creating an instance of CategoryController, like so:
cc = new CategoryController();
Then, you should be able to call:
cc.get();
Demo in the code below (same as yours, just slightly modified to reflect my point).
// ===================CommonController==========================
class CommonController {
constructor(service) {
this.service = service;
}
async get () {
console.log(this); // it returns undefined
}
}
// ===================CommonService==========================
class CommonService {
constructor(model, dto) {
this.model = model;
this.dto = dto;
}
}
// ===================CategoryService==========================
class CategoryService extends CommonService {
constructor() {
super(Category, dto);
}
}
class CategoryController extends CommonController {
constructor() {
super(CategoryService);
}
}
cs = new CategoryController();
cs.get();

Execute method by decorator

I would like to execute a function by a decorator with the current component this after angular run DI.
An example:
If execute on decorator, I don't have translateService on this
export const TesteDecorator = (actionName): any => {
return (target?: any, propertyKey?: string): void => {
Observable.timer(5000).subscribe(() => {
target[propertyKey](); // when i execute here not have translateService on (this)
});
};
};
But if execute on constructor have the translateService .
#Component({
...
})
export class TesteComponent {
constructor(
private translateService: TranslateService
) {
Observable.timer(1000).subscribe(() => {
this.teste(); // when i execute here translateService is on the (this)
});
}
#TesteDecorator('ACTION')
teste() {
console.log(this);
}
}
Can someone help me?
The problem is that the decorator is executed on class declaration and target is not an instance of the class but it's prototype, so it will not contain any fields.
One approach to get around this would be to wrap an existing function to invoke your extra code, and call the method from the constructor:
export const TesteDecorator = (actionName): any => {
return (target?: any, propertyKey?: string): void => {
var prevFn: ()=> void = target['testeDecoratorHelper'];
target['testeDecoratorHelper'] = function() {
prevFn.call(this);
setTimeout(() => {
console.log(propertyKey);
this[propertyKey](); // when i execute here not have translateService on (this)
}, 10);
}
};
};
export class TesteComponent {
constructor(private translateService: TranslateService) {
this.testeDecoratorHelper();
setTimeout(() => {
this.teste(); // when i execute here translateService is on the (this)
}, 10);
}
testeDecoratorHelper() {
}
#TesteDecorator('ACTION')
teste() {
console.log(this);
}
#TesteDecorator('ACTION')
teste2() {
console.log(this);
}
}
The implementation above does not work with derived types, but it shoud get you started.
Edit
Since you are using Angular, instead of testeDecoratorHelper you could also use ngOnInit which has the advantage of being invoked automatically so you don't have to invoke it from the constructor. (10x to estus for this suggestions)

How to update parent's variable in child component after child has called parents function that has http request

I cannot seem to see the changed #Input in the child component after it was updated in parents http request.
This is an example:
Parent
import { ChildComp } from './child.component';
#Component({
template: <child [counter]="a" [updateCounter]="updateCounter"></child>,
directives: [ChildComp]
})
export class ParentComponent {
public a = 1;
public CallBack:Function;
constructor(private _http:Http) {}
public ngOnInit() {
this.CallBack = this.updateCounter.bind(this);
}
public updateCounter() {
this._http.get('/newcounter/').subscribe(
data => {
// update counter
this.a = JSON.parse(data['_body']);
},
error => {},
() => console.log('updated counter')
);
}
}
Child
#Component({
selector: 'child',
template: `
<button class="btn btn-default" (click)="updateCounter()"></button>
<p>counter: {{ counter }}</p>
`,
inputs: ["counter", "updateCounter"]
})
export class ChildComponent {
public counter;
public updateCounter:Function;
constructor() {}
}
So, this works if there is not http request. But once I have the request, the child view will not update the counter.
Any ideas? What am I missing?
One hack i have now is to setTimeout on child component to update the counter 500ms after the call to updateCounter
Amend the updateCounter function of your parent component like this:
public updateCounter() {
let that = this;
this._http.get('/newcounter/').subscribe(
data => {
// update counter
that.a = JSON.parse(data['_body']);
},
error => {},
() => console.log('updated counter')
);
}
Using this in the promise does not reference your class anymore. So you need to keep a reference to this in another variable and use that one instead.

Categories

Resources