AngularJS directive that allows for either a click action to be passed or a ui-router state change to

I have a button (an a tag) that is displayed in multiple locations on my website. It is labeled "View Demo", and sometimes it directs to a demo page using an ui-sref:

<a class="btn btn-primary" ui-sref="hamburger-push" target="_blank">
   View Demo
</a>

This would be easy to turn into a directive, but occasionally it has an ng-click connected to the hosting page's controller:

<a class="btn btn-primary" ng-click="mod.modals.basicMessage()">
  View Demo
</a>

So, I am attempting to create a directive with attributes for each type of link, allowing them to be optional. This way, when using the directive, I can include the relevant attribute:

<view-demo-button clickaction="mod.modals.basicMessage()"></view-demo-button>

or

<view-demo-button linkaction="stateNameToGoTo"></view-demo-button>

To clarify, the button should be able to do either

  1. Invoke a function on the host controller, or
  2. Use $state.go in the host controller.

However, I am having trouble implementing this correctly. My template looks like this:

<div class="view-demo" >
  <a class="btn btn-primary" ng-if="ctrl.hasLink" ui-sref="{{ctrl.linkaction}}" target="_blank">
    View Demo
  </a>
  <a class="btn btn-primary" ng-if="ctrl.hasClick" ng-click="{{ctrl.clickaction}}" target="_blank">
    View Demo
  </a>
</div>

The directive code is as follows:

(function () {
  'use strict';

  angular.module('app').directive('viewDemoButton', function () {
    return {
      restrict: 'E',
      scope: {},
      bindToController: {
        'linkaction': '@?',
        'clickaction': '@?'
      },
      replace: true,
      templateUrl: 'core/directives/pb-view-demo-button.template.html',
      controller: function ($state) {
        var _this = this;

        _this.hasLink = _this.linkaction || false;
        _this.hasClick = _this.clickaction || false;


      },
      controllerAs: 'ctrl'
    };
  });
})();

I am not sure if this approach is correct or if this type of implementation even works.

I have created a Plunker showcasing the current non-functional state of the project.

Answer №1

The view-demo-button directive can be transformed into a more concise component structure:

  app.component('viewDemoButton',{
      bindings: {
        'linkaction': '@?',
        'clickaction': '&?'
      },
      controllerAs: 'ctrl',
      template: `
         <div class="view-demo" >
           <a class="btn btn-primary" ng-click="ctrl.viewDemoClick()">
              View Demo
           </a>
         </div>`,
      controller: function ($state) {
        var _this = this;

        _this.viewDemoClick = function () {
          console.log("viewDemoClick invoked");
          if (_this.clickaction) {
            _this.clickaction();
          }
          if (_this.linkaction) {
            $state.go(_this.linkaction);
          }
        };
      }
  });

Implement the component template to execute a function in the component controller and respond accordingly to the attributes of the component element.

Check out the live demo on PLNKR

Answer №2

Implement the & binding within your scope to ensure it functions as a callback. This is similar to how the ng-click directive operates.

  bindToController: {
    'linkhandler': '&?',
    'clickhandler': '&?'
  },

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

Creating a Class in REACT

Hello fellow coding enthusiasts, I am facing a minor issue. I am relatively new to REACT and Typescript, which is why I need some assistance with the following code implementation. I require the code to be transformed into a class for reusability purposes ...

Removing the navigation button from the hamburger menu

I am working on creating a semi-progressive top navigation bar. For the mobile viewport, the navigation bar will only display the logo and a hamburger button. When the button is clicked, various navigation menu options as well as the Log In and Sign Up bu ...

Action of the Floater Button in Material UI

I'm currently working with Material UI's floater button component and I am having trouble getting it to open a menu onClick as intended. It is frustrating that there are no example codes available that demonstrate how to make the menu appear when ...

How can a reusable ng-pattern be written in AngularJS?

I need to validate multiple fields in my application as valid French phone numbers. How can I efficiently reuse the regular expression for multiple input fields without repetitive copy and paste? Also, how can I localize the regex for easier management? ...

JavaScript Elegance: Error Encountered - Unable to Locate Property 'index of' of an Undefined Value

As I delve into learning JavaScript through Eloquent Javascript, I encountered an error in one of the chapters that has me stumped. The error message "Cannot read property 'indexOf' of undefined" is appearing with this line of code: re ...

Extending fabric.js toObject with custom properties can result in the loss of default properties

After doing extensive research on various platforms, including this one, I am still struggling to get everything working as desired. My main goal is to save custom properties in all shapes, specifically the uuid and rt_attributes. Following the manual, I ...

What is the best way to implement or disable a function when toggling a switch in pure JavaScript?

I'm currently facing an issue with my transliteration function that is supposed to be executed only when the checkbox is checked. The problem is, even after unchecking the checkbox, the function still continues to run. const checkBox = document.que ...

during implementation of ng-repeat directive with JSON dataset

When I receive JSON data and attempt to display it using the ng-repeat directive, I encounter an error ng-dupes error <table> <tr ng-repeat="emp in empArr"> <td>{{emp.empcode}}</td> <td>{{emp.empName}}< ...

Displaying properties of a class in Typescript using a default getter: Simplified guide

Here is an interface and a class that I am working with: export interface ISample { propA: string; propB: string; } export class Sample { private props = {} as ISample; public get propA(): string { return this.props.propA; } public se ...

Error occurs when attempting to reference an object from an NPM package

Currently, I'm attempting to utilize the https://github.com/iamcal/js-emoji library for colon-to-emoji conversion. Following the installation of its NPM package, I included <script src="../node_modules/emoji-js/lib/emoji.js" type="te ...

Using Angular and ASP.NET for image uploading functionality

Trying to source the image from the PC and upload it into the database as "Images/aaa.jpg". I am relatively new to Angular and have attempted an example that did not work for me. I have been stuck on this issue for almost 3 days trying to find a solution. ...

How to create a fresh factory instance in Angular Js

I have implemented a factory in my application to retrieve a list of folders and display it on the front end. Additionally, I have a form on the front end where users can add new folders to the existing list. After adding a folder, I need to refresh my fac ...

Converting an array into JSON format in JavaScript without duplicate curly braces

Having two parallel mysql queries in node js is meant to retrieve data more efficiently. The following javascript code reads from a mysql database and stores the results in a javascript object: async.parallel({ aaChannelsCount: function(cb) { /* G ...

Passing a list variable to JavaScript from Django: A step-by-step guide

Currently, I am facing an issue while attempting to generate a chart using Chartjs and Django. The problem arises when transferring data from views.py to the JavaScript code. Here is a snippet of my code in views.py: def home(request): labels = [&quo ...

Leveraging the power of async to streamline the serialization of operations with numerous layers of callbacks in Node

I'm relatively new to working with node.js and I'm encountering difficulties in understanding callback functions. The issue arises when I need to execute a series of complex operations that involve a lot of code divided into modules with numerous ...

Retrieving values from nested arrays in Vue.js

I'm currently delving into Vue3. My goal is to extract the values from an array within an array in order to create a neat table. Once extracted, I plan to separate these values with commas. For more information, you can visit this link: https://stack ...

Upon initial page load, React JS is unable to fetch the data but it functions correctly when triggered by a click

Here is the code I am working with: var CommonHeader = require('./header/CommonHeader.jsx'); var ListOptions = require('./header/ListOptions.jsx'); var SortableTable = require('../shared/SortableTable.jsx'); var ColumnDefinit ...

Increasing the variable by 1 in PHP will result in the variable value being incremented to 1

My issue involves incrementing a variable in my .php file code that changes the value in the database. After incrementing the acc_points variable by one, it updates the data in the MySQL database and then returns the data to the JavaScript, which alerts th ...

The module 'react/lib/React' could not be located within the file 'ReactTestUtils.js'

Setting up unit-tests for a React Native project using ReactTestUtils is causing an issue with npm test. The error message I receive is: Cannot find module 'react/lib/React' from 'ReactTestUtils.js' I suspect that my dependencies are ...

Using a JavaScript variable within an AngularJS scope

Currently in the process of building a webpage with the MEAN stack, I utilized the HTML5/Javascript sessionStorage variable to store the user data for access across all pages. Now, the challenge is passing this data into angularJS through the controller w ...