AngularJS scope variables - $ not updated in factory

For making video calls with webRTC I am using ONSIP.JS api. In my angular app, I have created a VideoSupport factory.

When the function is called through user action, the $ scope variables are updated in the DOM. However, when the function runs while listening to my RTC session object, the DOM doesn't change anything.

When I just made a prototype in my controller instead of a factory, I could solve the problem by calling $ scope. $ apply in setStatus function. But this is not possible in a factory.

So an example: I run the sendInvite function -> the invite button is disabled .. it works.

When the other party accepts the call, the "accepted" function internally is called setSession. Every variable that is changed by this last action is not reflected in my DOM. All buttons remain disabled.

Controller:

function SupportController($scope, $stateParams, navigationService, $css, VideoSupportFactory) {

    $scope.VideoSupport = VideoSupportFactory;
    $scope.VideoSupport.createUA();

}

      

Factory:

function VideoSupportFactory($modal) {
    var remoteMedias = angular.element( document.querySelector( '#remote-media' ) );
    var remoteMedia = remoteMedias[0];

    return {
        disableTerminate: true,
        disableAccept: true,
        disableInvite: false,
        _volume: 50,
        mute:false,

        createUA: function (credentials) {
            if (credentials !== null && typeof credentials === 'object') {
                this.ua = new SIP.UA(credentials);
                this.ua.on('invite', this.handleInvite.bind(this));
            } else {
                this.ua = new SIP.UA();
            }
        },

        handleInvite: function (session) {
            if (this.session) {
                session.reject();
                return;
            }

            this.setSession(session);
            this.disableAccept = false;
        },

        acceptSession: function () {
            if (!this.session) {
                return;
            }

            this.disableAccept = true;
            this.session.accept(remoteMedia);
        },

        sendInvite: function () {
            var session = this.ua.invite('test123@behousing.onsip.com', remoteMedia);
            this.setSession(session);
            this.disableInvite = true;
        },

        setSession: function (session) {
            session.on('progress', function () {
                progressSound.play();
                this.setStatus('progress', true);
            }.bind(this));

            session.on('accepted', function () {
                console.log(session);
                progressSound.pause();
                this.setStatus('accepted', true);
            }.bind(this));

            session.on('failed', function () {
                progressSound.pause();
                this.openModal('sm', 'Oops!', 'The connection could not be established...');
                this.setStatus('failed', false);
                delete this.session;
            }.bind(this));

            session.on('bye', function () {
                this.setStatus('bye', false);
                delete this.session;
            }.bind(this));

            session.on('refer', session.followRefer(function (req, newSession) {
                this.setStatus('refer', true);
                this.setSession(newSession);
            }.bind(this)));

            this.session = session;
        },

        setStatus: function (status, disable) {
            this.mainClass = status;
            this.disableInvite = disable;
            this.disableTerminate = !disable;
            //$scope.$apply();
        },

        terminateSession: function () {
            if (!this.session) {
                return;
            }

            progressSound.pause();
            this.setStatus('bye', false);
            this.session.terminate();
        },

        sendDTMF: function (tone) {
            if (this.session) {
                this.session.dtmf(tone);
            }
        },

        volume: function (newVolume) {
            if (arguments.length) {
                console.log('Setting volume:', newVolume, parseInt(newVolume, 10));
                remoteMedia.volume = (parseInt(newVolume, 10) || 0) / 100;
                return (this._volume = newVolume);
            } else {
                return this._volume;
            }
            ;
        },

        toggleMute: function () {
            if (!this.session) {
                return;
            }

            if (this.mute) {
                this.session.unmute();
                this.mute = false;
            } else {
                this.session.mute();
                this.mute = true;
            }

        },

        openModal: function (size, title, text) {
            var modalInstance = $modal.open({
                animation: true,
                templateUrl: 'SupportModalContent.html',
                controller: 'SupportModalInstanceCtrl',
                size: size,
                resolve: {
                    title: function () {
                        return title;
                    },
                    text: function () {
                        return text;
                    }
                }
            });
        }

    }
}

      

+3


source to share


1 answer


Not sure if this is the correct way to do it, but you can try the observer pattern, I just put one parameter below:

    setStatus: function (status, disable) {
        this.mainClass = status;
        this.disableInvite = disable;
        this.disableTerminate = !disable;
        //$scope.$apply();
        this.notifyObservers();
    },
    observers: [],
    notifyObservers: function(){
        this.observers.forEach(function(notifyFn){
            notifyFn();
        });
    },
    addObserver: function(notifyFn){
        this.observers.push(notifyFn);
    }


    ...
    // in controller

    $scope.VideoSupport = VideoSupportFactory;
    $scope.VideoSupport.createUA();
    $scope.VideoSupport.addObserver(update);
    function update(){
        $scope.$apply();
    }

      



of course the simplest hack might be, just by observing some parameter:

$scope.$watch('VideoSupport.mainClass', function() {
    console.log('status changed');
});

      

0


source







All Articles