1

I am using "@angular/cli": "1.0.2" and angular version 4.

For some reason I had to use jquery based plugin for select area because I couldn't found equivalent plugin in angular.

This is how my component looks like

declare var $ : any;
//adding only necessary code
export class SelectComponent implements OnInit {

    constructor(private _ngZone: NgZone) {}

    public rowData: any = [];

    ngOnInit() {
        $('img#example').selectAreas({
            minSize: [10, 10],
            onChanged: this.debugQtyAreas,
            width: 500,
            areas: [{
                x: 10,
                y: 20,
                width: 60,
                height: 100,
            }]
        });
    }
    debugQtyAreas(event, id, areas) {
        this.rowData = areas.map(function(obj) {
            return {
                left: obj.x,
                top: obj.y,
                id: obj.id
            };
        });
    };
}

Some how this way my jquery thing is working I am able to select areas on a Image.

But the value I am pushing / assigning to array rowData are not updating in the view

I tried searching on internet and found this solution working for everyone but not for me

this._ngZone.run(() => {
      //running code inside this 
})

But I am getting error here as

Cannot read property 'run' of undefined

Same thing happening with rowData, when I tried to push data instead of assigning it from map like following

for(var i = 0; i < areas.length; i++){
    this.rowData.push({
        left: areas[i].x,
        top: areas[i].y,
        id: obj.id
    });
}

It says Cannot read property 'push' of undefined

3
  • Have you imported NgZone? Commented Jul 4, 2017 at 13:40
  • import { NgZone } from '@angular/core'; this ? Yes did. Commented Jul 4, 2017 at 13:41
  • Show the full code. I believe I know why. Commented Jul 4, 2017 at 13:42

2 Answers 2

2

You need to use bind when you pass a function by reference if you want to persist the this reference.

onChanged: this.debugQtyAreas.bind(this)

When you're writting inline functions with TypeScript don't use the function prefix. If you use the => notation the this reference will persist by default.

    this.rowData = areas.map((obj) => {
        return {
            left: obj.x,
            top: obj.y,
            id: obj.id
        };
    });    
Sign up to request clarification or add additional context in comments.

4 Comments

Damn this scope issue. helpful. Thanks.
can you tell me why my auto-reload stopped working after injecting jquery. Before it was working.
@Rakeschand try injecting ChangeDetectorRef and calling detectChanges() after you've changed something from a jQuery callback. You might have to also call that method from inside the ngZone.run. I think you had part of the solution. The ngZone.run is misleading as it just lets you run code when the zone is updated.
Okay Thanks. I'll try.
1

this becomes reserved inside jQuery functions and is not referenced to the global scope as it usually is.

I always add this lines at the top of my function:

let scope = this;

And then use scope instead of this`, e.g.

scope._ngZone.run(() => {
  //running code inside this 
})

...

for(var i = 0; i < areas.length; i++){
    scope.rowData.push({
        left: areas[i].x,
        top: areas[i].y,
        id: obj.id
    });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.