Tips for binding a function dynamically to ng-click by using the function expression stored in the model

I've incorporated the code below into my Angular template to create a button bar containing Font Awesome icons:

<li 
    data-ng-repeat="btn in navigation.buttonBar" 
    data-ng-click="{{ btn[1] }}"
    class="btn btn-default" style="font-size: 30px; vertical-align: middle;"
    tooltip-placement="bottom" tooltip="{{ btn[2] }}">
        <i class="fa {{ btn[0] }}"></i>
</li>

navigation.buttonBar consists of the following array groupings:

[
    [ "fa-minus", "less()", "Display fewer cloud buttons." ],
    [ "fa-plus", "more()", "Show more cloud buttons." ],
    [ "fa-minus-square", "smaller()", "Reduce size of cloud buttons." ],
    [ "fa-plus-square", "bigger()", "Enlarge cloud buttons." ],
    [ "fa-bars", "toggleShowStrings()", "Switch on/off matching strings display." ],
    [ "fa-refresh", "initialize();", "Load additional content." ],
    [ "fa-undo", "resetQuery()", "Clear search query." ]
]

While the text and icons appear correctly, the buttons themselves are nonfunctional. Inspecting the element reveals that btn[1] has been expanded properly. What is the correct replacement for {{ btn[1] }} to ensure proper functionality?

Answer №1

It is not possible to assign a function expression as a string directly from a binding. Attempting to use interpolation will result in a syntax error, and using it as a binding is also not effective. Instead, consider utilizing $parse and implementing something like the following:

app.controller('MainCtrl',['$scope', '$parse', function($scope, $parse) { //<-- inject parse
    //.. Some code

    //Set up this function as the handler for ngClick by passing the function name you have in your model
    $scope.callFunc = function(exp){
       $parse(exp)($scope); //Parse the function name to get the expression and invoke it on the scope
    }
    //Define your specific functions to be called
    $scope.less = function(){
      console.log('less');
    }
    $scope.more = function(){
      console.log('more');
    }

In your view, include:

     data-ng-click="callFunc(btn[1])"

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $parse) {
  $scope.navigation = {buttonBar:[
    [ "fa-minus", "less()", "Show fewer cloud buttons." ],
    [ "fa-plus", "more()", "Show more cloud buttons." ],
    [ "fa-minus-square", "smaller()", "Make cloud buttons smaller." ],
    [ "fa-plus-square", "bigger()", "Make cloud buttons bigger." ],
    [ "fa-bars", "toggleShowStrings()", "Toggle display of matching strings." ],
    [ "fa-refresh", "initialize();", "Load more content." ],
    [ "fa-undo", "resetQuery()", "Clear query." ]
]};

  $scope.callFunc = function(exp){
    $parse(exp)($scope);
  }
  
  $scope.less = function(){
    console.log('less');
  }
  
  $scope.more = function(){
   console.log('more');
  }
});
    <link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0c6d626b79606d7e22667f4c3d223e2274">[email protected]</a>" src="https://code.angularjs.org/1.2.25/angular.js" data-semver="1.2.25"></script>


  <div ng-app="plunker" ng-controller="MainCtrl">
     <i>Click the first 2 buttons and check the console</i>
    <ul><li 
    data-ng-repeat="btn in navigation.buttonBar" 
    data-ng-click="callFunc(btn[1])"
    class="btn btn-default" style="font-size: 30px; vertical-align: middle;"
    tooltip-placement="bottom" tooltip="{{ btn[2] }}"
><i class="fa {{ btn[0] }}"></i></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

Retrieving error messages and status codes using Laravel and JWT authentication

One of the challenges I'm facing is implementing JWT Auth in my Laravel + Vue SPA. When checking the credentials in my Controller, the code looks like this: try { if (!$token = JWTAuth::attempt($credentials)) { return response()- ...

The mesh takes on a more defined geometric shape once it has been processed using ThreeCSG

When I use ThreeCSG to subtract one mesh from another, I encounter a problem. The main mesh is a ring and the mesh to subtract is a diamond. Initially, the scene looks fine: Mesh fine. However, after subtracting the meshes, the ring become angular: Mesh Br ...

Contrasting actions observed when employing drag functionality with arrays of numbers versus arrays of objects

Being a newcomer to D3 and JavaScript, I'm hoping someone can help me clarify this simple point. I am creating a scatter graph with draggable points using code that closely resembles the solution provided in this Stack Overflow question. When I const ...

AngularJS failing to override default form submission using $compile

When passing a form to $('#some-div').append($compile($('#my-form').html())(scope));, I am having trouble with Angular not suppressing the default form submit behavior, which results in the page refreshing. I suspect that this issue is ...

Exploring React's Suspense feature in an unconventional way without relying

Up until this point, my understanding is that React Suspense relies on promises to manage asynchronous rendering and fallback rendering can be accomplished with React.lazy for dynamic imports. However, I have come across information suggesting that Suspe ...

Comparing node.js timer functions: cron.js versus setInterval

I have a requirement to execute multiple scripts every hour or every 30 minutes, with the ability to control them (restart, stop, and start). Currently, I am utilizing cron.js for this task. However, I am curious if there would be any performance variation ...

Child directive of AngularJS fails to initiate when parent directive is using templateUrl

Feeling a bit weary of data grid initialization code, I have decided to experiment with AngularJS. My idea is to define my data grid inline like this: <grid src="http://my/web/service" page-size="10"> <column name="one" label="My First Column ...

Troubleshoot: Why is my AngularJS bootstrap.ui modal failing to

I am experiencing an issue with displaying a modal dialog using AngularJS bootstrap.ui. After calling $modal.open(...), the screen grays out, the HTML from my templateUrl is fetched from the server, but the modal does not appear. When I click on the gray a ...

Include two arguments when making a $http POST request

I am facing a situation where a single property can have multiple images, but each image can only be assigned to that one property (one-to-many relationship with propertyId as foreign key). In the HTML, I am fetching the propertyId and passing it along wi ...

Incorporate a PHP variable into JavaScript

class Map { public $Id; public $longitudes; public $latitudes; public $lat_init; public $lng_init; public static function createMap($Id){ global $latitude, $longitude; $dbh = Database::connect(); $query = "SELECT * FROM `cartes` WHERE Id=? "; ...

Transform the object's structure into an array

I've been attempting to modify the format of this object for quite some time: "Obj":{"0":"value1","1":"value2"} My desired output should be like a basic array: "Obj": ["value1","value2"] Is there an easy method to achieve this transformation? App ...

Rails assets folder is not directed to the specified directory in the layout file

I have a dilemma in the application layout where I'm referencing assets (js, css, and img) in the public/assets/... directory. For example: <link href='assets/images/meta_icons/apple-touch-icon-144x144.png' rel='apple-touch-icon-pre ...

Having trouble querying with the dynamic ID field in the mongoose function(req, res, next, id) for MongoDB

Utilizing mean js technology, my goal is to query mongodb through a Service call in angularjs. var Priority = 'Left_VM_P'; url = currentUrl+"/api/queryPrioritySearch/"+Priority; The query only functions properly when Property.find({ L ...

"Standard" approach for a Date instance

During my time in the Node REPL environment, the following output was displayed: > console.log(new Date()) 2023-08-15T09:21:45.762Z undefined > console.log(new Date().toString()) Sun Aug 15 2023 09:21:50 GMT+0000 (Coordinated Universal Time) undefine ...

Utilizing ui-router to resolve dynamic parameters

I'm facing a dilemma that seems simple but has me stumped. Despite searching through documentation and looking for solutions online, I can't seem to figure it out. My goal is to define a state in $stateProvider where the server URL I need to acce ...

Arrange the objects in the array according to the specified items that should come after

Consider the following data structure: var set = [ { "name":"alpha", "require":[] }, { "name":"beta", "require":["echo"] }, { "name":"charlie", "require":[] }, { "name":"d ...

What is the best way to automatically add a date and timestamp to every new entry?

I am currently working on a project that utilizes AngularJS and Ionic frameworks. The main feature of the project will involve users inputting data to create a list, and allowing any user to comment on each item in the list. One challenge I have encounter ...

Expanding form fields dynamically with AngularJS

I am currently working on a form that allows users to click a '+' sign in order to add new lines. I've set up a function to be called when the button is clicked, which should push a new line into the array. However, for some reason the new l ...

Using setInterval to update the content of a Text Area continuously

I am currently working on a script that involves extracting a string from a textarea, breaking it down into an array using the delimiter "=====\n", and then displaying each element of the array in the textarea every 250ms. However, I have noticed that ...

The smartcard node encounters an SCardConnect error when attempting to scan the card, followed by an SCardListReaders error upon disconnect

I am currently utilizing both angular and electron, and everything was functioning properly in the past. However, I am now encountering this error: Error: SCardConnect error: SCardConnect error: The smart card cannot be accessed because of other connecti ...