RandomEli
RandomEli

Reputation: 1557

ion-toggle ng-change does not trigger properly with controller + service structure

I've created a list of toggles to select bluetooth devices and connect it, and I've created a controller.js and service.js for them. However, the ng-changeonly triggers when ion-toggles first loaded in view, and were not triggering for changes afterwards.

Here is my snippet of setting.html:

<ion-toggle ng-repeat="item in devicesList"
            ng-model="item.checked"
            ng-change="connectDevice(devicesList)">
     {{ item.address }}
</ion-toggle>

and here is my settingController.js:

(function () {
    'use strict';

    angular.module('i18n.setting').controller('SettingController', SettingController);
    SettingController.$inject = ['$scope','SettingService'];

    function SettingController($scope, SettingService) {
        $scope.devicesList = [];
        $scope.scanDevices = SettingService.scanDevices($scope.devicesList);
        $scope.connectDevice = SettingService.connectDevice($scope.devicesList);
    };

})();

and here is my settingService.js:

(function(){
    'use strict';

    angular.module('i18n.setting').service('SettingService', SettingService);

    SettingService.$inject = [];
    function SettingService(){
        var self = this;

        this.scanDevices = function(devicesCollection) {
            window.bluetoothSerial.discoverUnpaired(function(devices) {
                console.log("in discoverUnpaired callback, setting page");
                devices.forEach(function(device) {
                    console.log(device.name);
                    device.checked = false;
                    devicesCollection.push(device);
                });

            }, function(error) {
                console.log("in discoverUnpaired error function");
                console.log(error);
            });
        };

        this.connectDevice = function(devicesCollection) {
            console.log(devicesCollection);
            console.log("In connectDevice");
            for (var i =0; i<devicesCollection.length; i++)
            {
                console.log(devicesCollection[i].id + " " + devicesCollection[i].checked);
                if (devicesCollection[i].checked == true)
                {
                    console.log(devicesCollection[i].name);
                    window.bluetoothSerial.connect(devicesCollection[i].address,
                        function(data) {console.log("This device is"+macaddress); console.log(data);},
                        function(error) {console.log(error);});
                }
            }
        };
    }
})();

And if I define this function directly in settingController.js, it's working properly and can detect every change of the toggle. Also, I noticed that my scanDevices function will be triggered even if I don't click the button. I don't know why is it. Will there be someone tell me what cause is it? Any help, thanks

Upvotes: 0

Views: 297

Answers (1)

georgeawg
georgeawg

Reputation: 48968

The controller should put the service functions on the scope; not invocations of the service functions.

(function () {
    'use strict';

    angular.module('i18n.setting').controller('SettingController', SettingController);
    SettingController.$inject = ['$scope','SettingService'];

    function SettingController($scope, SettingService) {
        $scope.devicesList = [];
        //$scope.scanDevices = SettingService.scanDevices($scope.devicesList);
        $scope.scanDevices = SettingService.scanDevices;
        //$scope.connectDevice = SettingService.connectDevice($scope.devicesList);
        $scope.connectDevice = SettingService.connectDevice;
    };

})();

Since the scanDevices function has no return statement, scanDevices($scope.deviceList) returns undefined. Thus $scope.scanDevices was getting set to undefined.


Update

Can you also explain why scanDevices get invoked before I press the Scan button?

Which was bind to:

<button class="button button-stable"
        ng-click="scanDevices(devicesList)">Scan Devices
</button>

By binding an invocation of the function to the scope variable instead of the function itself:

//ERRONEOUS
$scope.scanDevices = SettingService.scanDevices($scope.devicesList);

//CORRECT
$scope.scanDevices = SettingService.scanDevices;

The expression SettingService.scanDevices($scope.devicesList) invokes the function before the button is clicked. And assigns undefined to the $scope.scanDevices variable.

Upvotes: 1

Related Questions