0

У меня есть список элементов, и я отобразил их в шаблоне через ng-repeat. Каждый из них управляется itemController, который предоставляет некоторое поведение для элемента (например, захват фокуса). Вот HTML:Доступ к области доступа, соответствующей переменной модели

<body ng-controller="mainController"> 
    <button ng-click="addItem()">add</button> 
    <ul> 
    <li ng-repeat="item in items" ng-controller="itemController"> 
     <div ng-if="item.isEditing"> 
     <input ng-model="item.name"/> 
     <button ng-click="item.isEditing=false">done</button> 
     </div> 
     <span ng-if="!item.isEditing">{{item.name}}</span> 
    </li> 
    </ul> 
    </body> 

В mainController, у меня есть функция для добавления нового элемента в пунктов. Вот код для mainController:

app.controller('mainController', function($scope){ 
    $scope.items = [ 
    { 
     name: "alireza" 
    }, 
    { 
     name: "ali" 
    } 
    ]; 
    $scope.addItem = function(){ 
    $scope.items.push({isEditing: true}); 
    } 
}); 

Всякий раз, когда я добавить элемент в items массив, соответствующий li элемент добавляется в зрения которая контролируется экземпляром itemController, и соответствующая модель - это новый предмет, который я только что добавил (или, может быть, scopeitemController, в котором содержит позиция).

Проблема:

Когда я добавить элемент в items, я только иметь доступ к item и не масштаб недавно созданного элемента. Поэтому я не могу запустить некоторую функцию (например, grabFocus) в области нового элемента. Это что-то семантически неправильно в моем дизайне? Каков канонический подход к этой проблеме?

Plunker ссылка

Here is the plunker link with related comments

ответ

0

Я изменил ваш подход немного, создавая уникальный идентификатор для каждого входа, основанный на его номер индекса. См. Код ниже, надеюсь, что это поможет.

// Code goes here 
 

 

 
var app = angular.module("app",[]); 
 
app.controller('mainController', function($scope,$timeout){ 
 
    $scope.items = [ 
 
    { 
 
     name: "alireza" 
 
    }, 
 
    { 
 
     name: "ali" 
 
    } 
 
    ]; 
 
    $scope.addItem = function(){ 
 
    $scope.items.push({isEditing: true}); 
 
    $timeout(function(){ 
 
     document.getElementById("newItem"+($scope.items.length-1)).focus(); 
 
    },0) 
 
    } 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
<!DOCTYPE html> 
 
<html ng-app="app"> 
 

 
    <head> 
 
    <script data-require="[email protected]" data-semver="1.3.0" src="//code.angularjs.org/1.3.0/angular.js"></script> 
 
    <link href="style.css" rel="stylesheet" /> 
 
    <script src="script.js"></script> 
 
    </head> 
 

 
    <body ng-controller="mainController"> 
 
    <button ng-click="addItem()">add</button> 
 
    <ul> 
 
    <li ng-repeat="item in items"> 
 
     <div ng-if="item.isEditing"> 
 
     <input ng-model="item.name" id="newItem{{$index}}"/> 
 
     <button ng-click="item.isEditing=false">done</button> 
 
     </div> 
 
     <span ng-if="!item.isEditing">{{item.name}}</span> 
 
    </li> 
 
    </ul> 
 
    </body> 
 

 
</html>

+0

Спасибо, но я думаю, что это временное решение, а не чистое решение для таких ситуаций.Предположим, что вместо захвата фокуса была более сложная работа. Я думаю, что это «проблема с предметом» и не должна обрабатываться внешним контроллером. –

1

Вы можете использовать $broadcast из родительской области, наряду с $on от ребенка рамки, чтобы уведомить об этом дочерних рамках вновь добавленного элемента. И, передавая (в качестве аргумента) $id дочерней области, которая соответствует вновь добавленному элементу, каждый ребенок, поймавший событие, может узнать, должен ли он быть вызван grabFocus().

Вот fork of your Plunker, который использует этот подход. Я не был уверен, что вы пытались выполнить с $element.find(":text").focus(); в своем оригинальном Plunker, поэтому я настроил его, чтобы переключить свойство $scope, которое, в свою очередь, контролирует стиль в представлении. Недавно добавленный элемент будет красным (путем вызова его собственной функции grabFocus, чтобы переключить флаг на true), а остальные будут черными (путем вызова их собственной функции loseFocus для переключения флага на false).

Модифицированный HTML (только повторил li):

<li ng-repeat="item in items" ng-controller="itemController"> 
    <div ng-if="item.isEditing"> 
    <input ng-model="item.name"/> 
    <button ng-click="item.isEditing=false;handleItemAdded($index);">done</button> 
    </div> 
    <span ng-if="!item.isEditing" ng-style="{ color: isFocused ? 'red' : 'black' }">{{item.name}}</span> 
</li> 

Полный JavaScript:

var app = angular.module("app",[]); 
app.controller('mainController', function($rootScope, $scope){ 
    $scope.items = [ { name: "alireza" }, { name: "ali" } ]; 
    $scope.addItem = function(){ 
    $scope.items.push({isEditing: true}); 
    }; 
    $scope.handleItemAdded = function (index) { 
    // $rootScope.$broadcast('item-added', { index: index }); 
    for(var cs = $scope.$$childHead; cs; cs = cs.$$nextSibling) { 
     if (cs.$index === index) { 
     $rootScope.$broadcast('item-added', { id: cs.$id }); 
     break; 
     } 
    } 
    }; 
}); 
app.controller('itemController', function($scope, $element){ 
    $scope.$on('item-added', function (event, args) { 
    if ($scope.$id === args.id + 1) { 
     $scope.grabFocus(); 
    } else { 
     $scope.loseFocus(); 
    } 
    }); 
    $scope.grabFocus = function() { 
    $scope.isFocused = true; 
    }; 
    $scope.loseFocus = function() { 
    $scope.isFocused = false; 
    }; 
}); 
+0

... или, если вы хотите избежать свойств $$ '-prefixed, которые могут стать устаревшими, вот обновленный Plunker с более чистым подходом, который позволяет избежать таких: http://plnkr.co/edit/DjJBADTuAJ5GBSxXEqYg?p = preview –

+0

Спасибо. На самом деле, я уже делал что-то вроде этого, но мне было интересно, это лучшая практика или нет. Я думаю, что это не кажется разумной моделью для трансляции всем. Мне было интересно, все ли, что я пытаюсь сделать, неправильно и против MVC, и это ** вещание ** решение является всего лишь обходным путем, чтобы сделать это плохо! И если да, то каково решение для достижения того, чего я хочу? –

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