AngularJs'de dinamik kapsam değişkenlerini ayarlama - kapsam. <some_string>


97

Bir routeParamveya bir yönerge özniteliğinden veya her neyse aldığım bir dizgim var ve buna göre kapsam üzerinde bir değişken oluşturmak istiyorum. Yani:

$scope.<the_string> = "something".

Ancak, dize bir veya daha fazla nokta içeriyorsa, onu bölmek ve aslında kapsamda "detaya inmek" istiyorum. Öyleyse 'foo.bar'olmalı $scope.foo.bar. Bu, basit sürümün çalışmayacağı anlamına gelir!

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

Bir dizgeye dayalı bir değişkeni okurken yaparak bu davranışı elde edebilirsiniz $scope.$eval(the_string), ancak bir değer atarken nasıl yapılır?

Yanıtlar:


174

Bulduğum çözüm $ parse kullanmak .

"Açısal ifadeyi bir işleve dönüştürür."

Herhangi birinin daha iyi bir cevabı varsa lütfen soruya yeni bir cevap ekleyin!

İşte örnek:

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

1
Yani bu çok güzel! Ancak (ve neredeyse her zaman bir tane vardır) Verilerimi yaymak için $ kapsam. $ Apply () alamıyorum. Bunu bir konsol günlüğünde görebiliyorum, ancak görünümüm yeni eklenen verileri göstermiyor ($ kapsamını gösterdiğim bir altbilgi çubuğum var) - Herhangi bir fikir?
william e schroeder

Kodu görmeden bilmek zor, ancak ilk tahminim altbilginin aynı kapsamda olmadığıdır. Altbilgi ng-controller = "YourController" ile öğenin dışındaysa, değişkenlerine erişimi olmayacaktır.
Erik Honn

3
Cevap için teşekkürler. Atamanın sadece ilkel türlerle değil, karmaşık nesnelerle de çalıştığını belirtmek isterim.
Patrick Salami

1
$ Scope. $ Apply neden gerekli?
sinθ

Aslında tam olarak hatırlamıyorum. Bence model.assign veri bağlamayı tetiklemiyor, bu nedenle yapmanız gereken her şeyi yaptıktan sonra manuel olarak başvurmanız gerekiyor. Deneyin ve kaldırmanın mümkün olup olmadığını görün (Angular'ın daha yeni sürümlerinde de değişmiş olabilir, bunun bir veya iki sürüm olduğunu düşünüyorum).
Erik Honn

20

Erik'in cevabını başlangıç ​​noktası olarak kullanmak. Benim için çalışan daha basit bir çözüm buldum.

Ng-tıklama işlevimde:

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

Bunu $ kapsam ile ve olmadan test ettim. $ Uygula. Onsuz doğru şekilde çalışır!


13
Bunun, sorunun ne hakkında olduğundan tamamen farklı bir şey olduğunu unutmayın. Sorunun amacı, bir dizeye dayalı olarak 1'den fazla derinliğe sahip dinamik bir kapsam değişkeni oluşturmaktır. Bu nedenle, "kapsam.yaşam anlamını" değil, "kapsam.yaşam. anlamını" oluşturmak için. $ Kapsam [the_string] kullanmak bunu yapmaz. Ve sizin özel durumunuz için,! Undefined'in javascripte gerçekten doğru olduğunu unutmayın, böylece tüm if ifadesini atlayabilir ve sadece $ kapsam [the_string] =! $ Kapsam [the_string]; yapabilirsiniz. Yine de kodu biraz karıştırabilir, bu yüzden gerçekten isteyeceğiniz bir şey olup olmadığından emin değilim.
Erik Honn

@ErikHonn, aslında, $ kapsam [life.meaning] = true benim için çalıştı!
Jesse P Francis

1
"Çalışır", ancak 1.6'da bir şey değişmedikçe, sorunun istediği şeyi yapmaz. $ Kapsam [life.meaning] = true yaparsanız, mülkün adı "life.meaning" olacaktır ve bizim istediğimiz bu değil. Anlam denen bir çocuk özelliği olan hayat denen bir mülk istiyoruz.
Erik Honn

13

Sonuçlardan dinamik açısal değişkenler oluşturun

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

ps. $ parse özniteliğini denetleyicinizin işlevine aktarmayı unutmayın


5

Lodash kullanmakta sorun yoksa, _.set () kullanarak istediğiniz şeyi tek satırda yapabilirsiniz:

_.set (nesne, yol, değer) Nesne üzerindeki yolun özellik değerini ayarlar. Yolun bir bölümü yoksa, oluşturulur.

https://lodash.com/docs#set

Yani örneğiniz basitçe şöyle olacaktır: _.set($scope, the_string, something);


4

Sadece verilen cevaplara eklemek için aşağıdakiler benim için çalıştı:

HTML:

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

$indexDöngü indeksi nerede .

Javascript (burada valueişleve aktarılan parametre ve $indexmevcut döngü dizininin değeri olacaktır ):

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

Bunun soruyla ilgisi yok, lütfen konu üzerinde kalın.
Erik Honn

Üzgünüz, dizeleri kullanarak dinamik değişkenler oluşturmaya yardımcı olabileceğini düşündüm. Bu iş parçacığı, benim için iyi çalışan yukarıdaki kodu yazmama yardımcı oldu.
Riaz

Endişeye gerek yok, yanıt vermek istemek iyi bir başlangıçtır, önce soruyu okuduğunuzdan emin olun :) Bu durumda, bilinmeyen bir "abc" dizesini nesneye {a: {b: {c: ...} ayrıştırmakla ilgilidir. }}. Ancak yinelenen öğeleri ele almak yaygın bir sorundur, bu nedenle ileti dizisinde sağlıklı bir şey bulduğunuza sevindim.
Erik Honn

Oh, ve başka bir cevapta belirttiğim gibi, eğer değerlerin sadece doğru / yanlış (veya tanımsız) olması gerekiyorsa, tüm mantığı atlayıp $ kapsam [değişken] ===! $ Kapsam [değişken], çünkü ! undefined, javascript'te doğrudur. Daktilo kullanıyorsanız, size kızacağından şüpheleniyorum!
Erik Honn

3

Lütfen aklınızda bulundurun: bu sadece bir JavaScript meselesidir ve Angular JS ile hiçbir ilgisi yoktur. Bu yüzden büyülü '$' işareti konusunda kafanız karışmasın;)

Asıl sorun, bunun hiyerarşik bir yapı olmasıdır.

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

Bu tanımsızdır çünkü "$ kapsam.life" mevcut değildir, ancak yukarıdaki terim "anlamı" çözmek ister.

Bir çözüm olmalı

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

veya biraz daha efford ile.

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 ']);

Yapısal bir nesneye erişebildiğiniz için

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

JavaScript ile eğlencede size iyi bir şekilde rehberlik edecek birkaç iyi öğretici var.

Hakkında bir şey var

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

Gidin ve web'de 'angular $ apply' için arama yapın ve $ apply işlevi hakkında bilgi bulacaksınız. Ve akıllıca bu şekilde kullanmanız gerekir (eğer bir $ apply aşamasıyla baş başa kalmazsanız).

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

3
Cevabınız için teşekkürler, ancak soru baştan beri bilinen "basit versiyonun" neden işe yaramadığı değildi. Soru, alternatifin ne olduğuydu. Korkarım iki öneriniz de işe yaramayacak, her ikisi de dizenin yapısını önceden bilmenizi gerektiriyor ve mesele dinamik olması (ve keyfi dizeleri işleyebilmesi). Çözüm için kabul edilen cevaba bakın.
Erik Honn

1
Ayrıca, hiçbir cevap sorunu çözmez. Birincisi, $ kapsam ['abc'] 'ye değil $ kapsam. soru, sadece gereksiz sözdizimi ile, ama belki bu bir yazım hatası mı? :)
Erik Honn

0

Aşağıdaki Lodash kitaplığını kullanıyorsanız, açısal kapsamda dinamik bir değişken ayarlamanın yoludur.

Açısal kapsamdaki değeri ayarlamak için.

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

Açısal kapsamdan değeri almak için.

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

-1

Yapmaya çalıştığınızı düşündüğüm şeyi yapmaya çalışıyorsanız, o zaman kapsamı yalnızca normal bir JS nesnesi gibi ele almanız gerekir.

JSON veri dizisi için API başarı yanıtı olarak kullandığım şey bu ...

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;
    });
}

Şimdi {{konular}} bir dizi veri konusu adı döndürecek ve benim örneğimde $ kapsamdan {{işler}}, {{müşteriler}}, {{personel}} vb. İçin bir kapsam özelliği olacaktır. işler, $ kapsam.customers, $ kapsam.staff


4
Cevap için teşekkürler ama bu aynı şey değil. Bu, $ kapsam.subject'i sabit kodlamadan bir dizeden $ kapsam.subject.name oluşturmakla ilgilidir. Bu, direktifin yeniden kullanılabilir olmasını istiyorsanız kapsam hakkında hiçbir şey varsaymamanız gereken bazı direktiflerle ilgilidir. Ayrıca, angular.forEach ()!
JQuery'nin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.