firebolt_ash
firebolt_ash

Reputation: 1324

Angularjs $scope and this functions

I am working on a small application in angularjs :-

I am working on deleting a contact. Everything works fine but the this.openModal() throws an error as undefined even though it is defined in the same JS.

Have some confusions on how to use this and $scope together. Can anyone help ?

$scope.deleteContact = function ()
{
    var delNo = $scope.contactNumber;
    var delName = $scope.contactName;

    var person = {};
    person['phone'] = delNo;

    ...
    ...
    $timeout(function(){
        delete $scope.contacts[person['phone']];
        });

    $scope.activeChats={};
    $scope.showContactName = false;
    this.openModal();

    console.log("Delete success");

}

EDIT:

this.openModal is a function I have defined as follows

this.openModal = function (input) {
    this.modalOpen = !this.modalOpen;
    // RESET
    this.showNewMessage = false;
    this.showEditGroup = false;
    this.showAddContact = false;
    this.showPersonSettings = false;
    this.showUserProfile = false;

    if (input == "newmessage"){
        this.showNewMessage = true;
    } else if (input == "showEditGroup"){
        this.showEditGroup = true;
    } else if (input == "newcontact"){
        this.showAddContact = true;
    } else if (input == "userprofile"){
        this.showUserProfile = true;
    } else if (input == "usersettings"){
        this.showPersonSettings = true;
    }
}

Upvotes: 1

Views: 189

Answers (2)

Robert Koritnik
Robert Koritnik

Reputation: 104999

It's not completely clear what you're doing but I suppose you're having some context issues executing async functions. Try assigning $scope to a local variable closing it over in your function block and use the variable in asnyc functions' blocks.

$scope.deleteContact = function ()
{
    var person = {
        phone: $scope.contactNumber
    };

    ...

    // save scope reference to local variable
    var scope = $scope;

    $timeout(function(){
        // use saved scope
        delete scope.contacts[person['phone']];
    });

    $scope.activeChats={};
    $scope.showContactName = false;
    this.openModal();

    console.log("Delete success");
}

There's also another way that somewhat does something similar in but inside angular's code. And that's angular.bind. Use it in your $timeout. The similarity is that you provide the function's context in the time of execution, so this is what you provide. In the following case I'm providing $scope to be the execution context of the async function this referring to it using this:

$timeout(angular.bind($scope, function(){
    // context (this) is actually $scope
    delete this.contacts[person['phone']];
}));

Upvotes: 1

Callum Linington
Callum Linington

Reputation: 14417

You use either $scope or this in two scenarios. The first scenario where you use the binding:

ng-controller="MyCtrl"

Or in the route:

when('/color', { controller : 'MyCtrl' });

Here, angular js expects you include the $scope service in your controllers and attach bindable properties to that:

angular.module('myModule')
    .controller('MyCtrl', ['$scope', myCtrl]);

function myCtrl($scope) {
    $scope.title = "Hello";
}

In the second scenario, you define a controllerAs and this is where angular will expect to see the bindable properties on the controller object, controller as a class. I prefer this method because it looks cleaner.

ng-controller="MyCtrl as vm"

Or in the route:

when('/color', { controller : 'MyCtrl', controllerAs: 'vm' });

The controller:

angular.module('myModule')
    .controller('MyCtrl', [myCtrl]);

function myCtrl() {
    this.title = "Hello";

    // or to make sure that you don't get JS contexts mixed up
    var vm = this;

    vm.title = "Hello";

    vm.openModal = function () {
        this;// this refers to the current function scope

        vm.title = "Modal Opened"; // this refers to the controller scope
        // scope as in the JS function context.
    }
}

In the second scenario, the binded page will look like this:

<h3>{{vm.title}}</h3>

Where you use the 'controllerAs' string as the object you use to access the properties.

So to answer the question: Have some confusions on how to use this and $scope together

You generally would use one or the other. In the second scenario you would only inject the $scope if you needed to $watch a property, or use some other special scope function.

Upvotes: 1

Related Questions