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一個實例控制,以及相應的模型是我剛剛添加的新項目(或者可能是itemControllerscope,其中包含項目)。

問題:

當我加入一些項目items,我只能訪問item和最近創建的項目不是範圍。所以我不能在新項目的範圍上運行一些函數(如grabFocus)。 在我的設計中,它在語義上是錯的嗎?這個問題的典型方法是什麼?

Plunker鏈接

Here is the plunker link with related comments

回答

0

我通過建立每輸入一個唯一的ID,根據其指數改變你的方法一點點。看到下面的代碼,希望它有幫助。

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

謝謝你,但我認爲這是一種解決方法,而不是針對這些情況一個乾淨的解決方案。假設有一個更復雜的工作,而不是抓住焦點。我認爲這是'項目'的問題,不應該在外部控制器中處理。 – 2014-11-01 01:58:44

1

您可以使用$broadcast從父範圍,與$on從子範圍一起,通知新添加的項目的子作用域。通過傳遞(作爲參數)與新增項目相對應的子作用域的$id,每個捕捉事件的孩子都可以知道它是否需要調用grabFocus()

下面是使用該方法的fork of your Plunker。我不知道你試圖用你原來Plunker $element.find(":text").focus();來完成,所以我調整了它切換一個$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

...或者,如果您想要避免可能會被棄用的$$前綴屬性,請使用更清晰的方法來更新Plunker,以避免這些問題:http://plnkr.co/edit/DjJBADTuAJ5GBSxXEqYg?p =預覽 – 2014-11-01 01:19:28

+0

謝謝。其實,我已經做了這樣的事情,但我想知道這是不是最好的做法。我認爲向所有人廣播似乎並不合理。我想知道是否我想要做的事情是錯誤的,並針對MVC,這**廣播**解決方案只是一個解決方法,做這個壞事!如果是這樣,那麼達到我想要的標準解決方案是什麼? – 2014-11-01 02:19:18