How to access the parent array element in a nested ng-repeat in AngularJS

Hey there, I'm facing a bit of a puzzle with a seemingly simple question that's got me stumped.

In my code, I have a nested array structure:

$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: []
                }]
            }]
        }]
    };

This data is displayed using ng-repeat and everything works smoothly, including the sorting functionality implemented with ng-sortable (using JQuery UI Sortable).

Now, here's where I need your help - I'm trying to duplicate an item with ID: 5 using angular.copy().

The HTML setup:

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

The duplication process seems to be working well, as I can pass the object to the function without any issues. However, when I attempt to push the duplicated object into its parent's array, I encounter a problem where $parent.ngModelItem.items is returning as undefined.

Here's the controller code:

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

        parent.push(item);
    };

And this is how the HTML with ng-repeat looks like:

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

Despite my attempts to pass the parent's ngModelItem.items (rootItem.items), it appears Angular has different ideas on how this should work. So, the big question remains - how can I successfully access the parent's ngModelItem.items array?

I would appreciate it if someone could explain why

{{$parent.$parent.ngModelItems.id}}
returns the correct parent ID, but when I try to pass that parent to the function like

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

It doesn't seem to work as expected.

Below is the directive code snippet for reference:

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;
                    });
                }
            };
        }
    ]);

Answer №1

After spending a few hours troubleshooting and researching various resources on $scope inheritance, I discovered that ng-if creates a new scope using prototypical inheritance. This was something I had not taken into consideration.

This realization prompted me to add an additional $parent when passing it to the function like this:

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

In the controller, I then implemented the following solution:

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

I hope this information can help someone save valuable time and effort if they encounter a similar issue in the future.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to create a universal getter/setter for TypeScript classes?

One feature I understand is setting getters and setters for individual properties. export class Person { private _name: string; set name(value) { this._name = value; } get name() { return this._name; } } Is there a w ...

What is the best way to trigger a function when a button is enabled in Angular 8?

Here is a portion of my sign-in.component.html file. I have created a function in the corresponding sign-in.component.ts file that I want to trigger when the button below becomes enabled. Here is an example of what I am trying to achieve: <div class= ...

I seem to be facing some difficulty in dynamically calling my buttons in AngularJS

Can you assist me in solving this problem? I am new to Angular and just starting out. Initially, there is only one button on load called "Add list". When the user clicks on this button, they are able to add multiple lists. Each list contains a button labe ...

What causes the jQuery mouseenter events to be activated in a random sequence?

I currently have a setup of 3 nested divs, resembling the concept of a Matryoshka doll. Each div has a mouseenter event function bound to it. When moving the mouse slowly from the bottom and entering layer three, the events occur in the following sequence ...

Retrieving the total count of data entries from the JSON server endpoint

Working on a practice application with the JSON server serving as the backend, I have a question. Is there a way to determine the total number of records at an endpoint without actually loading all the records? For example, if my db.json file contains da ...

As the cursor moves, the image follows along and rotates in sync with its

Can anyone help me figure out how to create a moving image that follows the mouse cursor? I have a radial pie menu with an image in the middle, and I want it to spin and rotate as the mouse moves. Any ideas on how I can achieve this effect? I would greatl ...

What is the best way to make a select tag read-only before the Ajax request is successful

Is there a way to make a select tag read-only before an Ajax success? I tried using this code, but it didn't work: $("#tower").prop('readonly', true); Then I tried this alternative, but I couldn't get the value from the select tag: ...

jquery dialog box displaying a webpage

I am looking to implement a feature where, upon clicking the edit link in the last column of my dataTable, a separate page for editing should open within a jQuery dialog box. The goal is to seamlessly submit data while providing a user-friendly experienc ...

What is the best method for choosing a parent and child JSON pair dynamically in PHP?

I've got some JSON data that looks like this: { "Meta Data": { "1. Information": "Monthly Prices (open, high, low, close) and Volumes", "2. Symbol": "AAPL", "3. Last Refreshed": "2017-05-31", "4. Time Zone": "US/Ea ...

Code in JavaScript using VueJS to determine if an array includes an object with a certain value in one of its elements

I have a scenario where I need to address the following issue: I have an Object with a property called specs. This property consists of an Array that contains several other Objects, each having two properties: name value Here is an example of what my o ...

Retrieve the user_id without triggering any route

Is there a way to access the logged in user data without needing to make a request to any route or endpoint? //for example, how can I retrieve the id of the logged in user here? router.get('/',function(req,res,next){ //typically we would acce ...

Streamlining the code

Below is the code that I am working with: $j(document).ready(function(){ $j('#uang').on({ focus: function(){ var ini = $j( this ); var theVal = accounting.unformat( ini.val() , ',' ); var ...

Retrieving values from all fields in a dynamic form using VuejsLet's say

In the process of developing an admin panel using Vuejs and tailwind CSS for managing exercises on a page, I have encountered some challenges. My current objective is to insert the dynamic form values into a Firebase real-time database. However, I am stru ...

External variable accessing the getjson function

I have a question about optimizing the usage of the title variable within the getJSON function. Here's a sample code snippet that I'm working with: for (var x = 0; x < temp_addresses.length; x++) { var title = temp_addresses[x].title; ...

How to pass a variable or value through the async await API in the Vue.js and Laravel integration?

I'm facing an issue with my API where I want to check if a given email exists in the database, but every time I run it and view the console log, it returns undefined. Can anyone here suggest a better code snippet or approach for this? I specifically w ...

Organizing the directory layout for the /profile/username/followers route in NextJs

I want to set up a folder structure for my website that can accommodate the URL /profile/username/followers, where the username will be different for each user. The proposed folder structure is as follows: pages -- profile -- [username].js Curren ...

While the Mongoose aggregate query is functioning properly in MongoDB, I am encountering difficulties in converting it to a Mongoose

Here is the JSON structure provided: [{ "_id" : ObjectId("626204345ae3d8ec53ef41ee"), "categoryName" : "Test Cate", "__v" : 0, "createdAt" : ISODate("2022-04-22T01:26:11.627Z"), "items" : [ { ...

Is it possible to implement a custom radio tab index without using JavaScript

Is it possible to apply the tabindex attribute on custom radio buttons, hide the actual input element, and use keyboard shortcuts like Tab, Arrow Up, and Arrow Down to change the value? Check out this example on StackBlitz ...

I keep encountering multiple errors on my angularjs application without understanding the reason behind their occurrence

While working on my Angular app, I made a few changes and now I'm encountering an error that I can't quite figure out. Error: TypeError: a is not a function at angular.min.js:70 at m.promise.then.u (angular.min.js:97) at m.promise.then.u (angula ...

Ways to obtain data in JavaScript function from HTML

Struggling to pass the key from a database query in HTML using PHP to a JavaScript function? You're not alone. The challenge lies in passing the field_id to the updateRecords() JS function through the onClick() event of an HTML button. Previously, se ...