I am trying to store the event data from the onRowClicked event in a Component member. So that when the user hits a button it will be deleted. However when I try accessing it from the delete callback the member variable is undefined.
export class OilTypesComponent implements OnInit {
...
selectedOil : any;
gridOptions: GridOptions = <GridOptions>{};
ngOnInit() {
this.gridOptions = {
...
onCellEditingStopped: this.cellEdited,
onRowClicked: this.rowClicked
}
}
...
rowClicked(event){
this.selectedOil = event.data;
}
delete(){
console.log(`Deleting ${this.selectedOil.manufacturer} //this.selectedOil is undefined
}
Turns out it was a scoping issue when passing in the callbacks as shown here:
Angular2 component's "this" is undefined when executing callback function
What I ended up doing for both callbacks
this.gridOptions = {
...
onCellEditingStopped: this.cellEdited.bind(this),
onRowClicked: this.rowClicked.bind(this)
}
Related
export class AppComponent {
title = 'my-app';
constructor(private notifyService : NotificationService) {}
ngOnInit() {
socket.on("laravel_database_chat:test", function(message){
//I WANT TO CALL NOTIFICATION SERVICE HERE, BUT NOT WORKING
this.notifyService.showSuccess();
});
I am trying to call notification service inside socket.io class, but not working.
Change normal function to arrow function to get access to this outside current scope.
ngOnInit() {
socket.on("laravel_database_chat:test", (message) => {
this.notifyService.showSuccess();
});
}
I need to know which is executed first in the component and execution order.
Get is called before constructor or Constructor gets called first. I am unable to put console in Get accessor.
export class AppComponent implements OnChanges {
title = 'app';
constructor() {
console.log('constructor called on App Component');
}
ngOnChanges() {
console.log(' onChanges called on App Component');
}
clicked() {
console.log('red');
}
get name(): string {
return 'sahir';
console.log('called get method');
}
}
The constructor will always be called first. You need an instance of the class in order to access a property.
Also, the console.log you put on the getter will never run since it is after a return statement.
Hi I have an issue like in subject:
My Parent component passes the value to his child component like this:
<em-event-list [sumListEvents]="sumListEvents"></em-event-list>
So when when value sumListEvents will change I want to subscribe that value to call out the function from Service. This is how my children component looks:
#Input() sumListEvents: Observable<number>;
private events: Event[] = [];
constructor(private dataService: EventListService) {
let loadSubscription = this.sumListEvents.subscribe(
value => {
this.events = this.dataService.showEvents(value)
}
)
}
But I receive error on subscribe Cannot read property 'subscribe' of undefined in the sumListEvents. Any ideas?
sumListEvents is not available at the moment you need it. You can use *ngIf to subscribe only when sumListEvents available.
<em-event-list *ngIf [sumListEvents]="sumListEvents"></em-event-list>
This will work but it might not be a best practise to pass event to the child and subscribe it in a child.
You may refer to https://scotch.io/tutorials/3-ways-to-pass-async-data-to-angular-2-child-components for other ways to pass async data to child component.
A better approach will be to use the async pipe and a setter.
<em-event-list *ngIf [sumList]="sumListEvents$ | async"></em-event-list>
#Input() set sumList(value) {
if(value) {
this.events = this.dataService.showEvents(value);
}
}
private events: Event[] = [];
constructor(private dataService: EventListService) { }
I am using Angular 1.6 and am having trouble trying to get a controller to call a function I have passed in. In my example below, I have homepage.html which is passing a function into <image-selector>. I want <image-selector> to call the passed-in function which will update the parent when the image has been changed. HomepageCtrl will then call its own function updateState() to process the data.
The problem is that HomepageCtrl fails to call updateState() because this.updateState() in onImageChange() is undefined. I suspect that the issue is caused because ImageSelectorCtrl is invoking onImageChange() so this is pointed to the ImageSelectorCtrl instead of HomepageCtrl.
I am wondering how I would fix this issue so ImageSelectorCtrl can invoke onImageChange() which will then call updateState()?
// homepage.js
import homepageHtml from './homepage.html';
class HomepageCtrl {
constructor() {
}
onImageChange(newImage) {
this.updateState({newImage: processImage(newImage)}); // console error: cannot read property of 'updateState' of undefined
}
updateState(options) {
console.log('Updating state...');
}
}
export const Homepage = {
template: homepageHtml,
controller: HomepageCtrl
};
// homepage.html
<div class="homepage">
<image-selector on-change="$ctrl.onImageChange"></image-selector>
</div>
// imageSelector.js
import imageSelectorHtml from './image-selector.html';
class ImageSelectorCtrl {
constructor() {
this.imageUrl;
}
onChange() {
this.onChange()(imageUrl);
}
}
export const ImageSelector = {
bindings: {
onChange: '&'
},
template: imageSelectorHtml,
controller: ImageSelectorCtrl
};
please try binding this to your class methods as they are being executed in a different context.
class HomepageCtrl {
constructor() {
this.onImageChange = this.onImageChange.bind(this)
this.updateState = this.updateState.bind(this)
}
onImageChange(newImage) {
this.updateState({newImage: processImage(newImage)}); // console error: cannot read property of 'updateState' of undefined
}
updateState(options) {
console.log('Updating state...');
}
}
This is a jquery interface from jquery.d.ts:
export interface IDialogEvent extends DialogEvent {
(event: Event, ui: DialogUIParams): void;
}
This is my custom interface mimicking partial functionality of the DialogOptions interface of jquery.d.ts:
export interface IDialogOptions {
open: IDialogEvent;
}
export class DialogClass implements IDialogOptions {
//Dialog options
public open: IDialogEvent;
//Class related fields
public someField: any;
public dialogEl: JQuery;
constructor() {
this.open = this.OpenHandler;
this.dialogEl = $("<div></div>").dialog(this);
//Passing "this" initializes the dialog by mapping relevant class fields
//to the dialog's "option" object, in this case the only "relevant" field is "open".
}
public OpenHandler(event: Event, ui: DialogUIParams) {
var value = this.someField; //BAD. "this" is not type BaseClass
}
public NonEventHandlerMethod() {
var value = this.someField; //GOOD. "this" is type BaseClass
}
}
var dialog = new DialogClass();
dialog.dialogEl.dialog("open");
The last line fires OpenHandler() but inside it, this is not type BaseDialog (unlike in NonEventHandlerMethod).
The reason I need an event handler function for the dialog options field and the reason why I can't simply do this:
export class DialogClass implements IDialogOptions {
...
constructor() {
this.open = () => {
//event handling logic
};
...
}
...
}
is because I need to add additional open-event handling logic in classes that extend DialogClass and there is no differentiation between this.member and super.member... there is only differentiation between this.function() and super.function():
export class LoginDialog extends DialogClass {
...
constructor() {
this.open = this.OpenHandler;
...
}
public OpenHandler(event: Event, ui: DialogUIParams) {
super.OpenHandler(); //Base handling logic
//Additional handling logic
}
...
}
I think this may be a bug because
export class DialogClass implements IDialogOptions {
...
constructor() {
this.open = () => {
var test = this.someField; //Correct context
};
...
}
...
}
and calling the method directly:
var dialog = new DialogClass();
dialog.OpenHandler(); //Correct context when called directly
//Note: I haven't actually tested this persay but this function is no different
//than any other functionso a direct call should certainly not be problem.
TypeScript follows the usual JavaScript scoping conventions, so this will be dependent on context. If you have a method on a class that fires based on an event, this will be the event target. When you directly call a method on a class, this will be the class.
If you want to get around this, you can take advantage of how JavaScript walks up the scope chain by giving this an alias...
Here is one way to do that:
this.open = () => { this.OpenHandler(this); };
The arrow-function syntax creates and alias name _this in the JavaScript.
public OpenHandler(context: DialogClass, event: Event, ui: DialogUIParams) {
var value = context.someField;
}
We accept the cleverly aliased version of this as a parameter and context.someField should have the value we are after.