Creating an Angular directive that shares a single scope while displaying multiple behaviors

I am facing a specific scenario with my directive where the refresh scope needs to be either an object or a function. How can I properly assign this to my directive?

1. Initial scenario

<!--HTML-->
<directive 
  refresh="vm.refresh">
</directive>

//JS
scope:{refresh:"="}

2. Alternative scenario

<directive 
  refresh="vm.refresh(search)">
</directive>

//JS
scope:{refresh:"&"}

3. My current situation

<directive 
  refresh="vm.refresh or vm.refresh(search)">
</directive>

//JS - Unsure what to do, need assistance
scope:{refresh:"=&needHelp"}

However, I require both of these functionalities in my directive. So how can I segregate and differentiate between an object and a function within the link function of the directive?

Answer №1

This situation can be quite complex. If you encounter this scenario, it is important to examine the type of expression stored in the refresh attribute. To achieve this, manual parsing of the attribute value using the $parse service is necessary.

.directive('customDirective', function($parse) {
  return {
    scope: {
      // other bindings go here - isolated scope
    },
    template: '<button ng-click="runTest()">Run Test</button>',
    link: function(scope, element, attrs) {

      // parse the attribute expression (not yet evaluated)
      var callback = $parse(attrs.refresh);

      scope.query = 'Sample query';

      scope.runTest = function() {

        // when a refresh is needed: evaluate the refresh callback
        var evaluated = callback(scope.$parent, {query: scope.query});
        if (typeof evaluated == 'function') {
          evaluated(scope.query);
        }
      };
    }
  };
})

If the situation involves

refresh="vm.triggerRefresh(query)"
, using
callback(scope.$parent, {query: scope.query})
will work effectively. However, if the evaluation results in a function, indicating a case like refresh="vm.triggerRefresh", the code enters the if block and executes the function with the required parameter.

Check out the live demo: http://example.com

Answer №2

To assess the scope variable, you can utilize expression binding and inspect the $attrs object to identify its type. Take a look at the example below...

JSFiddle: http://jsfiddle.net/g4bft6rL/

JavaScript

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

myApp.directive('myDirective', function() {
    return {
        restrict: 'E',
        scope: {
            refresh: '&'
        },
        controller: function ($scope, $attrs) {
            $scope.$watch('refresh', function (prev, curr) {
                $scope.text = 'refresh is a ' + getExpressionType($attrs.refresh);
                $scope.value = $scope.refresh();
            });
        },
        template: "result: {{ text }} = {{ value }}"
    };

    function getExpressionType (expression) {
        // simple logic for illustration
        return expression.slice(-1)[0] === ')' ? 'function' : 'object';
    }
});

function MyCtrl($scope) {
    $scope.refresh = { a: 1 };
    $scope.refreshFn = function what (arg) {
        return {
            value: arg
        };
    };
    $scope.param = 123;
}

HTML

<div ng-controller="MyCtrl">
  <my-directive refresh="refreshFn(param)"></my-directive>
  <my-directive refresh="refresh"></my-directive>
</div>

Answer №3

If you want to experiment with an approach similar to the one below, keep in mind that I have not actually tested this code, but it should give you a general idea.

<directive update="updateFromExternal" filter="externalFilterString">" </directive>

The value of updateFromExternal can either be a string or a function. Within the directive's controller:

 return {
        restrict: 'EA',
        scope: {
            name: '=',
          update:'=',
          filter:'@'
        }, 
        controller:function($scope){
            console.log($scope);
          if(angular.isFunction($scope.show)){
            alert('is Function');
            $scope.update($scope.filter || '');
          }
          else{
            alert($scope.update + 'as string');
          }
        },
        template: '<div>Some template</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

Deciphering a JSON Array in JavaScript to extract specific components

I have a brief snippet for a JSON array and a JavaScript function that currently returns a single argument: <!DOCTYPE html> <html> <body> <h2>JSON Array Test</h2> <p id="outputid"></p> <script> var arrayi ...

Executing Code Upon Module Load and Presenting It as Middleware

I am currently delving into the intricacies of how exporting and importing modules function in Nodejs. One of my tasks involves using a specific file to seed a mongodb database. Surprisingly, this file operates flawlessly and delivers the desired results ...

Broadcasting Packets Between Node.js Ports

I have a set of server.js and client.js scripts that work in tandem. Below is the server.js script... var express = require('express'); var appMain = express(); var appReset = express(); var serverMain = require('http').Server(appMain ...

Attempting to bring in HTML through a helper, but Rails doesn't seem too thrilled about it

I have a form that triggers a remote GET request, leading to the display of a modal. The issue I'm facing is that multiple actions can utilize the same model, so I am attempting to employ a helper and jQuery to showcase different data based on what is ...

The specific model cannot be utilized for custom control within the ViewSettingsCustomItem

Exploring examples to enhance my SAPUI5 knowledge, I encountered an unusual behavior when utilizing the ViewSettingsDialog component with a ViewSettingsCustomItem filter. In my controller, I initiate the Dialog in this manner: onOrdersFilterPress ...

Different color for background of division

I am working with a structure that looks like this: <div class="wrapper"...> <a href="#"...>blah</a> <div class="post"...>stuff</div> </div> This structure repeats multiple times on a dynamic page. I am looking f ...

When setValue is called on VCheckbox in Vuetify, it emits an event called "update:modelValue"

After setting a value for the checkbox, I encountered a warning message: [Vue warn]: Component emitted event "update:modelValue" but it is neither declared in the emits option nor as an "onUpdate:modelValue" prop. Example.vue <script setup lang="t ...

Attempting to retrieve the current time using JavaSscript

const currentTime = new Date(); const hours = now.getHours(); Console.log(hours); This block of code is returning an error message... Uncaught ReferenceError: now is not defined Please note that this snippet is written in JavaScript. I attempted to us ...

Divide a string within a JSON object and output it as an array

I've encountered a challenge while working with data received from an API. My goal is to loop through this information and generate HTML elements based on it. The issue lies in the 'subjects' data, which arrives as a string but needs to be m ...

Angular so that the autocomplete field is filled with information retrieved from a PHP URL

I am currently utilizing an autocomplete field that needs to fetch data from a MySQL database based on a PHP (YII2) action. The autocomplete field is currently being populated statically. Below is the code used to populate the autocomplete field: app.cont ...

What is the correct way to display the value "0" using ng-show?

Looking for a way to display a zero value in an Angular UI. <ng-show ng-show="item._source.change.backOrdered"><br> {{'pages.items.backOrdered' | translate}} {{item._source.change.backOrdered}}</ng-show> There are 2 scenarios ...

AngularJS application: the button requires two clicks to activate

In my attempt to develop a simple CRUD app using AngularJS, I encountered an issue. The initial step involves clicking a button that fetches data from a REST API and populates an array. This array is then iterated using ng-repeat to generate Bootstrap card ...

Unusual behavior experienced with raycasting in Three JS when objects are are repositioned

Software Versions THREE.ObjectLoader2: 2.4.1 THREE.LoaderSupport.MeshBuilder: 1.2.1 THREE.LoaderSupport.WorkerSupport: 2.2.0 THREE.WebGLRenderer: 93 THREE.REVISION: 93 Anomalies Discovered During a raycast operation on objects within my scene, I encount ...

Looping through each combination of elements in a Map

I have a Map containing Shape objects with unique IDs assigned as keys. My goal is to loop through every pair of Shapes in the Map, ensuring that each pair is only processed once. While I am aware of options like forEach or for..of for looping, I'm s ...

Next.js pages do not respond to event listeners

Something strange is happening in my Next.js project. I've implemented a header that changes color as the page scrolls using the useEffect hook: The hook in the Header component looks like this: React.useEffect(() => { window.addEventListener(&a ...

Is it more suitable for a library used by getStaticProps to be classified as a normal dependency or a dev

When working with NextJS's getStaticProps, I am implementing a library that is only utilized during build time. Should this library be categorized as a regular or development dependency in my package.json? ...

Is the callback of $.post not being executed until the loop it's contained in finishes?

I'm working on a stock table that allows users to input the quantity of stock to issue. I have a function that verifies whether or not the database has sufficient stock for each entry in the table. When debugging through the code in Chrome, I noticed ...

What is the best method for choosing the next item with jQuery?

I am facing an issue while trying to apply some design on the next element. The error message that I am encountering is: Error: Syntax error, unrecognized expression: [object Object] > label Below are my selections for browsing by category: BROWSE BY ...

Obtain the inner text input value using jQuery

In my form, there is a feature that adds a new row of text inputs dynamically when a user wants to add more rows. Each new row is automatically populated with input fields that have the same id and class as the previous ones. My question is: how can I re ...

It is likely that the variable is out of scope and is undefined

I have a piece of code that retrieves the description of a word in JSON format from website, which is provided by the user in the request JSON body. The issue I'm facing is that I am unable to send back the 'desc' variable in the res.send ...