5

I need to add new items to a collection, that gets rendered with ngrepeat and using xeditable make it automatically editable.

BTW, I'm using the "manual trigger" method for xeditable.

Here it is the HTML

<h4>Angular-xeditable demo</h4>
<div ng-app="app" ng-controller="Ctrl" style="margin: 50px">
<div class="btn btn-default" ng-click="addNew()">+</div>
<ul>
  <li ng-repeat="item in array | orderBy:'-value'">
    <a href="#" e-form="itemForm" editable-text="item.field">{{ item.field }}</a>
    <i ng-show="!itemForm.$visible" ng-click="itemForm.$show()">edit</i>
  </li>
</ul>
</div>

and here the controller:

var app = angular.module("app", ["xeditable"]);

app.run(function(editableOptions) {
  editableOptions.theme = 'bs3';
});

app.controller('Ctrl', function($scope, $filter) {

  $scope.array = [
    {value: 1, field: 'status1'},
    {value: 2, field: 'status2'},
    {value: 3, field: 'status3'},
    {value: 4, field: 'status4'}
  ]; 

  $scope.addNew = function(){
    $scope.array.push({value:$scope.array.length+1, field: 'enter text here'});
    //MAKE IT EDITABLE????????
  }
});

Take a look to the issue in this fiddle: http://jsfiddle.net/dpamio/hD5Kh/1/

4

2 回答 2

3

这是一个有效的更新小提琴。由于指令的编写方式和ng-repeat工作方式,它需要一个非常hacky的解决方案......

app.controller('Ctrl', function($scope, $filter, $timeout) {

  $scope.itemForms = {};

  $scope.addNew = function(){
    $scope.array.push({value:$scope.array.length+1, field: 'enter text here'});

     // Use timeout to force evaluation after the element has rendered
     // ensuring that our assignment expression has run
     $timeout(function() {
         $scope.itemForms[0].$show(); // last index since we sort descending, so the 0 index is always the newest
     })
  }

ng-repeat 如何工作的背景: ng-repeat 将为每个重复的元素创建一个新的子范围。该指令使用传入的字符串e-form作为其名称(在本例中为itemForm)在该范围内分配一个变量。如果它更聪明,它将允许对赋值进行表达式评估。(然后我们可以将它分配给父范围,并在控制器中访问它,但这是另一回事)。

由于我们没有任何方法可以在指令之外访问这个子范围,所以我们做了一些非常糟糕的事情。我们在 display none 的范围内使用 mustache 表达式将itemForm变量分配给父范围,以便我们以后可以使用它。然后在我们的控制器内部,我们使用查找值来调用itemForm.$show()我们期望的方法。

将那一点讨厌的东西抽象成一个角度指令,我们可以编写以下内容:

.directive('assignFromChild', function($parse) {
    return {
        restrict: 'A',
        link: function(scope, el, attrs) {
            scope.$watch(function() { return $parse(attrs.assignFromChild)(scope); }, function(val) {
                $parse('$parent.' + attrs.toParent).assign(scope, val);
            })
        }
    }; 
});

允许我们的 HTML 返回到:

<ul>   
  <li ng-repeat="item in array | orderBy:'-value'" assign-from-child="itemForm" to-parent="itemForms[{{$index}}]">
    <a href="#" e-form="itemForm" editable-text="item.field">{{ item.field }}</a>
    <i ng-show="!itemForm.$visible" ng-click="itemForm.$show()">edit</i>
  </li>
</ul>

这是我最终解决方案的一个小提琴

于 2015-02-28T07:26:50.350 回答
1

我找到了一个非常简单的解决方案ng-init="itemForm.$show()"它会在插入新项目时激活 xeditable 表单。

这是更新的 jsFiddle 回答问题:http: //jsfiddle.net/hD5Kh/15/

于 2016-04-12T19:33:09.820 回答