Issue: [$compile:multidir] encountered for Component Directive that includes an Attribute Directive

In search of a 'sticky' directive that can trigger the addition of a css class to an element when it reaches the top of a page and also notify the changes in its state, I have declared a scope like { onStickyChange: '&' }. My goal is to utilize this directive within an angularjs component as follows:

<my-component sticky on-sticky-change="$ctrl.onStickyChange(sticky)">
</my-component>

My expectation was for the directive to inform the parent controller about the stick/unstick events of my-component. However, instead I encounter the following error:

Error: [$compile:multidir] Multiple directives [myComponent, sticky] requesting new/isolated scopes on: http://errors.angularjs.org/1.6.2/$compile/multidir?p0=myComponent&p1=&p2=s…icky%3D%22%22%20on-sticky-change%3D%22%24ctrl.onStickyChange(sticky)%22%3E at angular.js:68 at assertNoDuplicate (angular.js:10049) at applyDirectivesToNode (angular.js:9237) at compileNodes (angular.js:8826) at compileNodes (angular.js:8838) at compileNodes (angular.js:8838) at compile (angular.js:8707) at angular.js:1847 at Scope.$eval (angular.js:18017) at Scope.$apply (angular.js:18117)

app.component('myComponent', {
    template: '<div style="height: 6000px; width: 100%; background-color: #ccf></div>',
    controller: function () {
        this.is = 'nothing';
    }
});
app.directive('sticky', ['$window', function($window) {
    return {
        restrict: 'A',
        scope: { onStickyChange: '&' },
        link: link
    };
    function link(scope, element, attributes) {
        if (typeof scope.onStickyChange !== 'function' ) {
            throw Error('Sticky requires change handler');
        }

        let sticky = isSticky(element);

        angular.element($window).bind('scroll', _.throttle(onWindowScroll, 60));

        function onWindowScroll() {
            let isNowSticky = isSticky(element);

            if (sticky === isNowSticky) {
                return;
            }

            sticky = isNowSticky;

            if (sticky) {
                element.addClass('sticky');
            }
            else {
                element.removeClass('sticky');
            }

            scope.onStickyChange({ sticky: sticky });
        }

        function isSticky(element) {
            return window.scrollTop() > element.position().top;
        }
    }

}]);

Can anyone suggest a solution to this issue?

PS: For reference, here is a plunk.

Answer №1

An issue arises because both the component directive and the attribute directive are attempting to establish an isolate scope.

According to the Documentation:

Error: $compile:multidir

Multiple Directive Resource Contention

This error occurs when multiple directives are applied to the same DOM element, resulting in a conflict or an unsupported setup.

Examples of scenarios where incompatible directives are placed on the same element include:

  • Having multiple directives that require an isolated scope.

— AngularJS Error Reference - Error: $compile:multidir

The resolution involves modifying the attribute directive so that it operates without establishing an isolate scope:

app.directive('sticky', function($window, $parse) {
    return {
        restrict: 'A',
        ̶s̶c̶o̶p̶e̶:̶ ̶{̶ ̶o̶n̶S̶t̶i̶c̶k̶y̶C̶h̶a̶n̶g̶e̶:̶ ̶'̶&̶' ̶}̶,̶
        scope: false,
        link: postLink
    };
    function postLink(scope, elem, attrs) {

        //code ...

            ̶s̶c̶o̶p̶e̶.̶o̶n̶S̶t̶i̶c̶k̶y̶C̶h̶a̶n̶g̶e̶(̶{̶ ̶s̶t̶i̶c̶k̶y̶:̶ ̶s̶t̶i̶c̶k̶y̶ ̶}̶)̶;̶
            $parse(attrs.onStickyChange)(scope, { sticky: sticky });

        //code ...
    }
});

Utilize the $parse Service to assess the Angular Expression mentioned in the on-sticky-change attribute.

Answer №2

In Angular, trying to apply isolate scope to the same element with two different directives will result in internal conflicts. To work around this issue, you can use the attrs parameter within your link function to access and manipulate any necessary values without the need for isolate scope.

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

What is the best way to specify the correct content type for different parts of form data when using AngularJS, especially when including file uploads and other form fields?

As demonstrated in a helpful solution here, I have successfully managed to send multipart formdata including both a file and other form fields. However, I noticed that for the other form fields, the content type is missing in the request. The multipart for ...

Offline communication between Android and JavaScript web applications

I'm a newcomer to this whole scenario - I have a JavaScript web app up and running on a Windows 7 machine using Google Chrome, as well as an Android app. I'd like to establish an offline connection between the two to exchange data, keeping in min ...

Show or hide a component based on a mouse click in Vue JS

After a prolonged absence from working with Vue JS, I find myself in the process of displaying a list of data with a button for each item. The goal is to conditionally render a component when a button is clicked. I am wondering if there is a recommended a ...

Having trouble with clearTimeout and clearInterval functions not functioning properly?

Currently, I've set up a countdown using both setInterval and setTimeout functionalities, and it seems to be running smoothly. However, I encounter an issue when trying to stop the countdown upon clicking a certain button; it pauses only after complet ...

Launch a PowerPoint presentation in a separate tab on your web browser

If you have a link that leads to a .pdf file, it will open in a new tab like this: <a target="_blank" href="http://somePDF.pdf">Download</a> But what about a Powerpoint file, such as a .ppt? Is there a way to make it open in a new browser tab ...

What are some ways I can customize this jQuery :submit selector demonstration?

After reviewing the jQuery example provided here, I am curious about how to adjust the code in order to change the color of a cell only when the value of the submit button within that cell meets certain criteria. For instance: var submitEl = $( ...

RxJS - combine transformed items onto a data flow

Is there an operator that allows me to iterate over elements of a stream and concatenate them instead of transforming them? Consider the following stream: A => B => C If I use items$.concatMap(x => f(x)), the result will be: "f(A)" => " ...

Creating a dynamic dropdown in a Rails application using the simple_form gem

In my Rails application, I have a straightforward has_many and belongs_to relationship. Using simple_form, I am looking to dynamically adjust the dropdown options based on the selection made by the user. Models class Processor < ApplicationRecord ...

Using jQuery to select the next table cell vertically

Is there a way to utilize jQuery to access the cell (td) directly below a given cell in a traditional grid-layout HTML table (where each cell spans only one row and column)? I understand that the code below will assign nextCell to the cell immediately to ...

Updating the data and processing results settings for Select2 in an Angular 2 application

In my Angular2 app, I am utilizing Select2 and facing a challenge with accessing class properties in the data and processResults contexts. Unfortunately, these contexts do not belong to the class: export class DefaultFormInputSelectComponent { @Input ...

Retain the jQuery dropdown menu in an open state while navigating to a different webpage on the

I am encountering an issue with a drop-down menu on my website. Whenever I click on a submenu link, the new page opens but the menu automatically closes. However, I want the active menu to remain open even on the new page. To solve this problem, I believe ...

Utilize object property to refine ng-repeat filtering

Here is an array that I have: $scope.athletes= [ { name: 'name 01', measurements: [ { type: 'date' }, { type: 'info', value: 23, rank: 1 }] }, { name: 'name 02', measurem ...

In certain Express app files, the use of Sequelize modules may result in a return value of undefined

Objective - To implement a middleware-like callback in userHandler located in util.js for certain express routes in an express app, created using express-generator and sequelize-cli. Expected Outcome - Utilize the user model successfully in routes and use ...

Having trouble with Visual Studio 2015 not compiling TypeScript within an ASP.NET Core project?

Seeking assistance with my Angular app development setup in VS2015. Even though it is recognized as a TypeScript Virtual Project, I am facing issues getting the transpiled files into the wwwroot folder within my ASP.NET Core project. Here's an overvie ...

Node.js - Error: JSON.Parse and JSON.Stringify are not recognized as functions

Is it possible to convert a string to JSON and vice versa without any additional npm packages? I am currently using JSON.Stringfy in my router.js file. Are there any specific npm modules that need to be added to the project in order to use the JSON.Stringf ...

Choose the div without a class

I currently have several divs displayed on my website. <div class="slide bx-clone"></div> <div class="slide"></div> <div class="slide"></div> <div class="slide bx-clone"></div> <div class="slide bx-clone" ...

Having trouble connecting with Node.js and Express; encountering ERR_CONNECTION_REFUSED

I tried following this basic tutorial: After generating the files as instructed, I ran through all the steps but encountered an issue. Regardless of the browser I used, I kept getting "Unable to connect" in Firefox and "This webpage is not available ... E ...

What is the best approach to generate and organize 100 random numbers in a program, ensuring they are sorted in ascending order from 1 to 100?

I have successfully implemented the sorting and printout functionality of the program. However, I am now facing a challenge in generating 100 random numbers between 1 and 100, sorting them. I have created an array to store the generated numbers, and I ha ...

Fixing the "Unknown error status: Error: The uid provided must be a non-empty string containing no more than 128 characters" issue in Firebase Functions is crucial for seamless performance

In my firebase application, I am attempting to create a new user by transferring data from the UI to a callable function. The process involves: Creating a user account using an email and password. Adding a display name followed by creating a profile in a ...

Is there a maximum size limit for the Fabric.js Path Array?

Has anyone tried plotting a line graph using Fabric.js and encountered issues with the fabric.Path? I've noticed that it stops drawing after 8 segments even though I have attempted different methods like loops and individually coding each segment. co ...