2013-12-04 2 views
3

Предполагая, что контроллер предназначен для управления некоторыми данными по объему, какова наилучшая практика для поставки контроллера этими данными?поставка данных контроллера AngularJS

Например, если у меня есть список элементов, которые могут понадобиться ListController для управления списком и ItemController для управления отдельным элементом. Но как я могу дать каждому элементу ItemController элемент для использования?

В нижеследующем случае, как бы сделатьSomethingToItem доступ к элементу. При вложении в ngRepeat элемент имеет значение $ scope.item, но в представлении выбора элемент, который мы хотим манипулировать, - это $ scope.selection.

angular.module('MyApp', []) 

    .controller('ListController', function($scope, $http) { 

     $scope.list = $http.get(...); 

     $scope.selection = null; 

    }) 

    .controller('ItemController', function($scope) { 

     $scope.doSomethingToItem = function() { 
      ... 
     }; 

    }) 


<div ng-controller="ListController"> 
    <div ng-repeat="item in list" ng-click="selection = item"> 
     <div ng-controller="ItemController"> 
      <button ng-click="doSomethingToItem()">Do Something</button> 
     </div> 
    </div> 
    <div ng-show="selection" 
     <div ng-controller="ItemController"> 
      <button ng-click="doSomethingToItem()">Do Something</button> 
     </div> 
    </div> 
</div> 

Разве это не общая структура, или мое мышление назад?

ответ

1

Вы можете передать данные модели пункт так:

<div ng-init="instance = item" ng-controller="ItemController"> 
</div> 

«instance» будет ссылкой на элемент модели данных массива списка i n "ListController".

И вы могли бы получить доступ к его свойству в вашей замыканию функции ItemController:

.controller("ItemController", function($scope){ 
    $scope.instance={}; 
    $scope.doSomething = function(){ 
    console.log($scope.instance.name); 
    } 
    $scope.$watch('instance',function(){ 
    console.log("iitem changed"); 
    },true); 
}); 

Я не совсем уверен, что функция вы хотите достичь в своей реализации «Выбор».

Я думаю, что вы хотите реализовать выбранный список, и элемент списка будет добавлен к нему, когда пользователь щелкнет элемент списка. Вы можете попытаться создать модель «выбранного списка» для управления выбранным представлением списка, если вы хотите добавить выбранный элемент в список.

ListController.JS

.controller("ListController", function($scope){ 
    $scope.selectedList = []; 
    $scope.addItem = function(item){ 
    $scope.selectedList.push(item); 
    } 
}); 

HTML

<div ng-repeat="selected in selectedList"> 
    <div ng-init="instance = selected" ng-controller="ItemController"> 
    <span>{{instance.name}}</span> 
    <button ng-click="doSomething()">selectedAction</button> 
    </div> 
</div> 

Я написал простой мульти выбранный пример списка следующим образом:

HTML

<!doctype html> 
<html lang="en" ng-app="myApp"> 
<head> 
<meta charset="UTF-8"> 
<title>Nested controller</title> 
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script> 
<script src="js/nestedController.js"></script> 
</head> 
<body> 
<div ng-controller="parentCtrl"> 
    <h2>List</h2> 
    <div ng-repeat="item in list"> 
     <input type="checkbox" ng-model="item.selected" ng-checked="item.selected"/> 
     <div ng-init="instance = item" ng-controller="childCtrl"> 
      <span>{{instance.name}}</span> 
      <button ng-click="doSomething()">doSomething</button> 
     </div>   
    </div> 
    <h2>Selected</h2> 
    <div ng-repeat="selected in selectedList"> 
     <div ng-init="instance = selected" ng-controller="childCtrl"> 
      <span>{{instance.name}}</span> 
      <button ng-click="selectedAction()">selectedAction</button> 
     </div> 
    </div> 
</div> 

JS

angular.module("myApp",[]) 
.controller("parentCtrl",function($scope){ 
    //test data 
    $scope.list = [{name:'item1',age:'12',selected:false},{name:'item2',age:'18',selected:false}]; 
    //use model to control selected list view 
    $scope.selectedList = []; 
    //refresh the selected list model when the list checked stauts has been updated 
    $scope.$watch('list',function(){ 
    console.log("parent controller detected change"); 
    $scope.selectedList = []; 
    $scope.list.forEach(function(elem,index,array){ 
     if(elem.selected===true){ 
      $scope.selectedList.push(elem); 
     } 
    }); 
    },true); 
}) 
.controller("childCtrl",function($scope){ 
    $scope.instance={} 
    $scope.doSomething = function(){ 
    alert("I'm the item: "+$scope.instance.name); 
    } 

    $scope.selectedAction = function(){ 
    alert("I'm the selected item: "+$scope.instance.name); 
    } 
    //could register a watcher to monitor the model status 
    $scope.$watch('instance',function(){ 
    console.log("child controller detected change"); 
    },true); 
}); 

Вот jsFiddle demo

Надеется, что это полезно.

+0

Это отличная идея. Благодарю. Я смущаюсь использовать ngInit из-за этой строки в документах angularjs: «Единственное подходящее использование ngInit для сглаживания специальных свойств ngRepeat, как видно из демонстрации ниже. Кроме этого случая, вы должны использовать контроллеры, а не ngInit, чтобы инициализировать значения на область действия. " Где они использовали его для вложенных ngRepeats: 'ng-repeat =" innerList в списке "ng-init =" outerIndex = $ index "'. Хотя они не объясняют, почему они делают этот комментарий. – nicholas

2

Вы должны понимать, что Angular создаст n + 1 ItemController в вашем случае. N для элементов и 1 для секции выбора.

Для передачи объекта, который должен быть разработан на легче вы можете изменить метод подписи

doSomethingToItem(item) и в HTML сделать

<button ng-click="doSomethingToItem(item)">Do Something</button> в обоих местах.

Или же для повторного случае переменная item содержит ваш объект, который вы можете получить доступ в ItemController

selection переменная содержит ссылку на выберите контроллер, который может быть справка из экземпляра контроллера, определенного в разделе выбора ,

Update: Выражение в нг-повтора и выбора будет отличаться

<button ng-click="doSomethingToItem(item)">Do Something</button>

и

<div ng-show="selection" 
     <div ng-controller="ItemController"> 
      <button ng-click="doSomethingToItem(selection)">Do Something</button> 
     </div> 
    </div> 
+0

Я не думаю, что это тоже сработало? Когда вы используете переменную в шаблоне, она привязана к $ scope. Поэтому я ожидал бы doSomethingToItem (item), чтобы попытаться разрешить $ scope.item внутри ItemController. Это было бы неопределенным. –

+1

@JasonFarnsworth, вы правы. Я обновил ответ. – Chandermani

+1

Передача предмета в doSomethingToItem() - хорошая идея, но вы теряете много. В этот момент вы могли бы также включить функцию в ListController, чтобы избежать запуска ItemController N + 1 раз, как вы указываете. Причина, по которой вы используете ItemController, - это получить эту область, чтобы вы могли делать такие вещи, как '$ scope. $ On ('some-event', function() {...});' или '$ scope. $ Watch ('expression', function() {...}); 'Как эти обратные вызовы будут знать, что такое элемент? – nicholas

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