简体   繁体   English

Angular ngClick无法访问其他范围内的变量

[英]Angular ngClick cannot access variable in a different scope

I am completely new to Javascript and especially AngularJs. 我对Java语言,尤其是AngularJs完全陌生。 Here is my problem, I need to call ng-click function inside ng-repeat to hide a some html outside of it. 这是我的问题,我需要在ng-repeat中调用ng-click函数以在其中隐藏一些html。

As I understand the problem is because all of the variables (in this case specifically variable "locations") is in another scope which I cannot access. 据我了解,问题是因为所有变量(在本例中为变量“ locations”)都在另一个无法访问的范围内。 Can anybody help me with the shortest way possible to go around this problem? 有人可以以最快的方式帮助我解决这个问题吗?

I have managed so far to almost finish my website with only angular html tags (meaning I didn't really have to write any custom functions) and this is the absolute last piece. 到目前为止,我几乎只用角html标签完成了我的网站(这意味着我实际上不必编写任何自定义函数),而这绝对是最后一步。

Also, as I understand whenever a new controller in angular is created, it has its own scope. 另外,据我了解,每当创建一个新的Angle控制器时,它都有自己的作用域。 In this case, all of the calls (besides the one that I am having problems with) have been made without initializing any of the controllers, so how do you access variables? 在这种情况下,所有调用(除了我遇到问题的调用)都是在没有初始化任何控制器的情况下进行的,那么如何访问变量? Is there something like a "default Scope"? 是否有类似“默认范围”的内容? I know rootScope did not work for me. 我知道rootScope对我不起作用。

Thank you in advance. 先感谢您。

<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>

You will have to create a controller surrounding both HTML fragments: 您将必须围绕两个HTML片段创建一个控制器:

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

The controller will define the locations property, but inside another object (let's call it viewState ): 控制器将定义locations属性,但另一个对象内部 (我们将其viewState ):

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

Then bind to the inner locations : 然后绑定到内部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">

The reason for this, and why it didn't work for you with the $rootScope is how scopes inherit the properties of their parents through Javascript's prototypical inheritance. 这样做的原因以及$rootScope为何对您不起作用,是因为范围是如何通过Javascript的原型继承来继承其父级属性的。 Roughly and really shortly: 大致且实际上不久:

When you read a property from a scope and that scope does not contain this property, JS will look at its prototype (again very roughly speaking, the scope's parent scope). 当您从范围中读取一个属性并且该范围不包含此属性时,JS将查看其原型( 大致来说,该范围的父范围)。 The chain continues up to the $rootScope . 链一直延伸到$rootScope So, putting locations in the $rootScope will result in successful reading of this property. 因此,将locations放在$rootScope中将成功读取该属性。

Whenever you write a variable to a scope, it is written directly to that scope, no matter where it was read from. 每当变量写入作用域时,无论从何处读取变量,都会将其直接写入该作用域。 So changing locations in the inner scope has no effect in the outer scope (eg $rootScope ). 因此,更改内部作用域中的locations在外部作用域中不起作用(例如$rootScope )。

Putting the variable inside an object results in reading the object, which resolves to the correct scope, then writting the property to the correct object. 将变量放在对象内将导致读取对象,该对象解析为正确的范围,然后将属性写入正确的对象。

This is what I ended up using. 这就是我最终使用的。 It seems extremely simple but maybe it will help others who are beginners as well. 看起来非常简单,但也许会对初学者也有所帮助。 This is basically the code for making values accessible in different controllers. 基本上,这是使值可在不同控制器中访问的代码。 It is the same as Nikos suggested if I understood it correctly. 如果我理解正确,它与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;
    })

This is what I do to have an accessible Rootscope. 这就是我拥有可访问的Rootscope所做的工作。

Set up Rootscope in app.run: (Don't forget to inject $rootScope) 在app.run中设置Rootscope:(不要忘记注入$ rootScope)

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

Create a Controller with a function that changes Rootscope ($rootscope injected too) 创建一个具有更改Rootscope的功能的Controller(也注入$ rootscope)

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

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

    }

So this is the html: 因此,这是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>

And this is the JS: 这就是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;
  }
}

You will find a working Plunker here: http://plnkr.co/edit/ygLlIoE55aI5q8Wkicc5?p=preview 您可以在这里找到工作的Plunker: http ://plnkr.co/edit/ygLlIoE55aI5q8Wkicc5?p=preview

Not sure if this what you wanted. 不确定这是否是您想要的。 But I hope it helps anyway. 但我希望它能有所帮助。 (Don't yell at me that this is against Angular Zen, because of reasons:-) (不要因为这样而对我大喊:这是对Angular Zen的反对:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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