2014-11-13 3 views
0

Я новичок в угловом, я прочитал пару статей по области и контроллерам, но я думаю, что до сих пор не понял.

Допустим, у нас есть код

var myApp = angular.module("myApp", []); 
    myApp.controller("myCtrl", function($scope) { 

     $scope.array = [1,2,3]; 

     $scope.show = false; 
     $scope.toggle = function(){ 
      $scope.show = !$scope.show; 
      console.log($scope.show); 
     }; 
    }); 

и разметки:!.

<body ng-app="myApp"> 
<ul ng-controller="myCtrl"> 
    <li ng-repeat="n in array"> 
     <a href="#" ng-click="show = !show">Click here to show</a> 
     <span ng-show="show">Something to show</span> 
    </li> 
</ul> 
</body> 

Все работает, когда я использую "нг-клик =" показать = шоу»в нг-шоу Но когда я использую toggle() insted, это не так. Мой вопрос в том, как изменить код, чтобы заставить метод toggle() работать? Как получить доступ к области действия, чем я работаю в контроллере? Должен ли я использовать ng-controller = "myCtrl" для каждого тега li? Должен ли я иметь контроллер для каждой области действия, созданной директивами в моей разметке? Какова наилучшая практика здесь?

+0

Это один немного сложнее, потому что нг-повтор создает новую область для каждого повтора ребенка. Таким образом, переменная «show» в toggle будет родительской переменной, но «show» в вашем ng-show является дочерней переменной. –

ответ

0

То, что говорят, верно, show внутри ngRepeat отличается от show в myCtrl. Однако, даже если это не так, есть только одна переменная show в myCtrl, поэтому каждый элемент будет скрыт и показан вместе при переключении.

Если вы хотите переключать отдельные строки, каждому из них нужен собственный флаг. Это можно сделать несколькими способами. Но чтобы избежать слишком большой логики в представлении и избежать использования $parent, одним из способов было бы использовать синтаксис controller as и сохранить список флажков show, воспользовавшись тем, что ngRepeat поставляет индекс массива как $index.

var myApp = angular.module("myApp", []); 
myApp.controller("myCtrl", function() { 
    var myCtrl = this; 
    myCtrl.array = [1,2,3]; 
    myCtrl.show = [false, false, false]; 

    myCtrl.toggle = function (index){ 
     myCtrl.show[index] = !myCtrl.show[index]; 
     console.log(myCtrl.show); 
    }; 
}); 

Тогда вид:

<body ng-app="myApp"> 
<ul ng-controller="myCtrl as ctrl"> 
    <li ng-repeat="n in ctrl.array"> 
     <a href="#" ng-click="ctrl.toggle($index)">Click here to show</a> 
     <span ng-show="ctrl.show[$index]">Something to show</span> 
    </li> 
</ul> 
</body> 

Вы также можете использовать массив объектов, если вы собираетесь делать что-то сложное, где отслеживание двух массивов будет трудно. Что-то вроде:

myCtrl.array = [ 
    {val: 1, show: false}, 
    {val: 2, show: false}, 
    {val: 3, show: false}, 
]; 

Тогда функция переключения будет:

myCtrl.toggle = function(obj){ 
    obj.show = !obj.show; 
}; 

и вид:

<body ng-app="myApp"> 
<ul ng-controller="myCtrl as ctrl"> 
    <li ng-repeat="n in ctrl.array"> 
     <a href="#" ng-click="ctrl.toggle(n)">Click here to show</a> 
     <span ng-show="n.show">Something to show</span> 
    </li> 
</ul> 
</body> 

Edit: вот plunkr для каждого.

http://plnkr.co/edit/sBhY00c5LU4YMeHlqjG7?p=preview

http://plnkr.co/edit/axO9sEB6oHQeDwIRLU4a?p=preview

+0

Спасибо, это звучит разумно для меня, просто интересно, скажем, что array - это коллекция моих доменных имен, можно ли приложить это искусственное свойство «показать» моей модели? это обычная практика? – Samuraka

+0

Нет, я не думаю, что это была бы очень хорошая практика. Хотя это, безусловно, будет работать, это хорошая идея, чтобы ваши сущности были чистыми от любой логики отображения. Лучше всего было бы сохранить список «показанных» сущностей в контроллере, используя какой-то первичный идентификатор или ссылку на сам объект. Или в примере, который я дал с массивом объектов, просто замените значение 'val' вашей сущностью или основным идентификатором объекта. – Makaque

+0

Дело в том, что в то время мне нужно было показывать только один элемент, поэтому было бы лучше просто сохранить индекс и использовать его каким-то образом, а не нужен для массива. и что вы думаете о том, чтобы поместить ng-controller = "myCtrl" вместе с ng-repeat, что сделало бы область работы ... но я не знаю, что это за последствия:) – Samuraka

0

Причина, по которой все кажется странным, заключается в том, что ngRepeat использует область изоляции. Это означает, что он создает новую дочернюю область без родителя.

Когда вы используете show = !show, вы создаете значение show для этого дочернего объекта.

Когда вы используете toggle, вы пытаетесь вызвать метод в области, которая не существует.

Вы можете попробовать позвонить $parent.toggle() на событие click, но это будет устанавливать значение show в родительской области, а не в отдельных строках.

+0

Мне кажется, что $ partent для кода вызовет некоторое предположение/зависимость (что, если я хочу использовать мой контроллер в другом представлении?). Aslo оставаться с show =! Show, похоже, походит на то, что логика во многих местах ... просто все еще не уверен, что это лучший подход здесь .... – Samuraka

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