从父指令删除子指令时,ngRepeat错误 [英] ngRepeat error when removing child directive from parent directive

查看:31
本文介绍了从父指令删除子指令时,ngRepeat错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在图库管理器组件上遇到了一些问题,您可以在其中添加/删除图片.

这是图库处理程序的html代码:

 < img src ='{{snapshot}}'>< div class ='md-button l3'is-file ng-model ='picture'blob-url ='snapshot'>上传</div>< div class ='md-button l3'ng-click ='article.pictures.push(picture)'>添加</div>< div gallery-manager ='article.pictures'></div> 

以下,这些指令:

  .directive("galleryManager",function($ compile){var controllerFn = function($ scope,$ element,$ attrs){var self = this;self.removeItemAt = function($ index){self.pictures.splice($ index,1);$ compile($ element)($ scope);<-请注意}}var linkFn = function($ scope,$ element,$ attrs){}返回 {模板:< div gallery-item ='图片'ng-repeat ='图片在galleryManagerCtrl.pictures track by $ index'</div>",,限制:"A",控制器:controllerFn,controllerAs:"galleryManagerCtrl",bindToController:{图片:"= galleryManager",}}}).directive("galleryItem",function(FileService){var linkFn = function($ scope,$ element,$ attrs,galleryManagerCtrl){$ scope.galleryItemCtrl.galleryManagerCtrl = galleryManagerCtrl;}var controllerFn = function($ scope,$ element,$ attrs){var self = this;如果(File的self.item实例){FileService.buildBlobUrl(self.item).then(function(blobUrl){self.thumb = blobUrl;})}}返回{模板:< img src ='{{galleryItemCtrl.thumb}}'>" +< a class ='delete'ng-click ='galleryItemCtrl.galleryManagerCtrl.removeItemAt($ index)'& times</span></a>,"限制:"A",要求:"^ galleryManager",链接:linkFn,控制器:controllerFn,bindToController:{item:"= galleryItem",},controllerAs:"galleryItemCtrl"}}) 

现在,该指令在添加元素时运行良好,但是在删除项目时会出现问题.使用之前:$ compile($ element)($ scope)删除后,在图库中总是消失了最后一个项目,尽管picture数组删除了正确的项目,所以我在删除项目后添加了$ compile行.

问题在于,尽管图库现在可以满足我的要求,但编译后仍然会抛出错误(发布完整的跟踪记录,也许可以对某人有所帮助):

  angular.js:13920 TypeError:无法读取null的属性'insertBefore'在之后(http://localhost/www/project/admin/bower_components/angular/angular.js:3644:13)在JQLite.(匿名函数)[如后](http://localhost/www/project/admin/bower_components/angular/angular.js:3728:17)在domInsert(http://localhost/www/project/admin/bower_components/angular/angular.js:5282:35)在Object.move(http://localhost/www/project/admin/bower_components/angular/angular.js:5488:9)在ngRepeatAction(http://localhost/www/project/admin/bower_components/angular/angular.js:29865:26)在$ watchCollectionAction(http://localhost/www/project/admin/bower_components/angular/angular.js:17385:13)在Scope.$ digest(http://localhost/www/project/admin/bower_components/angular/angular.js:17524:23)在ChildScope.$ apply(http://localhost/www/project/admin/bower_components/angular/angular.js:17790:24)< anonymous>.(http://localhost/www/project/admin/bower_components/angular/angular.js:25890:23)在defaultHandlerWrapper(http://localhost/www/project/admin/bower_components/angular/angular.js:3497:11) 

这似乎来自ngRepeatDirective的watchCollection.

我觉得我缺少一些基本知识,但是看不到现在是什么,所以,在深入探讨角度代码之前,我来问一下.

谢谢.

编辑

添加了一个工作示例: http://codepen.io/sergio0983/pen/rMEMoJ?editors=1010

编辑2

从工作示例中删除了$ compile,它可以工作,是的,但是会引发错误;而且,我认为真正的问题在其他地方.在工作示例中,您可以看到删除项目时如何更新文件名,但是图片保持其原始顺序.

解决方案

  1. 向您的 mainController 中添加 addPicture()函数(这将在图片对象中添加恒定的唯一ID):

      .controller("mainController",function($ scope){$ scope.article = {图片:[]};$ scope.addPicture =函数addPicture(图片){//设置唯一的IDpicture.id = $ scope.article.pictures.length;$ scope.article.pictures.push(picture);};}) 

  2. 将添加按钮HTML更改为:

     < div class ='md-button l3'ng-click ='addPicture(picture)'> Add</div> 

  3. galleryManager 模板更改为 picture.id 跟踪:

     < div gallery-item ='picture'ng-repeat ='galleryManagerCtrl中的图片.picturesby picture.id'></div> 

  4. 修改 removeItemAt()函数,(此处不需要 $ compile ):

      self.removeItemAt = function removeItemAt(id){//查找具有给定id的图片的索引id = self.pictures.findIndex((item)=> item.id === id);self.pictures.splice(id,1);} 

    修改后的代码笔: http://codepen.io/anon/pen/mrZOre?editors= 1010

I´m having some issues with a gallery manager component where you can add/remove the pictures.

This is the html code of the gallery handler:

<img src = '{{snapshot}}' >
<div class = 'md-button l3' is-file ng-model = 'picture' blob-url = 'snapshot'>Upload</div>
<div class = 'md-button l3' ng-click = 'article.pictures.push(picture)'>Add</div>   

<div gallery-manager = 'article.pictures'></div>

Below, the directives:

.directive("galleryManager", function($compile){
        var controllerFn = function($scope, $element, $attrs){
            var self = this;        
            self.removeItemAt = function($index){
                self.pictures.splice($index, 1);
                $compile($element)($scope); <--Note this
            }
        }
        var linkFn = function($scope, $element, $attrs){
        }

        return {
            template:"<div gallery-item = 'picture' ng-repeat = 'picture in galleryManagerCtrl.pictures track by $index'></div>",
            restrict:"A",   
            controller:controllerFn,
            controllerAs:"galleryManagerCtrl",
            bindToController:{
                pictures:"=galleryManager",
            }
        }
    })
    .directive("galleryItem", function(FileService){
        var linkFn = function($scope, $element, $attrs, galleryManagerCtrl){
            $scope.galleryItemCtrl.galleryManagerCtrl = galleryManagerCtrl;
        }
        var controllerFn = function($scope, $element, $attrs){
            var self = this;
            if ( self.item instanceof File ){
                FileService.buildBlobUrl(self.item).then(function(blobUrl){
                    self.thumb = blobUrl;
                })
            }
        }
        return{
            template:"<img src = '{{galleryItemCtrl.thumb}}'>"+
                "<a class = 'delete' ng-click = 'galleryItemCtrl.galleryManagerCtrl.removeItemAt($index)'>&times</span></a>",
            restrict:"A",
            require:"^galleryManager",
            link:linkFn,
            controller:controllerFn,
            bindToController:{
                item:"=galleryItem",
            },
            controllerAs:"galleryItemCtrl"
        }
    })

Right now, the directive is working well when adding elements, but problems come when removing items; before using: $compile($element)($scope) after the deletion, in the gallery, always dissapeared the last item, although the pictures array removed the correct item, so I added the $compile line after deleting an item.

The problem is that, although the gallery now does what I want to, it keeps throwing an error after compiling (post the full trace, maybe it can help someone):

angular.js:13920 TypeError: Cannot read property 'insertBefore' of null
    at after (http://localhost/www/project/admin/bower_components/angular/angular.js:3644:13)
    at JQLite.(anonymous function) [as after] (http://localhost/www/project/admin/bower_components/angular/angular.js:3728:17)
    at domInsert (http://localhost/www/project/admin/bower_components/angular/angular.js:5282:35)
    at Object.move (http://localhost/www/project/admin/bower_components/angular/angular.js:5488:9)
    at ngRepeatAction (http://localhost/www/project/admin/bower_components/angular/angular.js:29865:26)
    at $watchCollectionAction (http://localhost/www/project/admin/bower_components/angular/angular.js:17385:13)
    at Scope.$digest (http://localhost/www/project/admin/bower_components/angular/angular.js:17524:23)
    at ChildScope.$apply (http://localhost/www/project/admin/bower_components/angular/angular.js:17790:24)
    at HTMLAnchorElement.<anonymous> (http://localhost/www/project/admin/bower_components/angular/angular.js:25890:23)
    at defaultHandlerWrapper (http://localhost/www/project/admin/bower_components/angular/angular.js:3497:11)

That seems to come from watchCollection at ngRepeatDirective.

I have the feeling that I´m missing something basic, but can´t see what is right now, so, here I come to ask before digging into angular code.

Thank you in advance.

EDIT

Added a working sample: http://codepen.io/sergio0983/pen/rMEMoJ?editors=1010

EDIT 2

Removed $compile from working sample, it makes it work, yes, but throws errors; and besides, I think the real problem is elsewhere. In the working sample, you can see how file names get updated when you delete an item, but the pictures keep their original order.

解决方案

  1. add addPicture() function to your mainController (which will add constant unique ID ro the picture object):

    .controller("mainController", function($scope){
      $scope.article = {pictures:[]};
      $scope.addPicture = function addPicture (picture) {
        // set unique ID
        picture.id = $scope.article.pictures.length;
        $scope.article.pictures.push(picture);
      };
    })
    

  2. change add button HTML to:

    <div class='md-button l3' ng-click='addPicture(picture)'>Add</div>
    

  3. change template of galleryManager to track by picture.id:

    <div gallery-item='picture' 
         ng-repeat='picture in galleryManagerCtrl.pictures track by picture.id'></div>
    

  4. modify removeItemAt() function, ($compile not needed here):

    self.removeItemAt = function removeItemAt (id) {
      // find index for the picture with given id
      id = self.pictures.findIndex((item) => item.id === id);
      self.pictures.splice(id, 1);
    }
    

    modified codepen: http://codepen.io/anon/pen/mrZOre?editors=1010

这篇关于从父指令删除子指令时,ngRepeat错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆