【问题标题】:angularjs - ngRepeat with ngInit - ngRepeat doesn't refresh rendered valueangularjs-带有ngInit的ngRepeat-ngRepeat不刷新渲染值
【发布时间】:2013-03-12 06:55:24
【问题描述】:

我有一个使用 ngRepeater 显示的数组,但是通过这个指令,我使用了 ngInit 指令,该指令执行应该返回要显示的对象的函数。一切正常,但是当我添加“新建”按钮时,我将新值添加到数组中,然后函数“SetPreview”仅在我认为应该根据数组值的数量执行时才执行。我怎样才能做到这一点?

用户界面:

<body ng-app>

  <ul ng-controller="PhoneListCtrl">
      <button ng-click="add()">Add</button>
    <li ng-repeat="phone in phones" ng-init="displayedQuestion=SetPreview(phone);">
      {{displayedQuestion.name}}
      <p>{{displayedQuestion.snippet}}</p>
    </li>
  </ul>
</body>

控制器:

function PhoneListCtrl($scope) {
  $scope.phones = [
    {"name": "Nexus S",
     "snippet": "Fast just got faster with Nexus S."},
    {"name": "Motorola XOOM™ with Wi-Fi",
     "snippet": "The Next, Next Generation tablet."},
    {"name": "MOTOROLA XOOM™",
     "snippet": "The Next, Next Generation tablet."}
  ];

    $scope.add = function(){
        this.phones.push({name:'1', snippet:'n'});
    };        
    $scope.SetPreview = function(phone)
    {
        //here logic which can take object from diffrent location
        console.log(phone);
        return phone;
    };
}

Sample is here - jsfiddle

编辑:
Here is more complicated sample: -> 现在电话集合是空的,当您单击添加按钮时,会添加新项目并设置为可编辑(您可以更改文本字段中的值)以及执行 ngRender 时的 SetPreview 功能返回可编辑对象(就像预览一样工作)。现在尝试再次单击添加按钮,您可以看到第一项的可编辑值仍然呈现给用户,但我想刷新整个 ng-repeater。

【问题讨论】:

  • 当您按下添加按钮时,SetPreview 执行了多少次?最初应该是 4 次,但只执行一次。查看控制台窗口;)
  • 每个add 都会在控制台中产生 1 个新条目
  • 完全正确,但我想刷新整个 ng-repeater 那么控制台中的条目数量应该与数组项的数量相等。我的函数 SetPrieview 可以返回已编辑的对象(在此示例中未实现)并进行渲染,但是当用户按下添加按钮时,他退出编辑并应显示原始值,但当前仅添加新记录并仍显示编辑值。我认为我必须强制刷新整个 ngRepeat。如果您愿意,我可以通过编辑内容创建整个示例
  • 是的,如果你能分享整个样本会更好
  • 我已经编辑了问题,希望现在更容易理解

标签: angularjs


【解决方案1】:

您遇到了 Angular 性能特性。

本质上 Angular 可以看到数组中的元素(例如“A”)是同一个对象引用,因此它不会再次调用 ng-init。这是有效的。即使您将旧列表连接到新列表中,Angular 也会看到它是相同的引用。

如果您创建一个与旧对象具有相同值的新对象,则它具有不同的引用并且 Angular 会重新初始化它: 做你正在寻找的坏例子:http://jsfiddle.net/fqnKt/37/

$scope.add = function(item) {
    var newItems = [];
    angular.forEach($scope.items, function(obj){
        this.push({val:obj.val});
    },newItems)

    newItems.push({val:item})
    $scope.items = newItems;
};

我不推荐小提琴中采用的方法,而是您应该找到与 ng-init 不同的方法来触发您的代码。

【讨论】:

    【解决方案2】:

    我发现您可以在隐藏块中将 ng-init 替换为角度表达式 {{}}

    <body ng-app>
    
    <ul ng-controller="PhoneListCtrl">
        <button ng-click="add()">Add</button>
        <li ng-repeat="phone in phones">
          <span style="display: none">{{displayedQuestion=SetPreview(phone)}}</span>
          {{displayedQuestion.name}}
          <p>{{displayedQuestion.snippet}}</p>
        </li>
      </ul>
    </body>
    

    【讨论】:

      【解决方案3】:

      如果元素中有 ngInit,而后代中有 ngRepeat,则 ngInit 只会运行一次。

      要解决此问题,请使用 ngInit 向元素添加 ngRepeat,并使用重复一次并依赖于同一数组(和其他依赖项)的表达式。

      例如:

      ng-repeat="_ in [ products ]" ng-init="total = 0"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-03-12
        • 1970-01-01
        • 1970-01-01
        • 2013-05-29
        • 2013-12-13
        • 1970-01-01
        • 2017-03-05
        相关资源
        最近更新 更多