Pregunta

I have some logic I would like to wrap up into an AngularJS factory so I can use angular's dependency injection. Since the logic is dynamic I don't necessarily know what is available to call ahead of time. What I have is a string representing the name of the function to call. I know I can do something like window["someFunctionName"]() to run a function with a string but since everything is wrapped up in a factory I'm not sure how to get reference to the factory to call it. ex. sampleFactory["someFuncitonName"]();

The only way I have found to run the function is using eval("someFuncitonName()"). Obviously I would like to avoid using eval if I can.

Here is an example of what I'm trying to do:

'use strict';

angular.module('testApp')
  .factory('testFactory', function (someData) {

    // User defined code that was wrapped up in a factory
    function foo() {
        someData.amount = 5;
    }
    // End dynamic code

    return {
      funcRunner: function(functionName) {
        testFactory[functionName]();
      } 
    };

  });

In the controller the user would run something like this testFactory.funcRunner("foo");.

Is there some way to do something along these lines testFactory[functionName]();? Is there some better way of doing this? Thanks for your help.

Update: Since the code in the comment is user defined I have no way of knowing nor do I have any control over how the code in the comments is written. I don't want to force any restrictions on the user. Therefore I can expect very little.

¿Fue útil?

Solución 3

from what I have read there isn't a way to do this. Its just how javascript works. There is no way to call the foo function via a string. The foo function would have to be part of an object to call it with a string. I just wanted to confirm there aren't any clever ways around this.

Otros consejos

Try this approach:

angular.module('testApp').factory('testFactory', function () {
    var service = this;
    this.foo = function() {
        someData.amount = 5;
    }

    return {
        funcRunner: function (functionName) {
            service[functionName]();
        }
    };
});


function Ctrl($scope, testFactory) {
    $scope.click = function () {
        testFactory.funcRunner("foo");
    }
}

You can use the $parse to parse the string and call a function. Here's an example: http://jsfiddle.net/WeirdAlfred/Lsfwtb96/

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

//inject the $parse service into your controller, service, factory, etc.
app.controller('myController', ['$scope', '$parse', myController]);

function myController($scope, $parse) {
    //setup a function on scope that will receive the 
    //string that you wish to execute as a function.
    //Note: this function doesn't need to be on scope, it's just there so 
    //we can call it with button clicks.   This could be any function
    //on a controller, service, factory, etc.
    $scope.buttonClick = function (someStringValue, useAngularParse) {
        alert('The string value passed in from the button click:  ' + someStringValue);

        //the parse service takes a string and converts it to a function call
        //the format for the command is:
        //$parse(inputString)(objectOfAvailableFunctions, objectOfParams);
        $parse(someStringValue)(internalFunctions);
    }

    //this provides a list of available functions for the 
    //$parse to call when it evaluates the given string.
    var internalFunctions = {
        catsSuckEggs: catsSuckEggs,
        dogsRock: dogsRock
    }

    //some random function that you want to make available via a string
    function catsSuckEggs() {
        alert('My cat is worthless!');
    }

    //some other random function that you want to make available via a string 
    function dogsRock() {
        alert('I wish my wife would let me have a dog!');
    }
}

Here's some quick markup that enables the buttonClick and passes in the string.

<body ng-app="myApp">
    <div ng-controller="myController">
        <h2>Do you like Cats or Dogs?</h2>
        <button class="btn btn-danger" ng-click="buttonClick('catsSuckEggs()')">Cats</button>
        <button class="btn btn-success" ng-click="buttonClick('dogsRock()')">Dogs</button>
    </div>
</body>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top