在 AngularJs-scope 中设置动态范围变量。 < some_string >

我有一个字符串,我已经从 routeParam或指令属性或任何东西,我想创建一个变量的范围基于此。所以:

$scope.<the_string> = "something".

但是,如果字符串包含一个或多个点,我希望将其分割,并实际“向下钻取”到作用域中。所以 'foo.bar'应该变成 $scope.foo.bar。这意味着简单的版本不会工作!

// This will not work as assigning variables like this will not "drill down"
// It will assign to a variables named the exact string, dots and all.
var the_string = 'life.meaning';
$scope[the_string] = 42;
console.log($scope.life.meaning);  // <-- Nope! This is undefined.
console.log($scope['life.meaning']);  // <-- It is in here instead!

当读取基于字符串的变量时,您可以通过执行 $scope.$eval(the_string)来获得这种行为,但是在赋值时如何执行呢?

125577 次浏览

The solution I have found is to use $parse.

"Converts Angular expression into a function."

If anyone has a better one please add a new answer to the question!

Here is the example:

var the_string = 'life.meaning';


// Get the model
var model = $parse(the_string);


// Assigns a value to it
model.assign($scope, 42);


// Apply it to the scope
// $scope.$apply(); <- According to comments, this is no longer needed


console.log($scope.life.meaning);  // logs 42

If you were trying to do what I imagine you were trying to do, then you only have to treat scope like a regular JS object.

This is what I use for an API success response for JSON data array...

function(data){


$scope.subjects = [];


$.each(data, function(i,subject){
//Store array of data types
$scope.subjects.push(subject.name);


//Split data in to arrays
$scope[subject.name] = subject.data;
});
}

Now \{\{subjects}} will return an array of data subject names, and in my example there would be a scope attribute for \{\{jobs}}, \{\{customers}}, \{\{staff}}, etc. from $scope.jobs, $scope.customers, $scope.staff

Please keep in mind: this is just a JavaScript thing and has nothing to do with Angular JS. So don't be confused about the magical '$' sign ;)

The main problem is that this is an hierarchical structure.

console.log($scope.life.meaning);  // <-- Nope! This is undefined.
=> a.b.c

This is undefined because "$scope.life" is not existing but the term above want to solve "meaning".

A solution should be

var the_string = 'lifeMeaning';
$scope[the_string] = 42;
console.log($scope.lifeMeaning);
console.log($scope['lifeMeaning']);

or with a little more efford.

var the_string_level_one = 'life';
var the_string_level_two = the_string_level_one + '.meaning';
$scope[the_string_level_two ] = 42;
console.log($scope.life.meaning);
console.log($scope['the_string_level_two ']);

Since you can access a structural objecte with

var a = {};
a.b = "ab";
console.log(a.b === a['b']);

There are several good tutorials about this which guide you well through the fun with JavaScript.

There is something about the

$scope.$apply();
do...somthing...bla...bla

Go and search the web for 'angular $apply' and you will find information about the $apply function. And you should use is wisely more this way (if you are not alreay with a $apply phase).

$scope.$apply(function (){
do...somthing...bla...bla
})

Create Dynamic angular variables from results

angular.forEach(results, function (value, key) {
if (key != null) {
$parse(key).assign($scope, value);
}
});

ps. don't forget to pass in the $parse attribute into your controller's function

Using Erik's answer, as a starting point. I found a simpler solution that worked for me.

In my ng-click function I have:

var the_string = 'lifeMeaning';
if ($scope[the_string] === undefined) {
//Valid in my application for first usage
$scope[the_string] = true;
} else {
$scope[the_string] = !$scope[the_string];
}
//$scope.$apply

I've tested it with and without $scope.$apply. Works correctly without it!

If you are ok with using Lodash, you can do the thing you wanted in one line using _.set():

_.set(object, path, value) Sets the property value of path on object. If a portion of path does not exist it’s created.

https://lodash.com/docs#set

So your example would simply be: _.set($scope, the_string, something);

Just to add into alread given answers, the following worked for me:

HTML:

<div id="div\{\{$index+1}}" data-ng-show="val\{\{$index}}">

Where $index is the loop index.

Javascript (where value is the passed parameter to the function and it will be the value of $index, current loop index):

var variable = "val"+value;
if ($scope[variable] === undefined)
{
$scope[variable] = true;
}else {
$scope[variable] = !$scope[variable];
}

If you are using Lodash library below is the way to set a dynamic variable in the angular scope.

To set the value in the angular scope.

_.set($scope, the_string, 'life.meaning')

To get the value from the angular scope.

_.get($scope, 'life.meaning')