简体   繁体   中英

AngularJS - $scope variables not updated in factory

For making videocalls with webRTC i'm using the ONSIP.JS api. In my angular app i created a VideoSupport factory.

When a function gets called through a user action, the $scope vars get updated in the DOM. However, when firing a function by listening on my RTC session object, the DOM is not changing anything.

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

So example: I fire the sendInvite function -> the invite button gets disabled.. this works.

When the other side accepts the call,the "accepted" function inside setSession gets called. Every variable that gets changed by this last action does not get reflected in my DOM. All buttons stay 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;
                    }
                }
            });
        }

    }
}

not sure if it is the right way to do it, but you can try observer pattern, I have just put one varient 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, simplest hack might be, just watching some paramter:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM