Developing a personalized materialize directive that seamlessly integrates with the dynamic {{expression}} within the data-activates attribute

I am currently experimenting with integrating the materialize library with Angular. I have created an attribute directive to initialize the dropdown menu on an element.

However, I encountered an issue where the directive throws an exception (check the dev tools) when the data-activates attribute uses a double-curly-brace expression. Here is a reproduction of the problem along with a hardcoded working version for reference:

angular.module('foo', [])
  .directive('materialKebab', function() {
    return {
      link: function(scope, element, attrs) {
        $(element).dropdown();
      }
    };
  })
  .controller('bar', function($scope) {
    $scope.id = "abc123";
  });
.dropdown-button { cursor: pointer; background: #ddd; padding: 10px; display: inline-block; font-weight: bold; }
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/css/materialize.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.js"></script>

<div ng-app="foo" ng-controller="bar">
  Doesn't work:
  <div class="dropdown-button" data-activates="item_{{id}}" material-kebab>⋮</div>
  <ul class="dropdown-content" id="item_{{id}}">
    <li>Action 1</li>
    <li>Action 2</li>
  </ul>
</div>
<hr>
<div>
  Hard coded one works:
  <div class="dropdown-button" data-activates="hardCodedId">⋮</div>
  <ul class="dropdown-content" id="hardCodedId">
    <li>Action 1</li>
    <li>Action 2</li>
  </ul>
</div>

The error is coming from jQuery (Sizzle specifically):

Error: Syntax error, unrecognized expression: #item_{{id}}

It seems like the dropdown is being activated too early. I have attempted to set a priority for my directive to ensure it runs after the other attribute has been properly populated, but that did not resolve the issue. I also looked at this Github repo with angular-materialize features, but found no specific solution to this case.

Is there a good workaround for this? Or do I need to watch the $scope.id variable before calling dropdown()?

Answer №1

After some thorough research, I have finally discovered the solution to the problem at hand. Sharing it here in hopes of assisting any other individuals who may come across this issue. Perhaps this answer can also inspire someone to come up with an even better solution?

Upon closer examination, it appears that the question is essentially a mashup of two existing inquiries:

  • How to dynamically set the id attribute of an HTML element using AngularJS?
  • Using Angular expression in a custom (data-, red) attribute

The key is to simply add the ng-attr- prefix to both the data-activates and id attributes as shown below:

angular.module('foo', [])
  .directive('materialKebab', function() {
    return {
      link: function(scope, element, attrs) {
        $(element).dropdown();
      }
    };
  })
  .controller('bar', function($scope) {
    $scope.id = "abc123";
  });
.dropdown-button { cursor: pointer; background: #ddd; padding: 10px; display: inline-block; font-weight: bold; }
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/css/materialize.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.js"></script>

<div ng-app="foo" ng-controller="bar">
  Now does work:
  <div class="dropdown-button" ng-attr-data-activates="item_{{id}}" material-kebab>⋮</div>
  <ul class="dropdown-content" ng-attr-id="item_{{id}}">
    <li>Action 1</li>
    <li>Action 2</li>
  </ul>
</div>

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 reset an object's prototype in typescript after fetching it from local storage?

In my TypeScript class, there is a method called getTotal() defined on the prototype. class Score { roundOne: any; roundTwo: any; roundThree: any; roundFour: any; roundFive: any; roundSix: any; roundSeven: any; getTotal() { ...

Error: the search variable is not defined

function sorting(type) { $("#parentDiv").empty(); $.getJSON("example_data.json", ({ Find })); function Locate(a, b) { return (a[Find.type] < b[Find.type]) ? -1 : (a[Find.type] > b[Find.type]) ? 1 : 0; }; } The example_data.j ...

Converting a PHP multidimensional array to JavaScript

I'm facing an issue with printing data from a PHP array in a JavaScript function. The current setup is not producing the desired outcome. Here's how the data is being processed in PHP: $daten = array(); $anzahl = array(); $leads = array(); if ($ ...

Guide to showing MySQL data on an HTML page using NodeJS

Currently delving into Node JS, I am faced with the challenge of displaying fetched data from my MySQL Table in an HTML table format. Despite my efforts, I have yet to find a solution that works for me. Any help or guidance on how to resolve this issue wou ...

The functionality of jquery.load() seems to be experiencing issues in Internet Explorer when attempting to load an HTML file

Code $('.form').load('http://'+window.location.hostname+':8423/html/form/form_generate.html/?session='+session); In an attempt to load a html file from a different port on the same server. The original server is accessible ...

Is there a way to recover a deleted element from an array?

I have a list of user cards, and my task is: Clicking the "undo" button: will restore the last card that was deleted (using an array) Question 1: How can I create an array from the displayed cards list? Question 2: How do I restore the last deleted card? ...

Tips for creating text that changes size based on the container dimensions

I am looking for a way to ensure that the content within a div container remains neatly contained without overflowing. How can I make the container responsive so that it adjusts its size based on dynamic text? .element { display: inline- ...

Show the value of the chosen checkbox using AngularJS

How can I display the selected checkbox value in a grid table on the same page when the save button is clicked? I have a form with textboxes, select boxes, and checkboxes that I am able to display in the table. However, I am struggling to figure out how to ...

Pausing and resuming WebRTC streams

Currently, I am exploring the integration of WebRTC in developing a web application that requires the ability to pause and resume video/audio streams based on certain events. While I attempted to use getTracks()[0].stop(), I am uncertain about how to res ...

``How can one validate a radio button within a reducer by utilizing the event object that is passed into the reducer process

In my React app, I am using the following reducer: const initialState = { genderRadio : false, ageRadio : false } const reducer = (state = initialState, action) => { switch(action.type) { case "VALI_RADIO_INP": console. ...

Jest encountered an UnhandledPromiseRejection error because the promise was unexpectedly resolved instead of being rejected

I am facing a difficult error message from Jest that I can't seem to figure out. The error message indicates that the promise is being resolved instead of rejected, causing an unhandled promise rejection. It's confusing because Jest expects an er ...

Verify the presence of a specific select option using text in jQuery version 1.7

Looking at the following snippet of HTML: <select id="sel"> <option value="0">Option1</option> <option value="1">Option2</option> <option value="2">Option3</option> <option value="3">Option4</option> & ...

"Exploring Angular: A guide to scrolling to the bottom of a page with

I am trying to implement a scroll function that goes all the way to the bottom of a specific section within a div. I have attempted using scrollIntoView, but it only scrolls halfway down the page instead of to the designated section. .ts file @ViewChild(" ...

Utilizing HTML and Bootstrap to create a collapsible dropdown menu

Is there a way to collapse just the dropdown menu in a navbar into a hamburger icon on small screens, rather than the entire navbar? Example: https://i.sstatic.net/bDxio.png ...

How to locate the "next" span element on a Google search page using selenium-webdriver and Node.js

I'm currently working on setting up a series of tasks using Selenium-Webdriver and NodeJs: Launch Firefox Navigate to Google.com Perform a search in Google Wait for the page to finish loading Select and click on the button to go to the second page. ...

"Utilizing Normalizr to standardize complex nested data structures

I am dealing with a complex nested data structure that looks like this: { components: [ guid: "cms-container/c154c79596b3af6326966b0c994e2a934", regions: [{ guid :"r1c154c79596b3af6326966b0c994e2a934", components: [{ guid: ...

The functionality of the wysiwyg-editor within a jQuery dialog is experiencing issues

As a website editor, I decided to test out various editing tools such as tinyEditor, wysihtml5, and jHTMLArea. Initially, everything seemed to work fine when I only had a textarea-element on my site. However, when I tried integrating the editor into a jQue ...

Can you provide guidance on securing a REST API using Google authentication?

I'm currently working on developing a REST API using NodeJS and Passport for a single-page JavaScript application. I am struggling to find the right approach to securing my REST API with Google OAuth. Can someone guide me on how to achieve this? Any ...

Ways to customize the TextInput component in React-Admin

I am facing a challenge with overriding specific fields in my custom theme. It seems that setting the custom theme also overrides other fields unintentionally. I attempted to use useStyles to resolve this issue, but unfortunately, it did not work as expec ...

What is the proper way to include a directive attribute in an element within the link function?

It is well known that Angular's performance can be affected when there are more than 2000 records on a page, especially if only some of the records require additional behavior. To address this, I prefer dynamically adding attributes to elements based ...