AngularJs에서 동적 범위 변수 설정-scope. <some_string>


97

나는 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)있지만 값을 할당 할 때 어떻게 수행합니까?

답변:


174

내가 찾은 해결책은 $ parse 를 사용하는 것 입니다.

"Angular 표현식을 함수로 변환합니다."

더 나은 사람이 있다면 질문에 새로운 답변을 추가하십시오!

다음은 그 예입니다.

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
그래서 이것은 아름답습니다! 그러나 (거의 항상 하나가 있습니다) $ scope. $ apply ()를 사용하여 데이터를 전파 할 수 없습니다. 콘솔 로그에서 볼 수 있지만보기에 새로 추가 된 데이터가 표시되지 않습니다 ($ scope를 표시하는 바닥 글 막대가 있음)-아이디어가 있습니까?
william e schroeder 2014 년

코드를 보지 않고는 알기 어렵지만 첫 번째 추측은 바닥 글이 동일한 범위에 있지 않다는 것입니다. 바닥 글이 ng-controller = "YourController"로 요소 외부에 있으면 해당 변수에 액세스 할 수 없습니다.
Erik Honn 2014 년

3
답변 해주셔서 감사합니다. 할당은 기본 유형뿐만 아니라 복잡한 객체에서도 작동한다는 점을 지적하고 싶습니다.
Patrick Salami

1
$ scope. $ apply가 필요한 이유는 무엇입니까?
sinθ

사실 기억이 나지 않습니다. model.assign은 데이터 바인딩을 트리거하지 않기 때문에 필요한 모든 작업을 수행 한 후에는 수동으로 적용해야합니다. 그것을 시도하고 그것을 제거하는 것이 가능한지 확인하십시오 (Angular의 최신 버전에서도 변경되었을 수 있습니다.
Erik Honn 2014

20

Erik의 대답을 시작점으로 사용합니다. 저에게 효과가있는 더 간단한 솔루션을 찾았습니다.

내 ng-click 기능에는 다음이 있습니다.

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

$ scope. $ apply를 사용하거나 사용하지 않고 테스트했습니다. 그것 없이는 올바르게 작동합니다!


13
이것은 질문의 내용과 완전히 다릅니다. 질문의 목표는 문자열을 기반으로 깊이가 2 개 이상인 동적 범위 변수를 만드는 것입니다. 따라서 "scope.lifeMeaning"이 아닌 "scope.life.meaning"을 만듭니다. $ scope [the_string]을 사용하면 그렇게되지 않습니다. 그리고 특정한 경우에,! undefined는 실제로 javascrip에서 참이라는 것을 기억하십시오. 따라서 실제로 전체 if 문을 건너 뛰고 $ scope [the_string] =! $ scope [the_string];을 수행 할 수 있습니다. 그래도 코드가 약간 혼란 스러울 수 있으므로 실제로 원하는 것인지 확실하지 않습니다.
Erik Honn

@ErikHonn, 실제로 $ scope [life.meaning] = true가 저에게 효과적이었습니다!
제시 P 프랜시스

1
"작동"하지만 1.6에서 변경되지 않는 한 질문에서 요구하는 것과 동일한 작업을 수행하지 않습니다. $ scope [life.meaning] = true를 수행하면 속성 이름은 "life.meaning"이되며 우리가 원하는 것은 아닙니다. 우리는 의미라는 자식 속성을 가진 생명이라는 속성을 원합니다.
에릭 Honn

13

결과에서 동적 각도 변수 생성

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

추신. $ parse 속성을 컨트롤러의 함수에 전달하는 것을 잊지 마십시오


5

Lodash를 사용해도 괜찮다면 _.set ()을 사용하여 한 줄에 원하는 것을 할 수 있습니다.

_.set (object, path, value) 객체의 경로 속성 값을 설정합니다. 경로의 일부가 존재하지 않으면 생성됩니다.

https://lodash.com/docs#set

따라서 귀하의 예는 다음과 같습니다. _.set($scope, the_string, something);


4

이미 주어진 답변에 추가하기 위해 다음이 저에게 효과적이었습니다.

HTML :

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

$index루프 인덱스는 어디에 있습니까 ?

자바 스크립트 (여기서는 value함수에 전달 된 매개 변수 $index이며 현재 루프 색인 의 값이됩니다 ) :

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

이것은 질문과 관련이 없습니다. 주제를 계속 유지하십시오.
에릭 Honn

죄송합니다. 문자열을 사용하여 동적 변수를 만드는 데 도움이 될 것이라고 생각했습니다. 이 스레드는 나를 위해 잘 작동하는 위의 코드를 작성하는 데 도움이되었습니다.
Riaz

걱정하지 마세요. 답변을 제공하려는 것이 좋은 시작입니다. 먼저 질문을 읽으십시오. :)이 경우 알 수없는 문자열 "abc"를 객체 {a : {b : {c : ...}로 구문 분석하는 것입니다. }}. 그러나 반복되는 항목을 처리하는 것은 일반적인 문제이므로 스레드에서 치유 된 것을 발견하여 다행입니다.
Erik Honn

아, 또 다른 답변에서 언급했듯이 값이 참 / 거짓 (또는 정의되지 않음)으로되어 있으면 전체 논리를 건너 뛰고 $ scope [variable] ===! $ scope [variable]를 수행 할 수 있습니다. ! undefined는 javascript에서 true입니다. typescript를 사용하고 있다면 화를 낼 것이라고 생각합니다!
Erik Honn

3

명심하세요 : 이것은 JavaScript 일 뿐이며 Angular JS와는 아무 관련이 없습니다. 따라서 마법의 '$'기호에 대해 혼동하지 마십시오.)

주요 문제는 이것이 계층 구조라는 것입니다.

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

"$ scope.life"는 존재하지 않지만 위의 용어는 "의미"를 해결하기를 원하기 때문에 정의되지 않았습니다.

해결책은

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

또는 조금 더 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 ']);

다음을 사용하여 구조적 객체에 액세스 할 수 있으므로

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

이것에 대한 몇 가지 좋은 튜토리얼이 있습니다.이 튜토리얼은 JavaScript의 재미를 잘 안내합니다.

에 대해 뭔가가

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

웹에서 'angular $ apply'를 검색하면 $ apply 기능에 대한 정보를 찾을 수 있습니다. 그리고 당신은 더 현명하게 사용해야합니다 ($ apply 단계가없는 경우).

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

3
대답 해 주셔서 감사합니다. 그러나 질문은 처음부터 알려진 "단순 버전"이 작동하지 않는 이유가 아닙니다. 문제는 대안이 무엇인지였습니다. 두 가지 제안 중 어느 것도 작동하지 않을까 두렵습니다. 둘 다 문자열의 구조를 미리 알아야하며, 요점은 동적이어야하며 임의의 문자열을 처리 할 수 ​​있어야한다는 것입니다. 해결책에 대한 답변을 참조하십시오.
에릭 Honn

1
또한 어떤 답변도 실제로 문제를 해결하지 못합니다. 첫 번째는 $ scope [ 'abc']가 아닌 $ scope.abc에 할당해야하는 기본 전제 조건을 실패하고, 두 번째도 실패하고 문자 그대로 "단순 버전"의 "단순 버전"과 동일한 결과를 가져옵니다. 불필요한 구문으로 질문하지만 아마도 오타입니까? :)
에릭 Honn

0

아래 Lodash 라이브러리를 사용하는 경우 각도 범위에서 동적 변수를 설정하는 방법이 있습니다.

각도 범위에서 값을 설정합니다.

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

각도 범위에서 값을 가져옵니다.

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

-1

하려는 작업을 수행하려는 경우 범위를 일반 JS 개체처럼 취급하면됩니다.

이것은 JSON 데이터 배열에 대한 API 성공 응답에 사용하는 것입니다.

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

이제 {{subjects}}는 데이터 주체 이름의 배열을 반환하며,이 예에서는 $ scope의 {{jobs}}, {{customers}}, {{staff}} 등에 대한 범위 속성이 있습니다. jobs, $ scope.customers, $ scope.staff


4
대답 해 주셔서 감사합니다. 그러나 그것은 같은 것이 아닙니다. $ scope.subject를 하드 코딩하지 않고 문자열에서 $ scope.subject.name을 만드는 것입니다. 이는 지시문을 재사용 할 수 있도록하려는 경우 범위에 대해 아무 것도 가정해서는 안되는 일부 지시문과 관련이 있습니다. 또한 angular.forEach ()! jQuery를이 각도 사용하는 방법으로 얻을하지 마십시오 : P를
에릭 Honn에게
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.