Angular: bindToController directive mishandles data

I created the actionButtons directive:

function actionButtons(){
    'use strict';
    return {
        scope: {},
        restrict: 'AE',
        bindToController: {
            itemId: '@',
            itemDescription: '@',
            actionsText: '@',
            previewAction: '&',
            previewText: '@',
            editAction: '&',
            editText: '@',
            removeAction: '&',
            removeText: '@'
        },
        controller: ActionButtonsController,
        controllerAs: 'actionButtonsCtrl',
        templateUrl: 'src/views/directives/actionButtons.html'
    };
}

The ActionButtonsController controller associated with it is as follows:

/**
 *
 * @constructor
 */
function ActionButtonsController() {
    'use strict';
    var viewModel = this;
    //not important assertions
    }
    /**
     *
     * @type {boolean}
     */
    viewModel.hasItemDescription = typeof viewModel.itemDescription === 'string' &&
        viewModel.itemDescription.length > 0;
    /**
     *
     * @type {string}
     */
    viewModel.previewText = viewModel.previewText || 'preview';
    /**
     *
     * @type {string}
    ...
url-toggle aria-haspopup="true">
    {{actionButtonsCtrl.actionsText}} <span class="sr-only" data-ng-if="::actionButtonsCtrl.hasItemDescription">
        for {{::(actionButtonsCtrl.itemDescription)}}</span></button>
</div>

This is how I include it in my application:

<td class="col-md-3 col-xs-3 text-center">
    <div data-action-buttons
         data-item-id="{{author.id + '_' + author.name + '_' + author.surname}}"
         data-item-description="{{author.name + ' ' + author.surname}}"
         data-preview-action="authorCtrl.preview(author)"
         data-edit-action="authorCtrl.edit(author)"
         data-remove-action="authorCtrl.remove(author)"
        ></div>
</td>

However, I encountered some issues. For instance, although actionsText and itemDescription are both optional inputs, only actionsText correctly defaults to "Actions" if not specified, while itemDescription always remains visible in the HTML DOM even when not provided. Despite checking the controller code, the value of actionsText appears as undefined at times, causing confusion. I am unsure why this happens and seek assistance in resolving this matter. Thank you for your help. P.S. I attempted to return the viewModel variable from the controller without success. P.S. 2 Notably, specifying actionsText directly (e.g.,

data-actions-text={{'Something'}}
) resolves the issue.

Answer №1

Utilizing bindToController leads to the indirect addition of scope values to the controller's context. However, this issue arises when using the @ symbol within the bindToController expression.

When dealing with controllerAs, bindToController, and scope with @, Angular approaches things slightly differently.

In essence, if you use @ on a scope variable within an isolated scope with controllerAs and bindToController, Angular sets up a watcher using $observe on the specified expression in the attribute value (see Angular code for reference).

The recommended solution is to utilize $timeout for all assignments that fetch values using @ from isolated scope values. This is because the value binds in the subsequent digest cycle after the evaluation of the $observe expression.

Code

function ActionButtonsController() {
    'use strict';
    var viewModel = this;
    $timeout(function() {
        viewModel.hasItemDescription = typeof viewModel.itemDescription === 'string' &&
            viewModel.itemDescription.length > 0;

        viewModel.previewText = viewModel.previewText || 'preview';

        viewModel.editText = viewModel.editText || 'edit';

        viewModel.removeText = viewModel.removeText || 'remove';

        viewModel.actionsText = viewModel.actionsText || 'Actions';
    })

    viewModel.preview = function() {
        viewModel.previewAction();
    };

    viewModel.edit = function() {
        viewModel.editAction();
    };

    viewModel.remove = function() {
        viewModel.removeAction();
    };
};

This provides a more detailed explanation in another answer.

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

Filtering data in AngularJS ui-grid 3.x using an input box

I've implemented the ui-grid and integrated an input box. My goal is to connect this input box to filter the grid column, without relying on the default textbox provided by the ui-grid. Seeking assistance on how to achieve this. Any suggestions? ...

How can we ensure that React state remains unaltered when modifying an array set to state?

Hope you're having a wonderful day! I'm encountering a significant problem with React. I have a state that contains an array. Within a function, I create a copy of the state in a new variable. However, any modifications made to this new variable ...

Why isn't the Angular function being activated by the HTML generated by the datatable?

{ sTitle: "ANSWER_CORRECT", mData:"ANSWER_CORRECT", sClass: "readonly", mRender: function(data, type, obj) { ...

Override existing Keywords (change false to true)

Are there any ways to overwrite reserved words? It's not something I would typically consider, but it has sparked my curiosity. Is it feasible to set false = true in JavaScript? I've come across instances on different websites where individuals ...

Having trouble displaying the image in my administrative tool

I am currently developing an admin application that will showcase uploaded product images stored in a database. The images are saved as object IDs in MongoDB. However, the image container in the admin app shows the count of images stored in the database bu ...

Using grunt to optimize and generate cache manifest

I am currently developing an angular application with the help of grunt and utilizing cache manifest. The issue I am facing is that once all my JavaScript files are concatenated and minified into one file, the manifest.cfm does not update accordingly, lead ...

Refresh the input data post verification

I am just getting started with Vue. I am curious to know if it is possible to automatically update the input value after performing custom validation in Vuelidate. For example, I have an input field for a postcode and I would like to format it correctly i ...

Is there a way to retrieve the original value of the substr value?

I successfully retrieved the correct value using the substr() method, but I am facing difficulty in getting back the original value. Can someone please guide me on how to achieve this? For example: "AAAAAA" -> AA... but I am unable to revert from AA.. ...

confrontation arising between two PHP scripts due to conflicting functionalities within the MetaSlider plugin

Seeking assistance with the WordPress plugin metaslider, specifically involving two code snippets. The first one implements the "ken burns effect" while the second disables the "pause on action" feature. Strangely, the "pause on action" seems to interfere ...

After switching from jQuery to pure JavaScript, the code is now up and

After initially coding in jQuery + AJAX, I attempted to rewrite it in vanilla JavaScript. However, the code is not functioning as expected now. Can someone help me identify the mistake causing nothing to display when I run it through the server? I have che ...

Is it possible to redirect a URL in AngularJS without loading a new page

I'm currently developing a Node.js application that includes a page built with Angular.js. This particular page lists all users as hyperlinks, and clicking on a user's link should allow me to access that specific user's information. My goal ...

JavaScript and PHP open-source libraries for enabling voice chat functionality

Seeking assistance on incorporating voice-chat functionality into my website through PHP and JavaScript. Are there any open-source libraries available for this purpose? I am willing to utilize Flash if necessary, but limited to using only Flash, JavaScri ...

Ways to hide the dropdown when clicking away from the menu in angularjs

Whenever I click on an item, a dropdown menu appears. Clicking again on the item hides the dropdown. But now, I want to make the dropdown disappear if I click anywhere else on the window. Here's the code snippet: <div ng-click="showDropDown()" cl ...

Retrieving MongoDB Query Data in Node API - What is the best way to send the mongoDB query results back to the

As a newcomer to JavaScript, I decided to challenge myself by diving into Node API development, specifically experimenting with querying my MongoDB. In my API's index.js script utilizing the 'express' module, I aim to return query results in ...

Leveraging jQuery within a method defined in an object using MyObject.prototype.method and the 'this' keyword

Recently, I've started exploring Object-oriented programming in JavaScript and have encountered a challenge. I'm trying to define an object like the example below, where I am using jQuery inside one of the methods. I'm curious about the best ...

Module 'git-host-info.js' not found

I am currently working on following the official Angular update instructions provided here from version 6.0 to 7.0. However, I have encountered an error. The error message states that my global Angular CLI version is higher (8.2.2) than my local version ( ...

Ways to convert JavaScript object to hashmap

I am attempting to generate a map of type <String, Array()> from a JSON object. Suppose I have the following JSON structure: [ { "userId": "123123", "password": "fafafa", "age": "21" }, { "userId": "321321 ...

Issue with jQuery Cycle causing images not to load in IE all at once, leading to blinking

When using the jQuery Cycle plugin in IE8 (as well as other versions of Internet Explorer), I am encountering an issue. My slideshow consists of 3 slides, each containing a Title, Description, and Image. The problem arises when viewing the slideshow in I ...

Retrieving JSON information from a PHP script with AJAX

I am currently experiencing an issue with my PHP script, 'getNews.php'. Despite working correctly in the terminal and returning the expected data, I am encountering difficulties when trying to retrieve this information through JavaScript. <?p ...

What can I do to stop a webpage from automatically refreshing when I submit a form?

I'm currently in the process of building my very first website, and I've run into a bit of a snag that I can't seem to figure out. Whenever a user tries to add an item to the cart or increase the quantity, I want to avoid the page refreshing ...