2013-11-27 15 views
17

Tôi đang cố gắng theo dõi this SO answer explaining how to render a recursive JSON structure using a directive. Tuy nhiên, không giống như câu trả lời được cung cấp, dữ liệu của tôi là không phải được biết khi DOM được tải và Góc chạy lần đầu tiên.Cập nhật chỉ thị JS góc khi Dịch vụ thay đổi

Thay vào đó, dữ liệu của tôi được truy xuất từ ​​trường nhập HTML và được lưu trữ trong Dịch vụ góc (khi người dùng gửi biểu mẫu).

Làm cách nào để giữ Chỉ thị góc được cập nhật khi dữ liệu của Dịch vụ được sửa đổi?


Cập nhật để đáp ứng để trả lời

@musically_ut cung cấp một câu trả lời tuyệt vời đã giúp, nhưng tiết lộ một vấn đề liên quan, ngăn chặn một thực hiện (cập nhật tại đây).

Chỉ thị ám HTML chứa Angular {{expressions}} truy cập dữ liệu được lưu trữ trong $scope. Vì giải pháp ban đầu là $watch khi dịch vụ có sẵn dữ liệu. Làm cách nào tôi có thể đảm bảo dữ liệu 'mới' được thêm vào $scopetrước khi chỉ thị hiển thị?

Tổng quan về kiến ​​trúc và dòng chảy là:

  1. ControllerA -> Nhận đầu vào từ người dùng
  2. ControllerA -> Sử dụng dịch vụ để chuyển đổi dữ liệu
  3. ControllerB ->$watch cho những thay đổi trong dịch vụ
  4. Directive ->$watch cho cha nges trong dịch vụ
  5. ControllerB -> Thêm dữ liệu vào $scope
  6. Directive -> Màn hình chuyển đổi dữ liệu (từ dịch vụ) sử dụng chỉ

Vấn đề là giữa các bước 5 và 6. Chỉ thị hiển thị {{expressions}} trước khi ControllerB thêm dữ liệu vào $scope. Ngay cả khi điều này đã làm việc, nó cảm thấy cách quá phức tạp và 'hacky'.

Thực tế, để hồi quy, tôi đang sử dụng $watch trong ControllerB để nghe khi dữ liệu được chuyển đổi sẵn sàng trong một dịch vụ. Ngay cả điều này cũng cảm thấy một chút quá mức cần thiết (dịch vụ không thực hiện các cuộc gọi không đồng bộ).

+0

Tôi mới trong góc, và nhận được bài viết của bạn bằng cách tìm kiếm thông tin về xem thay đổi dịch vụ trong chỉ thị. Theo như tôi hiểu bạn pb (và theo những gì tôi đọc gần đây), bạn không nên 'thêm dữ liệu vào phạm vi' trong ** ControllerB ** của bạn, tốt hơn bạn nên báo cáo nó cho ** dịch vụ **, và nó sẽ được tự động báo cáo đến phạm vi ** controllerB **. Nhân tiện, bạn sẽ có thể theo dõi ** thay đổi ** dịch vụ trong chỉ thị ** của bạn (tôi có nghĩa là dễ dàng hơn là theo dõi phạm vi ** externalB ** controllerB **.) Nhưng có lẽ tôi đã sai. –

Trả lời

17

Bạn có thể tiêm dịch vụ trong khi xác định chỉ thị và sau đó thiết lập $watch trên dữ liệu.Vì vậy, trong trường hợp của bạn:

.directive('tree', function ($compile, myService) { 
    return { 
     // ... 
     link: function (scope, element, attrs) { 
      scope.$watch(function() { 
       return myService.getData(); 
      }, 
      function (newVal) { 
       if (typeof newVal !== 'undefined') { 
        // ... 
       } 
      } 
     }); 
    } 
}); 

này sẽ xem dữ liệu cho sự thay đổi và chạy mã mỗi lần thay đổi dữ liệu.


Tuy nhiên, nếu dữ liệu không thay đổi sau khi được thiết lập một lần, một cách tốt hơn (hiệu quả hơn) sẽ được trả lại một lời hứa từ dịch vụ ($http phương pháp trả về một lời hứa trực tiếp hoặc bạn có thể tạo một sử dụng dịch vụ $q) và sau đó thêm tính toán của bạn làm phần tiếp theo cho dữ liệu.

.directive('tree', function ($compile, myService) { 
    return { 
     // ... 
     link: function (scope, element, attrs) { 
      myService.getData().then(function (data) { 
       // ... 
      }, function (err) { 
       // Handle error 
      }); 
     } 
    } 
}); 
+1

Cảm ơn bạn. Tuy nhiên, vấn đề là biểu thức ** chỉ thị ** hiển thị ** mà sử dụng dữ liệu JSON trong phạm vi $. Mã cho ** chỉ thị của bạn ** chạy khi cập nhật ** dịch vụ **, nhưng điều gì sẽ xảy ra nếu nó chạy trước khi dữ liệu ** dịch vụ ** có thể được đặt trong phạm vi $? Điều này xảy ra vì dữ liệu của tôi được lấy từ ControllerA, nhưng các chỉ thị được trả về trong ControllerB. Tôi $ xem 'myService.getData()' trong ControllerB và đặt dữ liệu trong phạm vi $. Tuy nhiên, chỉ thị của tôi đang hiển thị trước khi ControllerB thêm dữ liệu được cập nhật vào phạm vi $. – Jack

0

Tôi đã viết một hàm ngắn cho phép bạn đặt dữ liệu trong đối tượng mà không thay thế. Bạn có thể sử dụng nó trong dịch vụ của bạn. Bằng cách này, bạn không cần phải sử dụng đồng hồ. Bạn có thể sử dụng vòng lặp thông thường của Angular. Ví dụ, xem đơn giản dịch vụ này điều khiển &:

Demo: JSFidde - http://jsfiddle.net/y09kx7f7/1/ với xét nghiệm khẳng định

Bộ điều khiển:

app.controller('dem',function($scope,me){ 
    $scope.user=me.user; // {name:'user name'} 
}) 

Bộ điều khiển sẽ được chnage tự động mà không cần đồng hồ mỗi lần tên người dùng đã thay đổi!

Dịch vụ

.factory('me',function($timeout){ 
    var obj={} 
    obj.user={name:'hello'} 
    $timeout(function(){ //Example of change the data 
     newUser={name:'israel'} 
     cloneInto(obj.user,newUser) 
    },1000) 
    return obj 
}) 

Chức năng cloneInto mà tôi viết:

// The function it is like a=b, 
// but keeping the object in his original memory position. 
function cloneInto(a,b){ 
    var i 
    for (i in a){ 
     if(typeof a[i]!='object') //For supporting deep-copy 
      delete a[i] 
    } 
    for (i in b){ 
     if (typeof b[i]=='object'){ 
      if(!a[i]) a[i]={} 
      cloneInto(a[i],b[i]) 
     } 
     else{ 
      a[i]=b[i] 
     } 
    } 
} 
Các vấn đề liên quan