angularjs에서 배열을 자세히 보는 방법은 무엇입니까?


320

내 범위에는 객체 배열이 있으며 각 객체의 모든 값을보고 싶습니다.

이것은 내 코드입니다.

function TodoCtrl($scope) {
  $scope.columns = [
      { field:'title', displayName: 'TITLE'},
      { field: 'content', displayName: 'CONTENT' }
  ];
   $scope.$watch('columns', function(newVal) {
       alert('columns changed');
   });
}

내가 값, 예를 들어 나는 변화를 수정할 때 TITLE까지을 TITLE2alert('columns changed')튀어하지 않습니다.

배열 내부의 객체를 자세히 보는 방법은 무엇입니까?

라이브 데모가 있습니다 : http://jsfiddle.net/SYx9b/

답변:


529

당신의 세번째 인수 설정할 수 있습니다 $watch로를 true:

$scope.$watch('data', function (newVal, oldVal) { /*...*/ }, true);

https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch를 참조 하십시오.

Angular 1.1.x부터 $ watchCollection을 사용하여 컬렉션의 얕은 시계 ( "첫 번째 수준")를 볼 수도 있습니다.

$scope.$watchCollection('data', function (newVal, oldVal) { /*...*/ });

https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchCollection을 참조 하십시오.


2
angular.equals세 번째 인수가 부울 값 을 가질 때 왜 사용 합니까?
JayQuerie.com

Trevor에게 감사의 말을 전합니다. 위의 코드를 업데이트하고 일치하도록 코드를 업데이트했습니다.
Piran

36
1.1.x에서 당신은 지금$watchCollection
Jonathan Rowny

39
$watchCollection내가 이해하는 것처럼 배열이나 객체의 "첫 번째 수준"만 볼 것입니다. 그것보다 더 깊이 볼 필요가 있다면 위의 대답은 맞습니다. bennadel.com/blog/…
Blazemonger

1
큰 대답 ... 내가 할 수 있다면 당신에게 하나 이상의 투표권을 주었을 것입니다 ... :) 감사합니다
Jony-Y

50

$ watch에 객체를 딥 다이빙하면 성능이 저하됩니다. 때때로 (예를 들어, 변경 사항이 푸시 및 팝만 가능한 경우) array.length와 같이 쉽게 계산 된 값을 $ watch 할 수 있습니다.


1
투표권이 더 있어야합니다. 깊은 관찰은 비싸다. OP가 심층 관찰을 찾고 있었지만 사람들은 배열 자체가 변경되었는지 알고 싶어 할 수도 있습니다. 이 경우 길이를 보는 것이 훨씬 빠릅니다.
Scott Silvi

42
이것은 답변이 아닌 의견이어야합니다.
Blazemonger

1
@Blazemonger 주석 ( stackoverflow.com/questions/14712089#comment32440226_14713978 )에서 언급 한 것처럼 $ watchCollection을 사용하면 성능 문제가 최소화됩니다 .
Sean the Bean

깔끔한 조언. 이 의견이 답이 아닌 것에 관해서는, 내 의견으로는 대답의 수용 기준을 충족시키기 위해 제안을 정교하게하는 것이 좋습니다. 이 접근법을 사용하면 문제에 대한 우아한 해결책을 얻을 수 있다고 생각합니다.
에이미 펠레그리니

43

하나의 배열 만 보려는 경우이 코드를 간단히 사용할 수 있습니다.

$scope.$watch('columns', function() {
  // some value in the array has changed 
}, true); // watching properties

그러나 이것은 여러 배열에서 작동하지 않습니다.

$scope.$watch('columns + ANOTHER_ARRAY', function() {
  // will never be called when things change in columns or ANOTHER_ARRAY
}, true);

이 상황을 처리하기 위해 일반적으로보고 싶은 여러 배열을 JSON으로 변환합니다.

$scope.$watch(function() { 
  return angular.toJson([$scope.columns, $scope.ANOTHER_ARRAY, ... ]); 
},
function() {
  // some value in some array has changed
}

@jssebastian이 주석에서 지적했듯이 '$'로 시작하는 멤버 및 다른 경우도 처리 할 JSON.stringify수 있으므로 바람직 angular.toJson할 수 있습니다.


또한에 세 번째 매개 변수 $watch가 있습니다. 동일한 작업을 수행 할 수 있습니까? Pass true as a third argument to watch an object's properties too.참조 : cheatography.com/proloser/cheat-sheets/angularjs
Freewind

@Freewind 여러 배열을보아야 할 경우가 있으면 여기에 표시된 대로 실패 합니다 . 그러나 그렇습니다. 작동 angular.toJson하며 단일 배열에서 사용하는 것과 동일한 기능을 제공합니다 .
JayQuerie.com

2
angular.toJson에 '$'로 시작하는 멤버를 포함하지 않는 것 같습니다. angular.toJson ({ "$ hello": "world"})은 "{}"입니다. 대안으로 JSON.stringify ()를 사용했습니다
jssebastian

@ jssebastian 감사합니다-해당 정보를 포함하도록 답변을 업데이트했습니다.
JayQuerie.com 2016 년

1
어떤 속성이 바뀌 었는지 알 수 있습니까?
Ashwin

21

Angular 1.1.x 이상에서는 이제 $ watch 대신 $ watchCollection을 사용할 수 있습니다 . $ watchCollection은 얕은 시계를 만드는 것처럼 보이지만 예상대로 객체 배열에서 작동하지 않습니다. 배열에 대한 추가 및 삭제를 감지 할 수 있지만 배열 내의 객체 속성은 감지 할 수 없습니다.


5
그러나 $ watchCollection은 얕게 만 감시합니다. 내가 이해 한 것처럼 (질문에서와 같이) 배열 항목의 속성을 변경해도 이벤트가 트리거되지 않습니다.
Tarnschaf

3
이것은 답변이 아닌 의견이어야합니다.
Blazemonger

18

다음은 예제를 사용하여 범위 변수를 볼 수있는 3 가지 방법을 비교 한 것입니다.

$ watch () 는 다음에 의해 트리거됩니다.

$scope.myArray = [];
$scope.myArray = null;
$scope.myArray = someOtherArray;

$ watchCollection () 은 AND 이상의 모든 항목에 의해 트리거됩니다.

$scope.myArray.push({}); // add element
$scope.myArray.splice(0, 1); // remove element
$scope.myArray[0] = {}; // assign index to different value

$ watch (..., true) 는 AND 위의 모든 항목에 의해 트리거됩니다.

$scope.myArray[0].someProperty = "someValue";

한 가지 더...

$ watch () 는 다른 배열의 내용이 동일하더라도 배열을 다른 배열로 바꿀 때 트리거하는 유일한 것입니다.

예를 들어, 다음과 같은 경우에 $watch()발생합니다 $watchCollection().

$scope.myArray = ["Apples", "Bananas", "Orange" ];

var newArray = [];
newArray.push("Apples");
newArray.push("Bananas");
newArray.push("Orange");

$scope.myArray = newArray;

아래는 모든 다른 시계 조합을 사용하고 트리거 된 "시계"를 나타내는 로그 메시지를 출력하는 예제 JSFiddle에 대한 링크입니다.

http://jsfiddle.net/luisperezphd/2zj9k872/


정확하게, especailly는 '더 많은 것'에 주목
Andy Ma

12

$ watchCollection은 원하는 것을 수행합니다. 아래는 angularjs 웹 사이트 ( http://docs.angularjs.org/api/ng/type/$rootScope.Scope) 에서 복사 한 예입니다. 편리하지만 특히 대규모 컬렉션을 볼 때 성능을 고려해야합니다.

  $scope.names = ['igor', 'matias', 'misko', 'james'];
  $scope.dataCount = 4;

  $scope.$watchCollection('names', function(newNames, oldNames) {
     $scope.dataCount = newNames.length;
  });

  expect($scope.dataCount).toEqual(4);
  $scope.$digest();

  //still at 4 ... no changes
  expect($scope.dataCount).toEqual(4);

  $scope.names.pop();
  $scope.$digest();

  //now there's been a change
  expect($scope.dataCount).toEqual(3);

14
OP는 객체 배열을 지정했습니다. 이 예제는 문자열 배열에서 작동하지만 $ watchCollection은 개체 배열에서 작동하지 않습니다.
KevinL

4

이 솔루션은 저에게 매우 효과적이었습니다. 지시서 에서이 작업을 수행하고 있습니다.

scope. $ watch (attrs.testWatch, function () {.....}, true);

true는 꽤 잘 작동하며 모든 chnages에 반응합니다 (필드 추가, 삭제 또는 수정).

여기에 작동하는 플런저가 있습니다.

AngularJS에서 배열을 깊이 관찰

이것이 당신에게 도움이되기를 바랍니다. 질문이 있으시면 언제든지 문의하십시오.)


4

필자의 경우 여러 다른 컨트롤러가 감시하는 주소 개체가 포함 된 서비스를 감시해야했습니다. 'true'매개 변수를 추가 할 때까지 루프에 갇혔습니다.이 매개 변수는 객체를 볼 때 성공의 열쇠 인 것 같습니다.

$scope.$watch(function() {
    return LocationService.getAddress();
}, function(address) {
    //handle address object
}, true);

1

함수 의 objectEquality매개 변수 (세번째 매개 변수)를 설정하는 $watch것은 배열의 모든 속성을 보는 올바른 방법입니다.

$scope.$watch('columns', function(newVal) {
    alert('columns changed');
},true); // <- Right here

Piran 은 이것에 충분히 대답하고 언급 $watchCollection합니다.

자세한 세부 사항

내가 이미 대답 한 질문에 대답하는 이유는 wizardwerdna 의 대답이 좋은 것이 아니며 사용해서는 안된다는 것을 지적하고 싶기 때문 입니다.

문제는 다이제스트가 즉시 발생하지 않는다는 것입니다. 실행하기 전에 현재 코드 블록이 완료 될 때까지 기다려야합니다. 따라서 length어레이의 시계 가 실제로 $watchCollection포착 해야 할 중요한 변경 사항을 놓칠 수 있습니다 .

이 구성을 가정하십시오.

$scope.testArray = [
    {val:1},
    {val:2}
];

$scope.$watch('testArray.length', function(newLength, oldLength) {
    console.log('length changed: ', oldLength, ' -> ', newLength);
});

$scope.$watchCollection('testArray', function(newArray) {
    console.log('testArray changed');
});

언뜻보기 에이 경우와 같이 동시에 실행되는 것처럼 보일 수 있습니다.

function pushToArray() {
    $scope.testArray.push({val:3});
}
pushToArray();

// Console output
// length changed: 2 -> 3
// testArray changed

그것은 잘 작동하지만 이것을 고려하십시오 :

function spliceArray() {
    // Starting at index 1, remove 1 item, then push {val: 3}.
    $testArray.splice(1, 1, {val: 3});
}
spliceArray();

// Console output
// testArray changed

배열이 그래서 같이 시계와 같은 새로운 요소를 가지고 요소를 잃었지만 결과 길이가 동일하더라도이었다 공지 것을 $watch우려, length변경되지 않았습니다. $watchCollection그래도 집어 들었다.

function pushPopArray() {
    $testArray.push({val: 3});
    $testArray.pop();
}
pushPopArray();

// Console output
// testArray change

동일한 블록에서 푸시 및 팝으로 동일한 결과가 발생합니다.

결론

배열의 모든 속성을 보려면 $watch세 번째 매개 변수 (objectEquality)를 포함하고 true로 설정 한 배열 자체를 사용하십시오. 예, 이것은 비싸지 만 때로는 필요합니다.

객체가 배열에 들어오고 나가는 시점을 보려면 a를 사용하십시오 $watchCollection.

배열 $watchlength속성에 a 를 사용하지 마십시오 . 그렇게 생각할만한 이유는 거의 없습니다.


0

$scope.changePass = function(data){
    
    if(data.txtNewConfirmPassword !== data.txtNewPassword){
        $scope.confirmStatus = true;
    }else{
        $scope.confirmStatus = false;
    }
};
  <form class="list" name="myForm">
      <label class="item item-input">        
        <input type="password" placeholder="ใส่รหัสผ่านปัจจุบัน" ng-model="data.txtCurrentPassword" maxlength="5" required>
      </label>
      <label class="item item-input">
        <input type="password" placeholder="ใส่รหัสผ่านใหม่" ng-model="data.txtNewPassword" maxlength="5" ng-minlength="5" name="checknawPassword" ng-change="changePass(data)" required>
      </label>
      <label class="item item-input">
        <input type="password" placeholder="ใส่รหัสผ่านใหม่ให้ตรงกัน" ng-model="data.txtNewConfirmPassword" maxlength="5" ng-minlength="5" name="checkConfirmPassword" ng-change="changePass(data)" required>
      </label>      
       <div class="spacer" style="width: 300px; height: 5px;"></div> 
      <span style="color:red" ng-show="myForm.checknawPassword.$error.minlength || myForm.checkConfirmPassword.$error.minlength">รหัสผ่านต้องมีจำนวน 5 หลัก</span><br>
      <span ng-show="confirmStatus" style="color:red">รหัสผ่านใหม่ไม่ตรงกัน</span>
      <br>
      <button class="button button-positive  button-block" ng-click="saveChangePass(data)" ng-disabled="myForm.$invalid || confirmStatus">เปลี่ยน</button>
    </form>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.