Utilizing an Empty Array within an AngularJS Controller Function Invoked by a Directive

I have encountered a tricky issue that appears to be simple, but I am struggling to find a solution.

Currently, I am developing a to-do list application using Angular and Angular-Material.

The main part of the application is located in a file named main.html:

<md-content ng-show="mainCtrl.todos.length">
   <md-list class="todo_list" flex>
     <md-subheader class="md-no-sticky">{{mainCtrl.todoList.label}}</md-subheader>
       <acme-todo ng-show="mainCtrl.todos" ng-repeat="todo in mainCtrl.todos track by $index"
                  text="todo.content" index="$index"></acme-todo>
   </md-list>
</md-content>

Within this code snippet, you can see the usage of the acme-todo directive, which includes a file named todo.html:

<md-list-item layout='row' layout-sm='column' layout-align='center center' layout-wrap>
    <i class='material-icons md-avatar'>border_color</i>
    <div class='md-list-item-text'><h3>{{mainCtrl.text}}</h3></div>
    <div class='md-secondary'>
        <md-button class='md-fab md-primary md-small box red-btn'
                   aria-label='delete' ng-click='mainCtrl.deleteTodo(mainCtrl.index)'>
            <i class='material-icons small-icon'>highlight_off</i>
        </md-button>
    </div>
</md-list-item>

The logic for the acme-todo directive is defined in todo.directive.js:

(function () {
    'use strict';

    angular
        .module('todoApp')
        .directive('acmeTodo', acmeTodo);

    function acmeTodo() {
        var directive = {
            restrict: 'EA',
            scope: {
                text :  '=',
                index : '='
            },
            templateUrl: 'todo.html',
            controller : 'MainController',
            controllerAs : 'mainCtrl',
            bindToController : true
        };

        return directive;
    }

})();

Additionally, there is a file called main.controller.js, where the main controller functionality lies:

(function () {
    'use strict';

    angular
        .module('todoApp')
        .controller('MainController', MainController);

    function MainController() {

        var vm = this;
        vm.todos = [];

        . . .

        vm.addToDo = addToDo;
        vm.deleteTodo = deleteTodo;

        //vm.todo.content is the ng-model of the input-box
        function addToDo() {
            if( vm.todo && !_.isUndefined(vm.todo.content)){
                   pushNewToDo(vm.todo.content);
            }
        }

        function deleteTodo(index) {
            vm.todos.splice(index, 1);
        }

        function pushNewToDo(todo) {
            vm.todos.push({ content : todo });
            vm.todo.content = '';
        }

    }

})();

Everything works perfectly except when attempting to delete a to-do item. The deleteTodo function receives the correct external $index from the main's ng-repeat, but mysteriously, the vm.todos array is empty at that moment, resulting in nothing being deleted.

If I move all the content from todo.html directly into the place where acme-todo is used, everything functions correctly.

I also tried using $scope : true in the directive instead of passing both text and $index, but the issue persists.

To replicate the problem, here is a working Codepen. In this pen, I substituted template for templateUrl and changed some icons to ensure proper functionality.

Below is an image showing the real application:

https://i.sstatic.net/XY9GE.png

Although directives typically inherit their scope, I am puzzled as to why the todos array is empty despite sharing scope with the controller.

EDIT

Utilizing a Service or a Factory resolves the issue, similar to how it is solved in this CodePen. However, I feel that adding additional logic for such a minor task may be excessive.

Why is the todos array empty even though both the controller and directive share the same scope? How can I rectify this while still using the todo directive approach?

Answer №1

It is recommended to separate the app and directive controllers in order to avoid conflicts. When initializing a directive, a new controller, $scope, and todos array are created locally within the directive. This separation allows for passing functions like the delete function from the main controller to the directive's $scope.

To see an example, visit: http://codepen.io/anon/pen/xXzLPW

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

Express: Every declaration of 'user' must have the same modifiers

In my application, I am utilizing both express and passport. Within these packages, there is a user attribute within the Request interface. Currently, the express package has a user attribute in the request object, such as req.user, but no additional prope ...

What is the best way to attach a button to a mat-drawer?

I am facing an issue with aligning a button to a mat drawer located to the right of the screen to ensure a clear overall design. Check out this example How can I achieve this alignment? My current approach involves placing the button inside the drawer an ...

Create an input element using JavaScript/jQuery

Looking for some help with Javascript on a simple task. When a specific option is chosen, I want to add an input field to a div element. <select name="amount" > <option value="50">50$</option> <option value="100">100$</o ...

In JavaScript, split each element in an array into individual elements

Is there a way to split elements separated by commas into an array in JavaScript? ["el1,el2", "el3"] => ["el1", "el2", "el3"] I am looking for a solution to achieve this. Can you help me with that? ...

What is the best way to refresh or reset a component in VueJs: reloading it or destroying it and loading again?

In my VueJs application, I am using a component called Aplayer (or any similar components) to play audio and manage playlists. However, I am facing an issue where I need to reload the component when I change the playlist without changing the routes. Is th ...

Retrieving information received from an XML HTTP request in node.js

Currently, I am transmitting text data from a textbox to a node.js express server using XMLHttpRequest: var text = document.getElementById("textBox").value; console.log(text); var xmlhttp; if (window.XMLHttpRequest) {// code for IE7+, Fire ...

Exploring the syntax of ReactJS state management with setState

Trying to wrap my head around the following syntax in my React app. I am looking to understand how the code inside setState() works. this.getSomePromise().then( // resolve callback function someImg => this.setState(prevState => ( ...

Passport sessions do not retain persistence

Having some trouble implementing OAuth 2.0 login where the sessions don't persist after authentication is a common issue. Additionally, there seems to be a problem with the app getting stuck in the routes/bnetauth.js file during the redirect in the ca ...

Retrieving Distinct Values in CouchDB

In my database, there are documents that represent different rooms. Each room has properties like "floor" and "hotel", among others. What I need to do is fetch all the floors associated with a specific hotel from the database. Something like getAllFloorsOn ...

When attempting to add an item to an array within a sub-document using Mongoose and MongoDB, the error message "Property 'messages' not found" is returned

I am working with four different models: teacher, student, teacherMessageSchema, and studentMessageSchema. The teacherMessageSchema is a subdocument within the 'teacher' model under the messages: [teacherMessageSchema] property, while the student ...

jQuery eliminates initial div just a single time

Here is a function I have created: function removeDiv() { var topmost = jQuery('.xx'); var totContent = topmost.find('.zz').length; var $target = jQuery('.xx').find('.zz').eq(0); if(totCont ...

When trying to pull a component from Svelte, I receive an error message stating "Selection Range

I'm still relatively new to svelte, so I might be handling things incorrectly. Whenever I attempt to separate my button component, regardless of whether I name the component ./Button.svelte, ./Button, Button.svelte, or try variations with capitalizat ...

What is the best location to include my JavaScript code in WordPress?

Alright, so I've got this world map on one of my WordPress pages and here's an example of the code: <area onmousedown="modifyImage('world_map_01', './images/map/asia.jpg')" onmouseout="modifyImage('world_map_01', ...

Having trouble getting Nodejs Express to render with ejs?

Currently, I am working on a project that involves using express ejs on my node server to render views in a multiview app. I have implemented AngularJS on the client side. The login page is the initial view that should be displayed when the user connects s ...

The process of creating a mind map with blank spaces included

I am working on creating a mapping system that links companies with their logos. The goal is to display these logos on a google-map. While completing the company-logo association map, I noticed that some vessel names contain white spaces, causing a compil ...

Sorting the array in MongoDB before slicing it

Currently, I have a pipeline that aggregates Regions along with their respective countries and sales values. My goal is to obtain the top 5 countries by sales in each region using the $slice method. However, the issue I am facing is that it returns the fir ...

What's the best way to organize a list while implementing List Rendering in VueJS?

Currently, I am working on List Rendering in Vue2. The list is rendering correctly, but it appears ordered based on the data arrangement in the array. For better organization, I need to sort each item alphabetically by title. However, I am facing difficult ...

Converting a boolean value to a boolean type in a CSHTML file

In my cshtml file, I am retrieving the value from the server code. It's a boolean field that returns a boolean value. Order="@Model.OrderModel.IsToday" I attempted to convert it to JSON using @Model.OrderModel.IsToday.ToJson(), but it seems to be tr ...

Troubleshooting node modules for browser compatibility

Looking for assistance with running a specific node module in a browser. The module in question is called fury.js. I attempted to use browserify, however, encountered an error stating "ReferenceError: fury is not defined" when trying to utilize it. In th ...

Guide to correctly selecting <i> tags within a <p> tag using jQuery

I'm attempting to retrieve the text from the i (italic) elements within a paragraph using this code: $('p').each(function(j, element){ if($(element).is("i")){ console.log("The value is: "+$(element).text()); } }); However, ...