2014-10-24 35 views
5

Trong chỉ thị tùy chỉnh của tôi, tôi đang thêm các phần tử vào DOM dựa trên số đối tượng trong mảng nguồn dữ liệu của tôi. Tôi cần phải xem một tài sản cụ thể trong từng đối tượng. Khi tôi thêm các phần tử này vào DOM, tôi muốn thiết lập một đồng hồ $ trên thuộc tính checked của từng đối tượng trong mảng toppings, nhưng nó không hoạt động và tôi không biết tại sao. Tôi thiết lập một điểm ngắt bên trong hàm cần được gọi khi thuộc tính thay đổi từ true thành false hoặc false thành true, nhưng hàm đó không bao giờ được gọi. Lý do có rõ ràng không? Tôi chỉ học Angular, vì vậy tôi có thể dễ dàng tạo ra một lỗi ngu ngốc.AngularJS: xem một thuộc tính cụ thể trong một mảng các đối tượng cho các thay đổi trong giá trị của tài sản

$scope.bits = 66; (i.e. onions and olives) 


$scope.toppings = [ 
    { topping: 1, bits: 2, name: 'onions' }, 
    { topping: 2, bits: 4, name: 'mushrooms' }, 
    { topping: 3, bits: 8, name: 'peppers' }, 
    { topping: 4, bits: 16, name: 'anchovies' }, 
    { topping: 5, bits: 32, name: 'artichokes' }, 
    { topping: 6, bits: 64, name: 'olives' }, 
    { topping: 7, bits: 128, name: 'sausage' }, 
    { topping: 8, bits: 256, name: 'pepperoni' } 
    ] 

Mỗi đối tượng trong mô hình sẽ có thuộc tính mới hoặc đúng là checked.

LƯU Ý: mảng đối tượng sẽ chứa nhiều nhất một tá mục. Hiệu suất không phải là một mối quan tâm.

link: function link(scope, iElement, iAttrs, controller, transcludeFn) { 


    <snip> 

// At this point scope.model refers to $scope.toppings. Confirmed. 

    angular.forEach(scope.model, function (value, key) { 

    // bitwise: set checked to true|false based on scope.bits and topping.bits 

    scope.model[key].checked = ((value.bits & scope.bits) > 0); 


    scope.$watch(scope.model[key].checked, function() { 
     var totlBits = 0; 
     for (var i = 0; i < scope.model.length; i++) { 
      if (scope.model[i].checked) totlBits += scope.model[i].bits; 
     } 
      scope.bits = totlBits; 
     }); 

    }); 

    <snip> 

Trả lời

1

Tham số watchExpression đến $ phạm vi. $ Đồng hồ hoặc phải là một chuỗi hoặc một hàm. Tôi đã không thử nghiệm rộng rãi với điều này (tôi cố gắng và tránh đồng hồ rõ ràng nếu có thể) nhưng tôi nghĩ rằng nó cũng làm việc khi bạn xem 'đơn giản' thuộc tính phạm vi như tài liệu tham khảo đối tượng, nhưng không phải là rất tốt với sự tham khảo phức tạp hơn.

Tôi nghĩ nếu bạn cung cấp tham chiếu dưới dạng chuỗi, ví dụ: 'model [' + key + '] .check' sau đó bạn có thể có một số thành công (tôi chỉ nói điều này bởi vì tôi đã thực hiện một cái gì đó tương tự với $ watchCollection trước đây).

Hoặc bạn có thể cung cấp chức năng, ví dụ:

$scope.$watch(function() { return scope.model[key].checked; }, function() { ... });

Hy vọng điều này sẽ hữu ích!

+0

Cách tiếp cận chức năng hoạt động. Cảm ơn! – Tim

+0

Nhược điểm của phương pháp này là bạn đang tạo một trình theo dõi cho mỗi khóa trên đối tượng. $ WatchCollection hoạt động hiệu quả hơn. –

+1

@William Lepinski: Bạn có thể giải thích lý do tại sao một watchCollection trên mảng, trong đó có để xem mọi tài sản trên mỗi mục, sẽ thực hiện tốt hơn so với một chiếc đồng hồ trên chỉ tài sản mà tôi cần phải được theo dõi? Tôi không đồng ý, tôi chỉ muốn biết làm thế nào được thực hiện. Làm thế nào là một chiếc đồng hồ sâu được thực hiện? – Tim

0

Sử dụng $watchCollection để thay thế.

Từ tài liệu:

$ watchCollection (obj, listener); Nông đồng hồ các thuộc tính của một đối tượng và cháy bất cứ khi nào bất kỳ thuộc tính nào thay đổi (đối với mảng, điều này ngụ ý xem các mục mảng; đối với bản đồ đối tượng, điều này ngụ ý xem các thuộc tính). Nếu phát hiện thay đổi, cuộc gọi lại của người nghe sẽ được kích hoạt.

Bộ sưu tập obj được quan sát qua hoạt động $ đồng hồ tiêu chuẩn và được kiểm tra trên tất cả các cuộc gọi đến $ tiêu hóa() để xem nếu bất kỳ mục đã được thêm, xóa hoặc di chuyển. Người nghe được gọi bất cứ khi nào bất cứ điều gì trong obj đã thay đổi. Ví dụ bao gồm thêm, xóa và di chuyển các mục thuộc về một đối tượng hoặc mảng.

+1

nhưng nó sẽ giám sát mọi thuộc tính của một bộ sưu tập. không chỉ là một tài sản duy nhất. Trong trường hợp này, OP muốn chỉ xem thuộc tính 'checked'. – harishr

+0

Vâng, bạn có thể nhổ mảng của bạn grabbing chỉ kiểm tra tài sản. Gán mảng mới được tạo này cho phạm vi và sử dụng $ watchCollection để xem qua mảng các thuộc tính đã chọn. –

2

mảng các đối tượng:

$scope.toppings = [ 
    { topping: 1, bits: 2, name: 'onions' }, 
    { topping: 2, bits: 4, name: 'mushrooms' }, 
    { topping: 3, bits: 8, name: 'peppers', checked:undefined /*may be*/ } 
]; 

Xem bằng AngularJs $ WatchCollection:

Thay vì theo dõi objects mảng trên, có thể thay đổi cho bất cứ tài sản trong đối tượng, chúng tôi sẽ tạo ra một mảng các thuộc tính của các phần tử mà chúng tôi đang xem bộ sưu tập (.checked).

Chúng tôi filter các phần tử của mảng để chỉ giám sát các yếu tố đó có .checked được xác định và map đối với mảng cho góc watchCollection.

Khi thay đổi kích hoạt, tôi sẽ so sánh các mảng cũ và mới (.checked) để lấy yếu tố thay đổi chính xác bằng phương pháp lodash difference.

$scope.$watchCollection(
       //Watch Function 
       ()=>($scope.toppings.filter(tp=>tp.checked!=undefined).map(tp=>tp.checked)), 

       //Listner 
       (nv,ov)=>{ 
       if(nv==ov||nv=="undefined")return; 

       //Use lodash library to get the changed obj 
       let changedTop= _.difference(nv,ov)[0]; 

       //Here you go.. 
       console.log("changed Topping",changedTop); 
      }) 
+1

Đây là một trong những câu trả lời tốt hơn trong của tôi ý kiến, và nó hoạt động tốt hơn cho mảng, tuy nhiên vì lợi ích của tác giả câu hỏi và bất kỳ ai tìm kiếm trợ giúp về vấn đề này, bạn nên thêm chi tiết vào câu trả lời của mình để giải thích rằng bạn đang sử dụng kịch bản kiểu và giải thích lý do của bạn để lọc và ánh xạ mảng. Nếu không, một giải pháp tuyệt vời. – Squall

+0

Đây không phải là TypeScript nhưng Javascript ES6 :-). Đã chỉnh sửa vì lý do áp dụng bộ lọc. – ahmadalibaloch

+0

Tôi nghĩ rằng điều này chỉ làm việc trong trường hợp rất đặc biệt (điều đó xảy ra là của OP, như họ đã đề cập trong một nhận xét) rằng tài sản theo dõi không có nhiều hơn hai tiểu bang. –

1

Bạn sử dụng MAP để thu thập tất cả các giá trị tài sản mà bạn cần + chuyển đổi chúng thành một chuỗi đại diện nhỏ (trong trường hợp này 1 và 0) và sau đó tham gia cùng họ với nhau thành một chuỗi có thể được quan sát thấy.

Một ví dụ nguyên cảo:

 $scope.$watch(
      () => this.someArray.map(x => x.selected ? "1" : "0").join(""), 
      (newValue, oldValue, scope) => this.onSelectionChanged(this.getSelectedItems())); 
+1

Tôi nghi ngờ điều này có hiệu quả hơn một chút so với lần đầu tiên thực hiện một 'bộ lọc' và sau đó là một' bản đồ' như trong câu trả lời khác của @ahmadalibaloch –

Các vấn đề liên quan