1

Right so I have a dilemma, that seems like a simple question but I can't figure it out.

I have a nested array:

$scope.rootItem = {
        id: '1',
        type: 'course',
        title: 'Adobe Photoshop CC for beginners',
        items: [{
            id: '2',
            type: 'label',
            title:'Label Title',
            items:[{
                id: '3',
                type: 'module',
                title:'Module title',
                items: [{
                    id: '4',
                    type: 'topic',
                    title:'Topic title',
                    items: [{
                        id: '5',
                        type: 'content',
                        title:'Content title'
                    }, {
                        id: '6',
                        type: 'content',
                        title:'Content title'
                    }]
                }]
            },{
                id: '7',
                type: 'resources',
                title:'Resources'
            },{
                id: '8',
                type: 'module',
                title:'Module title',
                items: [{
                    id: '9',
                    type: 'topic',
                    title:'Topic',
                    items: [{
                        id: '10',
                        type: 'question',
                        title:'Question title'
                    }]
                }, {
                    id: '11',
                    type: 'topic',
                    title:'Topic title',
                    items: [{
                        id: '12',
                        type: 'content',
                        title:'Content title'
                    }]
                }]
            }]
        },{
            id: '14',
            type: 'assessmentLabel',
            title: 'Assessment Label',
            items: [{
                id: '15',
                type: 'assessment',
                title: 'Assessment Title',
                items: [{
                    id: '16',
                    type: 'courseAssessment',
                    title: 'Course Assessment Question',
                    items: []
                }]
            }]
        }]
    };

That is outputted using ng-repeat. All works great there, by the way it is also sortable using ng-sortable (based on JQuery UI Sortable).

What I'm trying to do is duplicate lets say id: 5 using angular.copy().

HTML:

<a href="" title="Duplicate Content" data-ng-click="duplicate(ngModelItem, $parent.ngModelItem.items)">
<span class="icon-duplicate"></span>
</a>

That seems to work fine too. I'm able to pass the object to the function.

The problem arises when I try and push that object to its parents array. I read about $parent and what I think would make sense is passing $parent.ngModelItems.items to the ng-click as such:

data-ng-click="duplicate(ngModelItem, $parent.ngModelItem.items)"

Which to me makes sense, pass parents ngModelItem.items (items is array that ID:5 is part of). But I can't figure out why do I get $parent.ngModelItem.items as undefined.

This is my controller:

$scope.duplicate = function(item, parent) {
        var itemCopy = angular.copy(item);

        parent.push(item);
    };

HTML ng-repeat:

<ul class="apps-container" ui-sortable="sortableOptions" ng-model="ngModelItem.items" ng-class="ngModelItem.type">
            <li class="innerCont" ng-repeat="innerItem in ngModelItem.items">
                <tg-dynamic-directive ng-model="innerItem" tg-dynamic-directive-view="getView">
                </tg-dynamic-directive>
            </li>
        </ul>

But angular seems to have different ideas. So I guess my question is how can I pass parents ngModelItem.items (rootItem.items) so that I can access that array?

Can someone please explain why {{$parent.$parent.ngModelItems.id}} returns correct parent id. Yet when I try to pass that parent to the function such as

data-ng-click="duplicate(parent.parent.ngModelItem.items)"

It doesnt work

Directive below:

angular.module('tg.dynamicDirective', [])
    .directive('tgDynamicDirective', ['$compile',
        function($compile) {
            'use strict';

            function templateUrlProvider(getView, ngModelItem) {
                if (getView) {
                    if (typeof getView === 'function') {
                        var templateUrl = getView(ngModelItem) || '';
                        if (templateUrl) {
                            return templateUrl;
                        }
                    } else if (typeof getView === 'string' && getView.length) {
                        return getView;
                    }
                }
                return '';
            }

            return {
                restrict: 'E',
                require: '^ngModel',
                scope: true,
                template: '<div ng-include="templateUrl"></div>',
                link: function(scope, element, attrs, ngModel) {

                    scope.$watch(function() {
                        var ngModelItem = scope.$eval(attrs.ngModel);
                        var getView = scope.$eval(attrs.tgDynamicDirectiveView);
                        scope.ngModelItem = ngModelItem;
                        return templateUrlProvider(getView, ngModelItem);
                    }, function(newValue, oldValue) {
                        scope.templateUrl = newValue;
                    });
                }
            };
        }
    ]);
6
  • can you create a fiddle showcasing your problem Commented Aug 3, 2016 at 10:31
  • Hey Gopinath its very complex to recreate in a fiddle. :( Commented Aug 3, 2016 at 10:38
  • I asked fiddle because I couldn't able to see your code of "ng-repeat" in the above question. Can you paste all necessary code which can be used to reflect your problem Commented Aug 3, 2016 at 10:39
  • Ok, sure no problem at all, 1 second Commented Aug 3, 2016 at 10:44
  • mention your directive code, some problem in directive scoping probably. Commented Aug 3, 2016 at 11:55

1 Answer 1

1

After few hours of trying to fix this, and reading numerous articles about $scope inheritance I found out that ng-if create new scope using prototypical inheritance. Which I was not accounting for.

Which required me to insert one more $parent when passing it to the function as such:

 data-ng-click="duplicate(ngModelItem, $parent.$parent.$parent.ngModelItem)"

and then in the controller do something like this:

$scope.duplicate = function(item, parent) {
        var itemCopy = angular.copy(item);
        var parentArray = parent.items;
        parentArray.push(itemCopy)
    };

Hope this will save someone hours of work, whoever runs into this problem.

Sign up to request clarification or add additional context in comments.

1 Comment

I had $parent.$parent and something must have updated. Adding the third $parent did the trick.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.