如何从一个控制器设置一个服务的值,并使用该服务更新另一个控制器的值

How to set value of one service from one controller, and update value of another controller with this service

本文关键字:控制器 服务 一个 另一个 更新 设置      更新时间:2023-09-26

我是这个领域的新手,想写一个app,现在遇到了一些问题。这是我的代码的一个简单版本,我想要的是API只显示signUp第一。在我按下signUpsubmit后,显示的按钮应该只有signout

我认为我的方法是不对的,因为当我在服务中更改了值后,另一个控制器无法更新它的值。你能告诉我吗?如果可能请使用this.logged,谢谢!

过程不必与我的标题相同。如果它能实现我的功能就行了。

https://plnkr.co/edit/1ptaVzmD7EwPZ6dU23gR?p =

预览
(function(){
    angular.module('myApp',['myApp.dashboard','myApp.value','myApp.signUp']);
})();
(function(){
    angular.module('myApp.dashboard',[]);
})();
(function(){
    angular.module('myApp.value',[]);
})();
(function(){
    angular.module('myApp.signUp',[]);
})();
(function(){
    'use strict';
    angular.module('myApp.dashboard').controller('mainControl',mainControl);
    mainControl.$inject = ['whichToShow'];
    function mainControl(whichToShow){
        this.logged=whichToShow.getVar();
        alert(this.logged);
    }
})();

(function(){
    'use strict';
    angular.module('myApp.value').factory('whichToShow',function(){
        alert("running2");
        var logged=false;
        return {
            getVar: function(){
                return logged;
            },
            setVar: function(value){
                logged=value;
            }
        };
    });
})();
(function(){
    'use strict';
    angular.module('myApp.signUp').controller('signUpControl',signUpControl);
    signUpControl.$inject = ['whichToShow'];
    function signUpControl(whichToShow){
        alert("haha");
        this.logIn=function(){
            whichToShow.setVar(true);
            alert("running set!");
        };
    };
})();

部分html:

<body ng-controller="mainControl as mc">
    <div>
        <div ng-hide="mc.logged">
                <button type="button" class="btn" data-toggle="modal" data-target=".signUp">Sign Up</button>
            </div>
            <div ng-show="mc.logged">
                <button>Sign Out</button>
            </div>
        </div>

        <div class="signUp modal fade" id="signUp" ng-controller='signUpControl as sc'>
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h4 class="modal-title">sigh up</h4>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">&times;</button>
                    </div>
                    <div class="modal-body">
                        <form id="signUpForm" name="signUpForm" ng-submit="sc.logIn()">
                            <label for="email">
                                <span>email:</span>
                                <input type="email" name="email">
                            </label>
                            <button class="submit" id="signUpSubmit" type="submit" value="signUp">submit</button>
                        </form>                 
                    </div>
                    <div class="modal-footer">
                    </div>
                </div>
            </div>
        </div>
    </body>

基本上你是在用户点击提交后在工厂对象中设置值,但这并没有反映在UI中,因为你没有更新范围对象this.logged,所以要告诉主控制器从注册控制器改变this.logged $scope的值我们可以使用$emit$broadcast

除了$watch的方法,你甚至可以使用$broadcast来实现这一点。

演示工作

在你的JS文件controllers中添加下面的代码

signUpControl

(function(){
    'use strict';
    angular.module('myApp.signUp').controller('signUpControl',signUpControl);
    signUpControl.$inject = ['whichToShow','$rootScope'];
    function signUpControl(whichToShow,$rootScope){
        alert("haha");
        this.logIn=function(){
            whichToShow.setVar(true);
            $rootScope.$broadcast('login');//broadcasting that user has logged in
            //alert("running set!");
        };
    };
})

mainControl

(function(){
    'use strict';
    angular.module('myApp.dashboard').controller('mainControl',mainControl);
    mainControl.$inject = ['whichToShow','$rootScope'];
    function mainControl(whichToShow,$rootScope){
        var mc = this;
        mc.main ={};
        mc.main.logged=whichToShow.getVar();
        alert(mc.main.logged);
       // below code will listen to the broadcast and do the necessary process..
        $rootScope.$on('login',function(event,args){
                mc.main.logged=whichToShow.getVar();
        });
    }
})

您需要监视来自服务的日志值的变化。

这就是你所需要做的。

(function() {
  angular.module('myApp', ['myApp.dashboard', 'myApp.value', 'myApp.signUp']);
})();
(function() {
  angular.module('myApp.dashboard', []);
})();
(function() {
  angular.module('myApp.value', []);
})();
(function() {
  angular.module('myApp.signUp', []);
})();
(function() {
  'use strict';
  angular.module('myApp.dashboard').controller('mainControl', mainControl);
  mainControl.$inject = ['$scope', 'whichToShow'];
  function mainControl($scope, whichToShow) {
    $scope.$watch(() => whichToShow.getVar(), (newValue, oldValue) => this.logged = newValue)
  }
})();
(function() {
  'use strict';
  angular.module('myApp.value').factory('whichToShow', function() {
    var logged = false;
    var service = {};
    return {
      getVar: function() {
        return logged;
      },
      setVar: function(value) {
        logged = value;
      }
    }
  });
})();
(function() {
  'use strict';
  angular.module('myApp.signUp').controller('signUpControl', signUpControl);
  signUpControl.$inject = ['whichToShow'];
  function signUpControl(whichToShow) {
    this.logIn = function() {
      whichToShow.setVar(true);
    };
  };
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="myApp">
  <div ng-controller="mainControl as mc">
    <div>
      <div ng-hide="mc.logged">
        <button type="button" class="btn" data-toggle="modal" data-target=".signUp">Sign Up</button>
      </div>
      <div ng-show="mc.logged">
        <button>Sign Out</button>
      </div>
    </div>
    <div class="signUp modal fade" id="signUp" ng-controller='signUpControl as sc'>
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h4 class="modal-title">sigh up</h4>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">&times;</button>
          </div>
          <div class="modal-body">
            <form id="signUpForm" name="signUpForm" ng-submit="sc.logIn()">
              <label for="email">
                <span>email:</span>
                <input type="email" name="email">
              </label>
              <button class="submit" id="signUpSubmit" type="submit" value="signUp">submit</button>
            </form>
          </div>
          <div class="modal-footer">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Codepen的工作解决方案

您仍然试图在这里设置原语的值,而不是对象属性。在JavaScript中,传递原语的是byValue,而不是byReference,所以whichToShow.getVar();返回的是truefalse,而不是返回对logged的引用。因此,除非再次调用.getVar()以获得新值,否则不会看到logged的变化。这就是为什么到目前为止您看到的大多数答案都有某种形式的$watch, $broadcast或类似的mc,以提醒您的CC_20应该再次询问logged变量的当前值。

如果你想避免使用$watch,你应该使用对象而不是原语。通过使用一个对象,你可以通过reference 传递对象,这将允许angular看到任何有引用集的属性的变化。

在工厂中,返回一个对象:

(function() {
  'use strict';
  angular.module('myApp.value').factory('whichToShow', function() {
    alert("running2");
    var status = {
      logged: false
    };
    var logged = false;
    return {
      getVar: function() {
        return status;
      },
      setVar: function(value) {
        status.logged = value;
      }
    };
  });
})();

在mainControl中,使用对该对象的引用:

(function() {
  'use strict';
  angular.module('myApp.value').factory('whichToShow', function() {
    alert("running2");
    var status = {
      logged: false
    };
    return {
      getVar: function() {
        return status;
      },
      setVar: function(value) {
        status.logged = value;
      }
    };
  });
})();
最后,使用HTML中的object属性:
<div ng-hide="mc.status.logged">
...
<div ng-show="mc.status.logged">
...

https://plnkr.co/edit/Pindt2LYxDxyk8C5Axp1?p =

预览

我甚至可以更进一步,直接通过服务返回对象,并跳过getVarsetVar函数。

你可以把一些变量全局或在你的根控制器,让说isLoggedIn

现在有一个服务,你可以在signingIn

上设置这个变量

,并像这样使用它{

}