Angular ng Click无法访问不同范围内的变量

时间:2014-01-09 16:13:47

标签: javascript html angularjs angularjs-scope

我是Javascript的新手,尤其是AngularJs。这是我的问题,我需要在ng-repeat中调用ng-click函数来隐藏它之外的一些html。

据我所知,问题是因为所有变量(在这种情况下特别是变量“locations”)都在另一个我无法访问的范围内。任何人都可以用最短的方式帮我解决这个问题吗?

到目前为止,我已经管理到几乎完成我的网站只有角html标签(意味着我真的不需要编写任何自定义函数),这是绝对的最后一块。

另外,据我所知,每当创建一个角度为新的控制器时,它都有自己的范围。在这种情况下,所有的调用(除了我遇到的问题)都是在没有初始化任何控制器的情况下完成的,那么如何访问变量呢?有没有类似“默认范围”的东西?我知道rootScope不适合我。

提前谢谢你。

  

<div id="top_nav">
    <div id="top_nav_right">    
        <div id="page_header" ng-show="checked" ng-switch on="page">
        </div>  
        <a href="#" ng-click="checked = ! checked">
        </a>
    </div>      
</div>  
<div id="main_sidebar" class="check-element animate-hide" ng-show="checked">
    <ul class="menu" ng-show="!locations">
    </ul>
    <ul class="menu" ng-show="locations">
    </ul>
</div>

<div id="sub_sidebar" ng-show="checked" ng-switch on="page">
        <div ng-switch-default "check-element animate-hide">
                <div id="latest_trips_container">       
                    <div ng-controller="PostsCtrlAjax">  
                                <ul id="latest_trips" ng-controller="MyCtrl">   
                                    <li ng-repeat="post in travels">
                                                <div id="trip_details">
                                                    <a id="details" href="#/details" ng-click="locations =! locations"></a>
                                                </div>
                                    </li>
                                </ul>
                    </div>  
                </div>
        </div>              
</div>

3 个答案:

答案 0 :(得分:1)

您必须创建一个围绕两个HTML片段的控制器:

<div ng-controller="Ctrl">
    <!-- YOUR CODE HERE -->
</div>

控制器将定义locations属性,但 inside 另一个对象(让我们称之为viewState):

app.controller("Ctrl", function($scope) {
    $scope.viewState = {
        locations: false
    };
};

然后绑定到内部locations

<ul class="menu" ng-show="!viewState.locations">
</ul>
<ul class="menu" ng-show="viewState.locations">
</ul>
...
<a id="details" href="#/details" ng-click="viewState.locations = !viewState.locations">

这个的原因,以及为什么它对$rootScope不起作用的是范围如何通过Javascript的原型继承继承父元素的属性。大致而且很快:

当您从作用域读取属性并且该作用域不包含此属性时,JS将查看其原型(再次非常粗略地说,作用域的父作用域)。该链继续到$rootScope。因此,将locations放入$rootScope将导致成功阅读此属性。

无论何时变量写入作用域,都会将其直接写入该作用域,无论从何处读取。因此,更改内部范围中的locations对外部范围没有影响(例如$rootScope)。

将变量放在对象中导致读取对象,该对象解析为正确的范围,然后将属性写入正确的对象。

答案 1 :(得分:0)

这是我最终使用的。这似乎非常简单,但也许它会帮助其他初学者。这基本上是使值可以在不同的控制器中访问的代码。如果我理解正确,它与Nikos建议的相同。

var myApp = angular.module('myApp',[]);

    myApp.value('Pages',{page:"My Profile"});
    myApp.value('Menu',{show:false});
    myApp.value('Menu2',{show2:false});

    myApp.controller('MainMenu', function($scope,Menu,Pages) {
        $scope.menu = Menu;
        $scope.pages = Pages;
    });

    myApp.controller('MainSidebar', function($scope,Menu,Menu2,Pages) {
        $scope.menu = Menu;
        $scope.menu2 = Menu2;
        $scope.pages = Pages;
    });

    myApp.controller('SecondSidebar', function($scope,Menu,Menu2,Pages) {
        $scope.menu = Menu;
        $scope.menu2 = Menu2;
        $scope.pages = Pages;
    });


    myApp.controller('TripsFx', function($scope,Menu2,Pages) {

        $scope.menu2 = Menu2;
        $scope.pages = Pages;
    })

答案 2 :(得分:-1)

这就是我可以使用Rootscope的方法。

在app.run中设置Rootscope :(不要忘记注入$ rootScope)

    var myApp = angular.module('ProGen', []);
    myApp.run(function($rootScope) {
      //setup Rootscope
      $rootScope.locations = false;
    })

使用更改Rootscope的函数创建一个Controller($ rootscope注入)

    function someCtrl($rootScope, $scope) {
      $scope.travels = [
        {dest: 'Rome'},
        {dest: 'London'}
        ];

      $scope.flipMenu = function() {
        $rootScope.locations = !$rootScope.locations;
      }

    }

所以这是html:

    <html ng-app>
            {...}
    <body>
      <div id="main_sidebar">
        <ul class="menu" ng-show="!locations">
          <li>x1</li>
          <li>x2</li>
          <li>x3</li>
          <li>x4</li>
        </ul>
        <ul class="menu" ng-show="locations">
          <li>y1</li>
          <li>y2</li>
          <li>y3</li>
          <li>y4</li>
        </ul>
      </div>

      <div ng-click="locations =! locations">Change me (no Controller)</div>

      <div ng-controller="someCtrl">
        <ul>
          <li ng-repeat="post in travels">
            <div ng-bind="post.dest" ng-click="flipMenu()"></div>
          </li>
        </ul>
      </div>

    </body>

    </html>

这是JS:

  var myApp = angular.module('ProGen', []);
  myApp.run(function($rootScope) {
    //setup Rootscope
    $rootScope.locations = false;
  })

function someCtrl($rootScope, $scope) {
  $scope.travels = [
    {dest: 'Rome'},
    {dest: 'London'}
    ];

  $scope.flipMenu = function() {
    $rootScope.locations = !$rootScope.locations;
  }
}

你会在这里找到一个有效的Plunker:http://plnkr.co/edit/ygLlIoE55aI5q8Wkicc5?p=preview

不确定这是否是你想要的。但无论如何,我希望它有所帮助。 (不要对我大喊大叫这是对抗Angular Zen,原因是: - )