web-dev-qa-db-fra.com

Définition de variables de portée dynamiques dans AngularJs - scope. <Chaîne_cache>

J'ai une chaîne que j'ai obtenue à partir d'un routeParam ou d'un attribut de directive, etc. Alors: 

$scope.<the_string> = "something".

Cependant, si la chaîne contient un ou plusieurs points, je souhaite la scinder et "explorer" en détail la portée. Donc, 'foo.bar' devrait devenir $scope.foo.bar. Cela signifie que la version simple ne fonctionnera pas!

// 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!

Lors de la lecture d'une variable basée sur une chaîne, vous pouvez obtenir ce comportement en effectuant $scope.$eval(the_string), mais comment procéder lors de l'affectation d'une valeur?

92
Erik Honn

La solution que j'ai trouvée consiste à utiliser $ parse .

"Convertit l'expression angulaire en une fonction."

Si quelqu'un en a un meilleur, veuillez ajouter une nouvelle réponse à la question!

Voici l'exemple:

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
168
Erik Honn

Utiliser la réponse d'Erik comme point de départ. J'ai trouvé une solution plus simple qui a fonctionné pour moi.

Dans ma fonction ng-click, j'ai: 

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

Je l’ai testé avec et sans $ scope. $ S’applique. Fonctionne correctement sans ça! 

17
Andrew Gray

Créer des variables angulaires dynamiques à partir des résultats

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

ps. n'oubliez pas de transmettre l'attribut $ parse dans la fonction de votre contrôleur

13
Demodave

Si vous êtes d'accord avec Lodash, vous pouvez faire ce que vous voulez en une ligne avec _.set ()

_.set (objet, chemin, valeur) Définit la valeur de la propriété chemin sur objet. Si une partie du chemin n’existe pas, elle est créée.

https://lodash.com/docs#set

Donc, votre exemple serait simplement: _.set($scope, the_string, something);

5
NorthernStar

Pour ajouter des réponses déjà données, les éléments suivants ont fonctionné pour moi:

HTML:

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

$index est l'index de la boucle.

Javascript (où value est le paramètre passé à la fonction et sera la valeur de $index, index de boucle en cours):

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

S'il vous plaît gardez à l'esprit: ceci est juste une chose en JavaScript et n'a rien à voir avec Angular JS. Alors ne soyez pas confus à propos du signe '$' magique;)

Le problème principal est qu'il s'agit d'une structure hiérarchique. 

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

Ceci n'est pas défini car "$ scope.life" n'existe pas, mais le terme ci-dessus veut résoudre "le sens".

Une solution devrait être

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

ou avec un peu plus d'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 ']);

Puisque vous pouvez accéder à un objet structurel avec

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

Il existe plusieurs bons tutoriels à ce sujet qui vous guideront à travers le plaisir avec JavaScript.

Il y a quelque chose à propos du

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

Allez sur le Web pour rechercher 'angular $ apply' et vous obtiendrez des informations sur la fonction $ apply. Et vous devriez utiliser sagement davantage de cette façon (si vous n’êtes pas déjà en phase $ apply).

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

Si vous utilisez la bibliothèque Lodash ci-dessous, vous pouvez définir une variable dynamique dans la portée angulaire.

Pour définir la valeur dans la portée angulaire.

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

Pour obtenir la valeur de la portée angulaire.

_.get($scope, 'life.meaning')
0
Sagar Vaghela