NG-包括使控制器块重新呈现 [英] ng-include causes the controller block to re render

查看:102
本文介绍了NG-包括使控制器块重新呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用NG-开关,NG-包括以下。问题是NG-init和整个控制器模块得到重新呈现在任何NG-包括改变。

在login_form.html,当用户登录时,我设置了isLoggedIn = TRUE,在LoginCtrl。然而,这将导致下面的完整的HTML,这会导致纳克-INIT再次重新呈现。

我如何避免这种循环?

 < D​​IV NG控制器=LoginCtrlNG-的init =isLoggedIn =假级=span4右拉式>
        <格上=isLoggedIn&GT NG-开关;
          < D​​IV NG-开关时=false的NG-包括SRC ='login_form.html'>< / DIV>
          < D​​IV NG-开关时=真正的NG-包括SRC ='profile_links.html'>< / DIV>
        < / DIV>
      < / DIV>

以下是HTML的登录表单 -

 <窗​​体类=形式的内联>
  <输入类型=文本占位符=电子邮件NG-模式=USEREMAIL级=输入小/>
  <输入类型=密码占位符=密码NG模型=的userPassword级=输入小/>
  <按钮式=提交NG点击=登录(USEREMAIL,userPassword的)级=BTN>登录< /按钮>
< /表及GT;

下面是控制器 -

  angularApp.controller('LoginCtrl',函数($范围的currentUser){  $ scope.loginStatus =功能(){
    返回currentUser.isLoggedIn();
  };/ * $范围。在$('登陆',函数(事件参数){
    $ scope.userName = args.name;
  });  $范围。在$('注销',函数(事件参数){
    $ scope.isLoggedIn = FALSE;
  }); * /  $ scope.login =功能(电子邮件,密码){
    currentUser.login(电子邮件,密码);
  };  $ scope.logout =功能(){
    currentUser.logout();
  };});

吹的是服务 -

  angularApp.factory('的currentUser',函数($ rootScope){
  //业务逻辑
  // ...
  //
    VAR ALLUSERS = {rob@gmail.com:{名:罗伯特·帕特森的角色:管理,电子邮件:rob@gmail.com,密码:抢},
            steve@gmail.com:{名称:史蒂夫谢尔顿的角色:用户,电子邮件:steve@gmail.com,密码:史蒂夫}}  VAR isUserLoggedIn = FALSE;  //此处的公共API
  返回{
    登录:功能(电子邮件,密码){
      VAR用户= ALLUSERS [邮件]
      VAR storedPass = user.password的;      如果(storedPass ===密码){
        isUserLoggedIn = TRUE;
        返回true;
      }
      其他
      {
        返回false;
      }
    },
    注销:功能(){
      $ rootScope $广播('注销')。
      isUserLoggedIn = FALSE;
    },    isLoggedIn:功能(){
      返回isUserLoggedIn;
    }
 };
});


解决方案

我相信你的问题是这样的原型继承工作的结果。 NG-包括创建自己的子范围。在儿童范围指定为基本价值创造上作用域阴影/隐藏parent属性的新属性。

我猜,在login_form.html你做的东西像下面这样当用户登录:

 <一个NG点击=isLoggedIn =真正的>登录和LT; / A>

在isLoggedIn设置为true,这是你的范围是什么样子:

isLoggedIn设置为true

后,这是你的范围是什么样子:

希望的图片说清楚为什么这导致您的问题。

有关为什么原型继承这种方式工作与原语的更多信息,请访问<一个href=\"http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs\">What范围是原型/原型继承的细微差别AngularJS?

由于上面的链接解释,你有三种解决方法:


  1. 定义父为模型中的对象,然后引用该对象的属性在孩子:parentObj.isLoggedIn

  2. 使用$ parent.isLoggedIn在login_form.html - 那么这将引用原始的$父范围,而不是创建一个新的。例如,结果
    &LT;一个NG点击=$ parent.isLoggedIn =真正的&GT;登录和LT; / A&GT;

  3. 上定义的父范围的功能,并且从子称之为 - 例如,setIsLoggedIn()。这将确保父作用域属性被设置,而不是一个子作用域属性。

更新:在审查你的HTML,你实际上可能有子范围的两个级别,因为NG-开关和NG-包括每个创建自己的范围。因此,画面就需要一个孙子范围,但三种解决方案都是一样的...除了#2,您需要使用$ $父parent.isLoggedIn - 难看。因此,我建议选择1或3。

UPDATE2 :@ murtaza52添加了一些code的问题...删除 NG-的init =isLoggedIn = FALSE从控制器(您的服务管理通过其 isUserLoggedIn 变量登录状态),并在控制器上loginStatus)切换(&LT; D​​IV NG-开关关于=loginStatus()方式&gt;

下面是工作拨弄

I am trying to use ng-switch with ng-include below. The problem is with ng-init and the whole controller block getting re-rendered on any ng-includes change.

In the login_form.html, when a user logins, I set the isLoggedIn = true, in the LoginCtrl. However this causes the re-rendering of the full html below, which causes the ng-init again.

How do I avoid this cycle?

      <div ng-controller="LoginCtrl" ng-init="isLoggedIn = false" class="span4 pull-right">
        <div ng-switch on="isLoggedIn"> 
          <div ng-switch-when="false" ng-include src="'login_form.html'"></div>
          <div ng-switch-when="true" ng-include src="'profile_links.html'"></div>
        </div>
      </div>

Below is the HTML for the login form -

<form class="form-inline">
  <input type="text" placeholder="Email" ng-model="userEmail" class="input-small"/>
  <input type="password" placeholder="Password" ng-model="userPassword" class="input-small"/>
  <button type="submit" ng-click="login(userEmail, userPassword)" class="btn">Sign In</button>
</form>

Below is the controller -

angularApp.controller('LoginCtrl', function($scope, currentUser){

  $scope.loginStatus = function(){
    return currentUser.isLoggedIn();
  };

/*  $scope.$on('login', function(event, args) {
    $scope.userName = args.name;
  }); 

  $scope.$on('logout', function(event, args) {
    $scope.isLoggedIn = false;
  });*/

  $scope.login = function(email, password){
    currentUser.login(email, password);
  };

  $scope.logout = function(){
    currentUser.logout();
  };

});

Blow is the service -

angularApp.factory('currentUser', function($rootScope) {
  // Service logic
  // ...
  // 
    var allUsers = {"rob@gmail.com": {name: "Robert Patterson", role: "Admin", email: "rob@gmail.com", password: "rob"},
            "steve@gmail.com":{name: "Steve Sheldon", role: "User", email: "steve@gmail.com", password: "steve"}}

  var isUserLoggedIn = false;

  // Public API here
  return {
    login: function(email, password){
      var user = allUsers[email];
      var storedPass = user.password;

      if(storedPass === password){
        isUserLoggedIn = true;
        return true;
      }
      else
      {
        return false;
      }
    },
    logout: function(){
      $rootScope.$broadcast('logout');
      isUserLoggedIn = false;
    },

    isLoggedIn: function(){
      return isUserLoggedIn;
    }
 };
});

解决方案

I believe your problem is a result of the way prototypal inheritance works. ng-include creates its own child scope. Assigning a primitive value in a child scope creates a new property on that scope that shadows/hides the parent property.

I'm guessing that in login_form.html you do something like the following when a user logs in:

<a ng-click="isLoggedIn=true">login</a>

Before isLoggedIn is set to true, this is what your scopes look like:

After isLoggedIn is set to true, this is what your scopes look like:

Hopefully the pictures make it clear why this is causing you problems.

For more information about why prototypal inheritance works this way with primitives, please see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

As the above link explains, you have three solutions:

  1. define an object in the parent for your model, then reference a property of that object in the child: parentObj.isLoggedIn
  2. use $parent.isLoggedIn in login_form.html -- this will then reference the primitive in the $parent scope, rather than create a new one. E.g.,
    <a ng-click="$parent.isLoggedIn=true">login</a>
  3. define a function on the parent scope, and call it from the child -- e.g., setIsLoggedIn(). This will ensure the parent scope property is being set, not a child scope property.

Update: in reviewing your HTML, you may actually have two levels of child scopes, since ng-switch and ng-include each create their own scopes. So, the pictures would need a grandchild scope, but the three solutions are the same... except for #2, where you would need to use $parent.$parent.isLoggedIn -- ugly. So I suggest option 1 or 3.

Update2: @murtaza52 added some code to the question... Remove ng-init="isLoggedIn = false" from your controller (your service is managing the login state via its isUserLoggedIn variable) and switch on loginStatus() in your controller: <div ng-switch on="loginStatus()">.

Here is a working fiddle.

这篇关于NG-包括使控制器块重新呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆