MattDionis MattDionis - 4 months ago 7
AngularJS Question

Reference directive attribute with vm rather than $scope

I have a custom directive that looks like this:

<my-queue id="report.id" version="report.version"></my-queue>


In my directive definition object I reference my controller and scope like so:

controller: 'QueueController',
controllerAs: 'myQueue',
scope: {
id: '=',
version: '='
}


In my controller I set
var vm = this
so I can refer to scope variables as
vm.variable
. However this does not work for
id
and
version
. I've found that I need to inject
$scope
and reference these properties as
$scope.id
and
$scope.version
.
Is there a way to set this up so that I can avoid injecting
$scope
and stay consistent with the rest of my controller by referencing
vm.id
and
vm.version
?

Answer

The controllerAs property on your directive config object will be what you use to refer to your controller instance, so if you want to use vm in your template, you will need to set the controllerAs property to vm. Also, by setting the bindToController property to true you can bind directly to the view model instead of $scope:

function myQueue() {
    return {
        restrict: 'E',
        template: ... ,
        controller: myQueueCtrl,
        controllerAs: 'vm',
        scope: {
            id: '=',
            version: '='
        },
        bindToController: true
    }
}

With your current directive configuration, your controllerAs reference will be under myQueue, not vm, meaning any properties you create on your vm (e.g. vm.id) in your controller will be on myQueue in your template (e.g. myQueue.id).

By adding bindToController we do not need to inject $scope in the directive's controller:

function QueueController() {
    var vm = this;
}

Then you can refer to your vars in the directive template as

{{vm.id}}
{{vm.version}}

There is a plunker here of your directive with bindToController set to true, and controllerAs set to vm.

Comments