2015-08-15 3 views
1

У меня в настоящее время проблема, когда при вызове функции в службе, которая меняет собственную внутреннюю переменную, она не сохраняется, если я не изменю ее с контроллера. Когда я вывожу переменную на консоль сразу после ее изменения, она появляется с правильным значением. Однако, когда я вызываю функцию в контроллере, который печатает объект для консоли, он показывает исходное значение.AngularJS: изменения служебной переменной не применяются

Переменная Im, имеющая проблемы с «isSignedIn», которая всегда показывает false (подтверждена методом $ scope.verify в контроллере входа в систему) даже после строки «console.log (« Signin: '+ isSignedIn »; показывает правду.

Спасибо заранее за любое руководство!

служба Skype

angular.module('Skype', ['ng']) 
    .service('skypeClient', function() { 
     //Service Properties 
     var client = new Skype.Web.Model.Application; 
     this.errors = []; 
     this.errorCount = -1; 
     var isSignedIn = false; 
     var state = 'SignedOut'; 

     var init = function() { 
      client.signInManager.state.when('SignedIn', function() { 
       isSignedIn = true; 
       console.log('Signin:' + isSignedIn); // This outputs the correct value 
      }); 
      property = client.signInManager.state; 
      property.changed(function (status) { 
      state = status; 
      console.log("New State"+status) }); 
      } 

     //Signin Function 
     var signIn = function (username,password) { 
      client.signInManager.signIn({ 
       username: username, 
       password: password 
      }).then(function() { 
       isSignedIn = true; 
       this.errorCount++; 
       console.log(this.errorCount); 
      }); 
     } 

     //SignOut Function 
     var signOut = function() { 
     client.signInManager.signOut() 
     .then(function() { 
      this.isSignedIn = false; 
     }, function (error) { 
      this.erros.push(error); 
      this.errorCount++; 
     }); 
     } 

     return { 
      signIn: signIn, 
      signOut: signOut, 
      init: init, 
      state: state, 
      isSignedIn: isSignedIn 
     }; 

}); 

Контроллер Войти

'use strict'; 
angular.module('login', ['ngRoute', 'classy', 'Metio.Skype']) 
.config(['$routeProvider', function ($routeProvider) { 
    $routeProvider.when('/login', { 
     templateUrl: 'app/views/login.html', 
     controller: 'loginCntrl' 
    }); 
}]).controller('loginCntrl', function ($scope,skypeClient) { 

    skypeClient.init(); 

    $scope.skypeClient = skypeClient; 
    console.log('LoginCntrl Loaded'); 

    $scope.signIn = function() { 
     skypeClient.signIn($scope.user, $scope.password); 
    } 
    $scope.signOut = function() { 
     skypeClient.signOut(); 
    } 
    $scope.verify = function() { 
     console.log(skypeClient); 
    } 
}); 

[EDIT] Модифицированный код в соответствии с pdenes рекомендации (комментарии), тот же вопрос, но уборщик

завод Skype

.factory('skypeClient', function() { 
     //Service Properties 
     var client = new Skype.Web.Model.Application; 
     var state = 'SignedOut'; 
     //Initialize Listeners 
     var init = function() { 
      client.signInManager.state.when('SignedIn', function() { 
       console.log('Signin:' + state); // This outputs the correct value 
      }); 
      property = client.signInManager.state; 
      property.changed(function (status) { 
       state = status; 
       console.log("New State" + state); 
      }); 
      console.log('init'); 
      } 
     //Signin Function 
     var signIn = function (username, password) { 
      client.signInManager.signIn({ 
       username: username, 
       password: password 
      }).then(function() {console.log('LoggedIn');}); 
     } 
     init(); 
     return { 
      signIn: signIn, 
      state: function(){return state} 
     } 
    }); 

Контроллер Войти

.controller('loginCntrl', function ($scope,skypeClient) { 
    $scope.skypeClient = skypeClient; 
    $scope.signIn = function() { 
     skypeClient.signIn($scope.user, $scope.password); 
    } 
    $scope.verify = function() { 
     console.log(skypeClient); 
     console.log($scope.skypeClient); 
    } 
}); 

DOM Markup

<input type="checkbox">Keep Me Signed In (Currently Signedin: {{skypeClient.state()}}) 

Console Output и DOM Изменения

Когда я попал в функцию signin, консоль регистрирует «New State SigningIn», а dom изменяет на «Signedin: SigningIn», но когда я получаю следующее событие, я запускаю консольные журналы «New State SignedIn», но DOM все еще отражает старое значение «В настоящее время Signedin: SigningIn», поэтому привязка появляется только для обновления в первый раз, но не в последующие моменты времени.

ответ

7

Значение в объекте, который вы возвращаете как услуга, не совпадает с переменной isSignedIn, которую вы определили ранее. Итак:

... 
var isSignedIn = false; 
... 
return { 
    isSignedIn: isSignedIn 
    //   ^this is false when the object is created 
    //   and will remain false, no matter how you 
    //   change the value of the above variable later 
}; 

Выставить значение isSignedIn в вашем закрытии от службы, вы должны были бы функцию, что-то вроде:

... 
return { 
    ... 
    isSignedIn: function() { 
    return isSignedIn; // <- this refers to the above variable itself 
    } 
}; 

EDIT: Последующие для обновленного кода вопрос ...

Так что, по-видимому, значение обновляется должным образом внутренне, но привязка {{skypeClient.state()}} по-прежнему не обновляется (только когда какое-то другое действие каким-то образом «заставляет» его). Вероятно, это происходит потому, что значение обновляется чем-то вне цикла Angular's digest, поэтому нет ничего, что могло бы заставить Angular обновить вещи в нужный момент.

Глядя на код, state присваивается новое значение внутри обратного вызова для property.changed (кстати, property должен правильно быть объявлен с var!). Попробуйте обернуть эту строку в $apply(), чтобы сделать Угловое обновление привязок!

+0

Спасибо за невероятно быстрый ответ! Вопрос с двумя частями, когда я пытаюсь связать, используя {{skypeClient.isSignedIn()}}, привязка, похоже, не обновляется при изменении значения (мне нужно добавить часы?). Вторая часть - это возможность вместо того, чтобы делать обратный блок в службе, просто используя «this.isSignedIn» в сервисе и получая его непосредственно от контроллера? Я уже пробовал этот второй метод, но столкнулся с той же проблемой. – strspl

+0

Это может помочь заметить, что, если я вызываю метод $ scope.verify, который печатает объект службы на консоли, значения обновляются. Спасибо. – strspl

+0

. Добро пожаловать! :) Первый: привязка {{skypeClient.isSignedIn()}} отлично подходит для меня, вам не нужны часы ... Можете ли вы отправить какой-то код, чтобы узнать, что вы пытаетесь сделать? Во-вторых: вы правы, я только что заметил, что вы используете службу, а не фабрику, поэтому вместо возврата объекта вам нужно заполнить «this» (ваша функция является конструктором). – pdenes

0

На месте, где вы вызываете служебное (заводское) значение, возвращаемое функцией, добавьте $ watch. Это изменит значение, если оно изменится в службе.

$scope.$watch(function() { return ModalService.getInfo(); }, function(){ 
    $scope.info = ModalService.getInfo(); 
}); 

See solution

Смежные вопросы