Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I am trying to avoid using $scope in my controller function, instead opting to use

var viewModel = this;

with "controller as" viewModel syntax. My problem is that I need to use ng-change to call a function in my controller but while I am able to access data from a service, I am unable to call functions.

//Controller
(function () {
'use strict';

angular
    .module('app')
    .controller('GeneralSettingsController', GeneralSettingsController);

GeneralSettingsController.$inject = ['SimulationService'];
function GeneralSettingsController(SimulationService) {
    var viewModel = this;
    viewModel.SimulationService = SimulationService;
    viewModel.setSimulationPeriod = setSimulationPeriod;

    function setSimulationPeriod() {
        console.log("Entered local setSimulationPeriod");
        viewModel.SimulationService.setSimulationPeriod();
    }
}
})();

The controller is being instantiated in a directive that defines the controller and controllerAs: 'viewModel'

My html looks like this:

<div class="col-xs-2">
    <input type="text" class="form-control" id="startyear" name="startyear" placeholder="start year"
                       autocomplete="off" value="2017" maxlength="4"
                       ng-model="viewModel.SimulationService.data.simulationPeriodStart" ng-change="viewModel.setSimulationPeriod">
</div>

I was able to call things fine when I used $scope instead of referencing the controller however I feel this is not ideal. I was hoping there is a way of calling a function with ng-change that still uses viewModel.

share|improve this question

angular expressions

You're not calling the function. Instead try:

 <input ng-change="viewModel.setSimulationPeriod()">

Note the () at the end of your function. Ng-change, like most other angular directives use expressions, meaning they're actually trying to execute a subset of JavaScript. In this case when you just passed a reference to your vm's function, it simply evaluated it rather than executing it.

order of assignment

Also, you've defined the viewModel function before you've defined the function you're setting it to. Move the function declaration above the part of your code where you assign it to your viewModel.

instead of this

viewModel.setSimulationPeriod = setSimulationPeriod;

function setSimulationPeriod() {
    console.log("Entered local setSimulationPeriod");
    viewModel.SimulationService.setSimulationPeriod();
}

reorder it like this

function setSimulationPeriod() {
    console.log("Entered local setSimulationPeriod");
    viewModel.SimulationService.setSimulationPeriod();
}

viewModel.setSimulationPeriod = setSimulationPeriod;
share|improve this answer
    
I have made your suggested change, unfortunately this still does not call the function. – Jonathan Van Buren 15 hours ago
    
You've also set the viewModel's function to an undefined value before defining your function. Move the function declaration up in your file, then set it to your viewModel – jusopi 15 hours ago
    
I moved the function above viewModel.setSimulationPeriod = setSimulationPeriod; however this still doesn't work. – Jonathan Van Buren 15 hours ago
    
Set a read only value on your viewModel and then bind to it. Let's make sure you are actually getting your viewModel wired up. – jusopi 15 hours ago
    
FYI, functions in JS are hoisted so the declaration order shouldn't matter – Phil 15 hours ago

jusopi was right. My controller was not wired up correctly. The problem was that I had another controller active at a higher scope which was also set to controllerAs: viewModel. This caused me to reference the wrong controller where the function did not exist. Once I gave this controller a unique name everything went smoothly which is why it worked for $scope.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.